This commit is contained in:
rizky 2024-08-16 21:12:06 -07:00
parent 53c2009509
commit e49b299249
4 changed files with 100 additions and 68 deletions

View File

@ -1,7 +1,8 @@
import { ReactNode, useCallback, useEffect, useState } from "react"; import { ReactNode, useCallback, useEffect, useState } from "react";
import { BaseFormLocal, default_base_form_local } from "./types"; import { BaseFormLocal, default_base_form_local } from "./types";
import { useLocal } from "lib/utils/use-local"; import { useLocal } from "lib/utils/use-local";
import { FieldLocal, FieldProp, fieldType } from "../typings"; import { FieldLocal, FieldProp, fieldType, FMLocal } from "../typings";
import { FieldLoading } from "lib/exports";
export type BaseFormProps<T> = { export type BaseFormProps<T> = {
data: T; data: T;
@ -9,13 +10,16 @@ export type BaseFormProps<T> = {
on_submit?: (form: BaseFormLocal<T>) => Promise<any> | any; on_submit?: (form: BaseFormLocal<T>) => Promise<any> | any;
children: ReactNode | ((form: BaseFormLocal<T>) => ReactNode); children: ReactNode | ((form: BaseFormLocal<T>) => ReactNode);
render?: () => void; render?: () => void;
on_change?: (fm: FMLocal, name: string, new_value: any) => any;
is_form?: boolean; is_form?: boolean;
}; };
export const BaseForm = <T extends Record<string, any>>( export const BaseForm = <T extends Record<string, any>>(
props: BaseFormProps<T> props: BaseFormProps<T>
) => { ) => {
const { data, children, className, on_submit, render } = props; const { data, children, className, on_submit, render, on_change } = props;
const form = useLocal({ ...default_base_form_local }) as BaseFormLocal<T>; const form = useLocal({
...default_base_form_local,
}) as BaseFormLocal<T>;
if (render) { if (render) {
form.render = render; form.render = render;
@ -73,12 +77,21 @@ export const BaseForm = <T extends Record<string, any>>(
} }
form.fm = { form.fm = {
data: data, data: data,
status: "ready",
deps: {},
props: { label_mode: "vertical" }, props: { label_mode: "vertical" },
error: { error: {
get: () => { get: () => {
return []; return [];
}, },
}, },
events: {
on_change: (n: any, v: any) => {
if (on_change && form.fm) {
on_change(form.fm, n, v);
}
},
},
submit: () => on_submit?.(form), submit: () => on_submit?.(form),
size: { field: size }, size: { field: size },
render: form.render, render: form.render,
@ -109,27 +122,14 @@ export const BaseForm = <T extends Record<string, any>>(
form.status = "ready"; form.status = "ready";
} }
if (!form.fm) {
form.fm = form.createFm();
}
if (typeof props.is_form === "boolean") { if (typeof props.is_form === "boolean") {
if (!props.is_form) { if (!props.is_form) {
return ( if (!form.fm.data) return <FieldLoading />;
<div return <>{typeof children === "function" ? children(form) : children}</>;
className={cx(
"form c-flex-1 c-flex-col c-w-full c-h-full c-relative c-overflow-auto c-contents",
className
)}
>
<div
className={cx(
"form-inner c-flex-1 c-flex-wrap c-items-start c-content-start c-absolute c-inset-0 c-contents",
css`
padding-right: 10px;
`
)}
>
{typeof children === "function" ? children(form) : children}
</div>
</div>
);
} }
} }
@ -142,9 +142,6 @@ export const BaseForm = <T extends Record<string, any>>(
form.render(); form.render();
}, 50); }, 50);
} }
if (!form.fm) {
form.fm = form.createFm();
}
return ( return (
<form <form
onSubmit={(e) => { onSubmit={(e) => {

View File

@ -54,6 +54,14 @@ export const Field: FC<FieldProp> = (arg) => {
} else { } else {
local.prev_val = fm.data[name]; local.prev_val = fm.data[name];
} }
if (!fm.events) {
fm.events = {
on_change(name, new_value) {},
};
}
fm.events.on_change(name, fm.data[name]);
return; return;
} }
@ -169,7 +177,12 @@ export const Field: FC<FieldProp> = (arg) => {
arg={arg} arg={arg}
/> />
{field.desc && ( {field.desc && (
<div className={cx("c-p-2 c-pl-0 c-text-xs", errors.length > 0 && "c-pb-1")}> <div
className={cx(
"c-p-2 c-pl-0 c-text-xs",
errors.length > 0 && "c-pb-1"
)}
>
{field.desc} {field.desc}
</div> </div>
)} )}

View File

@ -3,6 +3,7 @@ import { useLocal } from "lib/utils/use-local";
import { FC, useEffect, useRef } from "react"; import { FC, useEffect, useRef } from "react";
import { FMLocal } from "../../typings"; import { FMLocal } from "../../typings";
import get from "lodash.get"; import get from "lodash.get";
import { BaseForm } from "../../base/BaseForm";
export const TableEdit: FC<{ export const TableEdit: FC<{
on_init: () => FMLocal; on_init: () => FMLocal;
@ -43,7 +44,17 @@ export const TableEdit: FC<{
"props.meta.item.component.props.child.content.childs" "props.meta.item.component.props.child.content.childs"
); );
let columns: any[] = []; let columns: {
key: string;
name?: string;
label?: string;
width?: number;
minWidth?: number;
resizable?: boolean;
sortable?: boolean;
frozen?: boolean;
renderCell: (arg: any) => any;
}[] = [];
let childs: any[] = []; let childs: any[] = [];
const mode_child = raw_childs.find((e: any) => const mode_child = raw_childs.find((e: any) =>
["tbl-col", "table: columns"].includes(e.name) ["tbl-col", "table: columns"].includes(e.name)
@ -73,7 +84,6 @@ export const TableEdit: FC<{
renderCell(arg: any) { renderCell(arg: any) {
// return <></>; // return <></>;
const { props, tbl } = arg; const { props, tbl } = arg;
const fm_row = { ...fm, render: local.render };
return ( return (
<PassProp <PassProp
idx={props.rowIdx} idx={props.rowIdx}
@ -84,7 +94,7 @@ export const TableEdit: FC<{
value: get(props.row, props.column.key), value: get(props.row, props.column.key),
depth: 0, depth: 0,
}} }}
fm={fm_row} fm={arg.fm}
ext_fm={{ ext_fm={{
idx: props.rowIdx, idx: props.rowIdx,
change: () => {}, change: () => {},
@ -114,8 +124,6 @@ export const TableEdit: FC<{
sortable: true, sortable: true,
renderCell(arg: any) { renderCell(arg: any) {
const { props, tbl } = arg; const { props, tbl } = arg;
const fm_row = { ...fm, render: local.render };
fm_row.data = props.row;
local.tbl = tbl; local.tbl = tbl;
const key = props.column.key; const key = props.column.key;
return ( return (
@ -128,7 +136,7 @@ export const TableEdit: FC<{
depth: props.row.__depth || 0, depth: props.row.__depth || 0,
}} }}
rows={tbl.data} rows={tbl.data}
fm={fm_row} fm={props.fm}
fm_parent={parent} fm_parent={parent}
ext_fm={{ ext_fm={{
idx: props.rowIdx, idx: props.rowIdx,
@ -205,7 +213,7 @@ export const TableEdit: FC<{
css` css`
background-color: #f9f9f9; background-color: #f9f9f9;
`, `,
header.width > 0 header.width || 0 > 0
? css` ? css`
width: ${header.width}px; width: ${header.width}px;
` `
@ -216,7 +224,7 @@ export const TableEdit: FC<{
className={cx( className={cx(
"rdg-cell c-py-2 c-px-4 c-flex c-flex-row c-items-center c-h-full", "rdg-cell c-py-2 c-px-4 c-flex c-flex-row c-items-center c-h-full",
header.width > 0 header.width || 0 > 0
? css` ? css`
width: ${header.width}px; width: ${header.width}px;
` `
@ -244,15 +252,25 @@ export const TableEdit: FC<{
{Array.isArray(value) && value.length ? ( {Array.isArray(value) && value.length ? (
<> <>
{value.map((row: any, idx: number) => { {value.map((row: any, idx: number) => {
return (
<BaseForm
is_form={false}
data={row}
on_change={(_fm) => {
fm.data[name][idx] = _fm.data;
fm.render();
}}
>
{(form) => {
return ( return (
<tr> <tr>
{columns.map((header) => { {columns.map((header) => {
return ( return (
<td <td
className={cx( className={cx(
header.width > 0 header.width || 0 > 0
? css` ? css`
width: ${header.width}px; width: ${header.width || 0}px;
` `
: "" : ""
)} )}
@ -268,6 +286,7 @@ export const TableEdit: FC<{
row: row, row: row,
rowIdx: idx, rowIdx: idx,
column: header, column: header,
fm: form.fm,
}, },
tbl: { tbl: {
data: value, data: value,
@ -279,6 +298,9 @@ export const TableEdit: FC<{
})} })}
</tr> </tr>
); );
}}
</BaseForm>
);
})} })}
</> </>
) : ( ) : (