This commit is contained in:
rizky 2024-04-09 00:32:10 -07:00
parent 121ec5f0ed
commit 1e2754ec9b
8 changed files with 125 additions and 21 deletions

View File

@ -1,5 +1,5 @@
import { useLocal } from "@/utils/use-local";
import { FC } from "react";
import { FC, useEffect } from "react";
import { FMInternal, FMProps } from "./typings";
import { formReload } from "./utils/reload";
import { formInit } from "./utils/init";
@ -9,11 +9,12 @@ import { Toaster } from "sonner";
export const Form: FC<FMProps> = (props) => {
const { PassProp, body } = props;
const fm = useLocal<FMInternal>({
data: "",
data: {},
status: "init",
reload: async () => {
formReload(fm);
},
submit: null as any,
error: {} as any,
internal: {
reload: {
@ -25,9 +26,12 @@ export const Form: FC<FMProps> = (props) => {
props: {} as any,
});
if (fm.status === "init") {
formInit(fm, props);
}
useEffect(() => {
if (fm.status === "init") {
formInit(fm, props);
fm.reload();
}
}, []);
if (document.getElementsByClassName("prasi-toaster").length === 0) {
const elemDiv = document.createElement("div");
@ -39,7 +43,7 @@ export const Form: FC<FMProps> = (props) => {
return (
<>
{toaster_el && createPortal(<Toaster cn={cx} />, toaster_el)}
<PassProp>{body}</PassProp>
{fm.status !== "init" && <PassProp fm={fm}>{body}</PassProp>}
</>
);
};

6
comps/form/fields/Field.tsx Executable file
View File

@ -0,0 +1,6 @@
import { FC } from "react";
import { FieldProp } from "../typings";
export const Field: FC<FieldProp> = ({ fm }) => {
return <></>;
};

View File

@ -1,20 +1,57 @@
import { SliderOptions } from "../form-old/Slider/types";
import { FieldOptions } from "../form-old/type";
import { FormHook } from "../form-old/utils/utils";
export type FMProps = {
on_init: (arg: { submit: any; reload: any }) => any;
on_load: () => any;
on_init: (arg: { fm: FMLocal; submit: any; reload: any }) => any;
on_load: (arg: { fm: FMLocal }) => any;
on_submit: (arg: { form: any; error: any }) => Promise<any>;
body: any;
form: FormHook;
PassProp: any;
props: any;
sonar: "on" | "off";
layout: "auto" | "1-col" | "2-col";
};
export type FieldProp = {
name: string;
label: string;
desc?: string;
fm: FMLocal;
type:
| "text"
| "number"
| "textarea"
| "dropdown"
| "relation"
| "password"
| "radio"
| "date"
| "datetime"
| "money"
| "slider"
| "master-link"
| "custom";
required: "y" | "n";
options: FieldOptions;
on_change: (arg: { value: any }) => void | Promise<void>;
PassProp: any;
custom: "y" | "n";
child: any;
selection: "single" | "multi";
suffix: any;
placeholder?: any;
rel_table: string;
rel_fields: string[];
rel_query: () => any;
};
export type FMInternal = {
status: "init" | "loading" | "saving" | "ready";
data: any;
reload: () => Promise<void>;
submit: () => Promise<void>;
error: {
list: { name: string; error: string }[];
set: (name: string, error: string) => void;
@ -32,6 +69,26 @@ export type FMInternal = {
};
export type FMLocal = FMInternal & { render: () => void };
export const FormType = `{
status: "init" | "loading" | "saving" | "ready"
}`;
export const formType = (active: { item_id: string }) => {
console.log("auoaou", typeof active);
return `{
status: "init" | "loading" | "saving" | "ready";
data: any;
reload: () => Promise<void>;
submit: () => Promise<void>;
error: {
list: { name: string; error: string }[];
set: (name: string, error: string) => void;
get: (name: string, error: string) => void;
clear: () => void;
};
internal: {
reload: {
timeout: ReturnType<typeof setTimeout>;
promises: Promise<void>[];
done: any[];
};
};
props: any;
}`;
};

1
comps/form/utils/ed-data.ts Executable file
View File

@ -0,0 +1 @@
export const editorFormData = {} as Record<string, any>;

View File

@ -2,6 +2,7 @@ import { Loader2 } from "lucide-react";
import { toast } from "sonner";
import { FMLocal, FMProps } from "../typings";
import { formError } from "./error";
import { editorFormData } from "./ed-data";
export const formInit = (fm: FMLocal, props: FMProps) => {
for (const [k, v] of Object.entries(props)) {
@ -12,6 +13,9 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
fm.error = formError(fm);
fm.reload = () => {
fm.status = "loading";
fm.render();
const promise = new Promise<void>((done) => {
fm.internal.reload.done.push(done);
clearTimeout(fm.internal.reload.timeout);
@ -29,10 +33,31 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
const res = on_load({ fm });
if (typeof res === "object" && res instanceof Promise) {
fm.data = await res;
} else {
fm.data = res;
}
// if (isEditor) {
// const item_id = (props?.props?.className || "")
// .split(" ")
// .find((e: string) => e.startsWith("s-"));
// if (item_id) {
// console.log(item_id);
// }
// }
fm.internal.reload.done.map((e) => e());
}, 50);
});
fm.internal.reload.promises.push(promise);
return promise;
};
fm.data = { halo: "any" };
fm.submit = async () => {};
fm.props.on_init({ fm, submit: fm.submit, reload: fm.reload });
};

14
data.ts
View File

@ -1,11 +1,11 @@
export { Form } from "@/comps/form/Form";
export { Field } from "@/comps/form/fields/Field";
export { formType } from "@/comps/form/typings";
export { TableList } from "@/comps/list/TableList";
export { TableListType } from "@/comps/list/typings";
export { MasterDetail } from "@/comps/md/MasterDetail";
export { getProp } from "@/comps/md/utils/get-prop";
export { MasterDetailType } from "@/comps/md/utils/typings";
export { TableList } from "@/comps/list/TableList";
export { MasterDetail } from "@/comps/md/MasterDetail";
export { MDAction } from "./comps/md/MDAction";
export { Form } from "@/comps/form/Form";
export { FormType } from "@/comps/form/typings";
export { Field } from "@/comps/form-old/Field";
export { prasi_gen } from "@/gen/prasi_gen";
export { FormatValue } from "@/utils/format-value";
export { TableListType } from "@/comps/list/typings";
export { MDAction } from "./comps/md/MDAction";

View File

@ -1,8 +1,6 @@
export { Card } from "@/comps/custom/Card";
export { Detail } from "@/comps/custom/Detail";
export { Tab } from "@/comps/custom/Tab";
export { Field } from "@/comps/form-old/Field";
export { Form } from "@/comps/form/Form";
export { formatMoney } from "@/comps/form-old/InputMoney";
export { icon } from "@/comps/icon";
export { List } from "@/comps/list/old/List";

View File

@ -16,9 +16,22 @@ export const on_load = ({
after_load: string;
};
}) => {
const sample: any = {};
for (const [k, v] of Object.entries(select) as any) {
if (typeof v === "object") {
sample[k] = {};
Object.keys(v.select).map((e) => {
sample[k][e] = "sample";
});
} else {
sample[k] = "sample";
}
}
return `\
async (opt) => {
if (isEditor) return {};
if (isEditor) return ${JSON.stringify(sample)};
let raw_id = params.id;
if (typeof md === 'object' && md.selected && md.master?.pk) {