import { parseGenField } from "lib/gen/utils";
import { MDLocal } from "lib/comps/md/utils/typings";
import { Button } from "lib/comps/ui/button";
import { toast } from "lib/comps/ui/toast";
import get from "lodash.get";
import { AlertTriangle, Check, ChevronLeft, Loader2, Plus } from "lucide-react";
import { FMLocal, FMProps } from "../typings";
import { editorFormData } from "./ed-data";
import { formError } from "./error";
import { lang, translate } from "lib/lang";
export const formInit = (fm: FMLocal, props: FMProps) => {
for (const [k, v] of Object.entries(props)) {
if (["PassProp", "body", "meta", "item"].includes(k)) continue;
(fm.props as any)[k] = v;
}
const { on_load, sonar } = fm.props;
fm.error = formError(fm);
fm.field_def = {};
const defs = parseGenField(fm.props.gen_fields);
for (const d of defs) {
fm.field_def[d.name] = d;
}
const toastSuccess = (opt: { addNewText: string }) => {
const md = fm.deps.md as MDLocal;
fm.save_status = "saved";
if (md) {
toast.success(
{
toast.dismiss();
}}
>
{translate("Record Saved")}
{md.props.mode === "full" && (
)}
,
{
duration:3000,
className: css`
background: #e4ffed;
border: 2px solid green;
.success-title {
margin-bottom: 20px;
}
`,
}
);
} else {
toast.success(
{
toast.dismiss();
}}
>
Saved
,
{
duration:3000,
className: css`
background: #e4ffed;
border: 2px solid green;
`,
}
);
}
};
fm.reload = async () => {
fm.status = isEditor ? "ready" : "loading";
fm.render();
if (sonar === "on" && !isEditor) {
toast.dismiss();
toast.loading(
<>
Loading data...
>,
{ dismissible: true }
);
}
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) {
if (!on_load) {
console.error("Form on_load is empty. Please re-generate the form.");
} else {
const on_load_result = on_load({ fm });
let result = undefined;
if (
typeof on_load_result === "object" &&
on_load_result instanceof Promise
) {
result = await on_load_result;
} else {
result = on_load_result;
}
fm.data = result;
fm.save_status = "saved";
if (result === undefined) fm.data = {};
if (isEditor) {
const item_id = props.item.id;
if (item_id) {
editorFormData[item_id] = {
data: fm.data,
on_load: get(props.item, "component.props.on_load.value"),
};
}
}
}
}
toast.dismiss();
if (fm.is_newly_created) {
fm.is_newly_created = false;
toastSuccess({ addNewText: translate("Add Another") });
}
fm.status = "ready";
fm.render();
};
fm.submit = async () => {
if (fm.status !== "ready") {
return;
}
if (typeof fm.props.on_submit === "function") {
fm.status = "saving";
fm.render();
if (fm.props.sonar === "on" && !isEditor) {
toast.loading(
<>
Submitting...
>
);
}
const form = JSON.parse(JSON.stringify(fm.data));
if (fm.deps.md) {
const md = fm.deps.md;
const last = md.params.links[md.params.links.length - 1];
if (last) {
const pk = Object.values(fm.field_def).find((e) => e.is_pk);
if (pk) {
let obj = last.update;
if (!fm.data[pk.name]) {
obj = last.create;
}
if (typeof obj === "object" && obj) {
for (const [k, v] of Object.entries(obj)) {
form[k] = v;
}
}
}
}
}
const success = await fm.props.on_submit({
fm,
form,
error: fm.error.object,
});
toast.dismiss();
fm.status = "ready";
fm.render();
if (fm.props.sonar === "on" && !isEditor) {
toast.dismiss();
if (!success) {
const errors = Object.keys(fm.error.list);
const count = errors.length;
toast.error(
{translate("Save Failed")}
{count > 0 &&
`, ${translate("please correct")}
${count} ${translate("errors")}`}
.
,
{
dismissible: true,
className: css`
background: #ffecec;
border: 2px solid red;
`,
}
);
} else {
toastSuccess({ addNewText: lang.t("Add New") });
}
}
return success;
}
};
if (typeof fm.props.on_init === "function") {
fm.props.on_init({ fm, submit: fm.submit, reload: fm.reload });
}
};