This commit is contained in:
rizky 2024-04-09 19:40:08 -07:00
parent 29cb938e60
commit 70a4422600
10 changed files with 146 additions and 27 deletions

View File

@ -14,6 +14,7 @@ export const Form: FC<FMProps> = (props) => {
reload: async () => { reload: async () => {
formReload(fm); formReload(fm);
}, },
fields: {},
submit: null as any, submit: null as any,
error: {} as any, error: {} as any,
internal: { internal: {

23
comps/form/field/Field.tsx Executable file
View File

@ -0,0 +1,23 @@
import { FC } from "react";
import { FieldProp } from "../typings";
import { createField } from "../utils/create-field";
import { Label } from "./Label";
export const Field: FC<FieldProp> = (arg) => {
const field = createField(arg);
if (field.status === "init") return null;
const mode = field.label_mode;
return (
<div
className={cx(
"field",
mode === "horizontal" && "",
mode === "vertical" && ""
)}
>
{mode !== "hidden" && <Label field={field} />}
</div>
);
};

8
comps/form/field/Input.tsx Executable file
View File

@ -0,0 +1,8 @@
import { FMLocal, FieldLocal } from "../typings";
export const FieldInput: FC<{ field: FieldLocal; fm: FMLocal }> = ({
field,
fm,
}) => {
return <></>;
};

6
comps/form/field/Label.tsx Executable file
View File

@ -0,0 +1,6 @@
import { FC } from "react";
import { FieldLocal } from "../typings";
export const Label: FC<{ field: FieldLocal }> = ({ field }) => {
return <div className={cx("label")}>{field.label}</div>;
};

View File

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

View File

@ -1,6 +1,8 @@
import { ReactNode } from "react";
import { SliderOptions } from "../form-old/Slider/types"; import { SliderOptions } from "../form-old/Slider/types";
import { FieldOptions } from "../form-old/type"; import { FieldOptions } from "../form-old/type";
import { FormHook } from "../form-old/utils/utils"; import { FormHook } from "../form-old/utils/utils";
import { editorFormData } from "./utils/ed-data";
export type FMProps = { export type FMProps = {
on_init: (arg: { fm: FMLocal; submit: any; reload: any }) => any; on_init: (arg: { fm: FMLocal; submit: any; reload: any }) => any;
@ -12,12 +14,15 @@ export type FMProps = {
props: any; props: any;
sonar: "on" | "off"; sonar: "on" | "off";
layout: "auto" | "1-col" | "2-col"; layout: "auto" | "1-col" | "2-col";
meta: any;
item: any;
}; };
export type FieldProp = { export type FieldProp = {
name: string; name: string;
label: string; label: string;
desc?: string; desc?: string;
label_mode: "vertical" | "horizontal" | "hidden";
fm: FMLocal; fm: FMLocal;
type: type:
| "text" | "text"
@ -40,6 +45,7 @@ export type FieldProp = {
custom: "y" | "n"; custom: "y" | "n";
child: any; child: any;
selection: "single" | "multi"; selection: "single" | "multi";
prefix: any;
suffix: any; suffix: any;
placeholder?: any; placeholder?: any;
rel_table: string; rel_table: string;
@ -52,6 +58,7 @@ export type FMInternal = {
data: any; data: any;
reload: () => Promise<void>; reload: () => Promise<void>;
submit: () => Promise<void>; submit: () => Promise<void>;
fields: Record<string, FieldLocal>;
error: { error: {
list: { name: string; error: string }[]; list: { name: string; error: string }[];
set: (name: string, error: string) => void; set: (name: string, error: string) => void;
@ -69,11 +76,40 @@ export type FMInternal = {
}; };
export type FMLocal = FMInternal & { render: () => void }; export type FMLocal = FMInternal & { render: () => void };
export const formType = (active: { item_id: string }) => { export type FieldInternal = {
console.log("auoaou", typeof active); status: "init" | "loading" | "ready";
return `{ name: FieldProp["name"];
type: FieldProp["type"];
label: FieldProp["label"];
desc: FieldProp["desc"];
prefix: FieldProp["prefix"];
suffix: FieldProp["suffix"];
label_mode: FieldProp["label_mode"];
Child: () => ReactNode;
};
export type FieldLocal = FieldInternal & { render: () => void };
export const formType = (active: { item_id: string }, meta: any) => {
let data = "null as any";
const cache = editorFormData[active.item_id];
if (cache && cache.data) {
data = JSON.stringify(cache.data);
} else {
const m = meta[active.item_id];
if (m && m.parent && m.parent.id) {
const cache = editorFormData[m.parent.id];
if (cache && cache.data) {
data = JSON.stringify(cache.data);
}
}
}
return `
const ___data = ${data};
const fm = null as unknown as {
status: "init" | "loading" | "saving" | "ready"; status: "init" | "loading" | "saving" | "ready";
data: any; data: typeof ___data;
reload: () => Promise<void>; reload: () => Promise<void>;
submit: () => Promise<void>; submit: () => Promise<void>;
error: { error: {

View File

@ -0,0 +1,31 @@
import { useLocal } from "@/utils/use-local";
import { FMLocal, FieldInternal, FieldProp } from "../typings";
import { useEffect } from "react";
export const createField = (arg: FieldProp) => {
const field = useLocal<FieldInternal>({
status: "init",
name: arg.name,
label: arg.label,
type: arg.type,
desc: arg.desc,
prefix: arg.prefix,
suffix: arg.suffix,
label_mode: arg.label_mode,
Child: () => {
return <arg.PassProp>{arg.child}</arg.PassProp>;
},
});
const fm = arg.fm;
useEffect(() => {
if (field.status === "init") {
field.status = "ready";
fm.fields[arg.name] = field;
field.render();
}
}, []);
return field;
};

View File

@ -1 +1,4 @@
export const editorFormData = {} as Record<string, any>; export const editorFormData = {} as Record<
string,
{ on_load: string; data: any }
>;

View File

@ -3,10 +3,11 @@ import { toast } from "sonner";
import { FMLocal, FMProps } from "../typings"; import { FMLocal, FMProps } from "../typings";
import { formError } from "./error"; import { formError } from "./error";
import { editorFormData } from "./ed-data"; import { editorFormData } from "./ed-data";
import get from "lodash.get";
export const formInit = (fm: FMLocal, props: FMProps) => { export const formInit = (fm: FMLocal, props: FMProps) => {
for (const [k, v] of Object.entries(props)) { for (const [k, v] of Object.entries(props)) {
if (["PassProp", "body"].includes(k)) continue; if (["PassProp", "body", "meta", "item"].includes(k)) continue;
(fm.props as any)[k] = v; (fm.props as any)[k] = v;
} }
const { on_load, sonar } = fm.props; const { on_load, sonar } = fm.props;
@ -31,6 +32,21 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
}); });
} }
let should_load = true;
if (isEditor) {
const item_id = props.item.id;
if (item_id) {
const cache = editorFormData[item_id];
if (
cache &&
cache.on_load === get(props.item, "component.props.on_load.value")
) {
fm.data = cache.data;
should_load = false;
}
}
}
if (should_load) {
const res = on_load({ fm }); const res = on_load({ fm });
if (typeof res === "object" && res instanceof Promise) { if (typeof res === "object" && res instanceof Promise) {
@ -39,15 +55,16 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
fm.data = res; fm.data = res;
} }
// if (isEditor) { if (isEditor) {
// const item_id = (props?.props?.className || "") const item_id = props.item.id;
// .split(" ") if (item_id) {
// .find((e: string) => e.startsWith("s-")); editorFormData[item_id] = {
data: fm.data,
// if (item_id) { on_load: get(props.item, "component.props.on_load.value"),
// console.log(item_id); };
// } }
// } }
}
fm.internal.reload.done.map((e) => e()); fm.internal.reload.done.map((e) => e());
}, 50); }, 50);

View File

@ -1,5 +1,5 @@
export { Form } from "@/comps/form/Form"; export { Form } from "@/comps/form/Form";
export { Field } from "@/comps/form/fields/Field"; export { Field } from "@/comps/form/field/Field";
export { formType } from "@/comps/form/typings"; export { formType } from "@/comps/form/typings";
export { TableList } from "@/comps/list/TableList"; export { TableList } from "@/comps/list/TableList";
export { TableListType } from "@/comps/list/typings"; export { TableListType } from "@/comps/list/typings";