mirror of
https://codeberg.org/MarkusThielker/next-ory.git
synced 2025-04-19 17:11:18 +00:00
99 lines
3.6 KiB
TypeScript
99 lines
3.6 KiB
TypeScript
'use client';
|
|
|
|
import { FieldValues, Path, SubmitErrorHandler, SubmitHandler, UseFormReturn } from 'react-hook-form';
|
|
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel } from '@/components/ui/form';
|
|
import { Input } from '@/components/ui/input';
|
|
import { Button } from '@/components/ui/button';
|
|
import React, { ReactNode } from 'react';
|
|
import { Checkbox } from '@/components/ui/checkbox';
|
|
import { KratosSchemaProperties } from '@/lib/forms/identity-form';
|
|
|
|
interface DynamicFormProps<T extends FieldValues> {
|
|
children?: ReactNode,
|
|
form: UseFormReturn<T>,
|
|
properties: KratosSchemaProperties,
|
|
onValid: SubmitHandler<T>,
|
|
onInvalid: SubmitErrorHandler<T>,
|
|
submitLabel?: string,
|
|
}
|
|
|
|
export function DynamicForm<T extends FieldValues>(
|
|
{
|
|
children,
|
|
form,
|
|
properties,
|
|
onValid,
|
|
onInvalid,
|
|
submitLabel,
|
|
}: DynamicFormProps<T>,
|
|
) {
|
|
|
|
const generateFormFields = (data: KratosSchemaProperties, prefix = '') => {
|
|
return (
|
|
<React.Fragment key={prefix}>
|
|
{
|
|
data && Object.entries(data).map(([key, value]) => {
|
|
|
|
const fullFieldName = prefix ? `${prefix}.${key}` : key;
|
|
|
|
if (value.type === 'object') {
|
|
|
|
return generateFormFields(value.properties!, fullFieldName);
|
|
|
|
} else if (value.type === 'boolean') {
|
|
|
|
return (
|
|
<FormField
|
|
{...form.register(fullFieldName as Path<T>)}
|
|
key={fullFieldName}
|
|
render={({ field }) => (
|
|
<FormItem className="flex items-center space-x-2 space-y-0">
|
|
<Checkbox {...field} checked={field.value}/>
|
|
<FormLabel>{key}</FormLabel>
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
);
|
|
|
|
} else {
|
|
|
|
return (
|
|
<FormField
|
|
{...form.register(fullFieldName as Path<T>)}
|
|
key={fullFieldName}
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>{value.title}</FormLabel>
|
|
<FormControl>
|
|
<Input placeholder={value.title} {...field} />
|
|
</FormControl>
|
|
<FormDescription>{value.description}</FormDescription>
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
);
|
|
}
|
|
})
|
|
}
|
|
</React.Fragment>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<Form {...form}>
|
|
<form className="grid grid-cols-1 gap-2" onSubmit={form.handleSubmit(onValid, onInvalid)}>
|
|
{generateFormFields(properties)}
|
|
{children}
|
|
<Button
|
|
key="submit"
|
|
type="submit"
|
|
disabled={!form.formState.isDirty}
|
|
>
|
|
{submitLabel ?? 'Submit'}
|
|
</Button>
|
|
</form>
|
|
</Form>
|
|
);
|
|
}
|
|
|
|
export default DynamicForm;
|