This commit is contained in:
2025-10-18 01:46:46 +03:00
commit 9baa68258e
74 changed files with 29125 additions and 0 deletions

View File

@ -0,0 +1,74 @@
import { ZodObject } from 'zod';
import { Flex, rem } from '@mantine/core';
import BooleanField from '@/components/ObjectForm/Fields/BooleanField/BooleanField';
import NumberField from '@/components/ObjectForm/Fields/NumberField/NumberField';
import StringField from '@/components/ObjectForm/Fields/StringField/StringField';
type EditProps<T> = {
object: T;
onChange: (item: T) => void;
};
type CreateProps<T> = {
onCreate: (item: T) => void;
};
type SchemaLabels<S extends ZodObject<any>> = Partial<Record<keyof S['shape'], string>>;
type RestProps<S extends ZodObject<any>> =
| {
schema: S;
labels?: SchemaLabels<S>;
excludeKeys?: (keyof S['shape'])[];
includeKeys?: never;
}
| {
schema: S;
labels?: SchemaLabels<S>;
includeKeys?: (keyof S['shape'])[];
excludeKeys?: never;
};
type Props<ObjectType, ObjectSchema extends ZodObject> = (
| EditProps<ObjectType>
| CreateProps<ObjectType>
) &
RestProps<ObjectSchema>;
const RenderField = (key: string, value: any, label?: string) => {
const getField = () => {
switch (value.type) {
case 'string':
return <StringField label={label ? label : key} />;
case 'number':
return <NumberField label={label ? label : key} />;
case 'boolean':
return <BooleanField label={label ? label : key} />;
default:
return <></>;
}
};
return <div key={key}>{getField()}</div>;
};
function ObjectForm<ObjectType, ObjectSchema extends ZodObject<any, any>>(
props: Props<ObjectType, ObjectSchema>
) {
const processKeyValue = (key: string, val: any) => {
const keyTyped = key as keyof typeof props.schema.shape;
if (props.excludeKeys && props.excludeKeys.includes(keyTyped)) {
return <></>;
}
if (props.includeKeys && !props.includeKeys.includes(keyTyped)) {
return <></>;
}
const label = props.labels ? props.labels[keyTyped] : undefined;
return RenderField(key, val, label);
};
return (
<Flex gap={rem(10)} direction="column">
{Object.entries(props.schema.shape).map(([key, val]) => {
return processKeyValue(key, val);
})}
</Flex>
);
}
export default ObjectForm;