mirror of
https://codeberg.org/MarkusThielker/next-ory.git
synced 2025-04-10 11:58:41 +00:00
NORY-47: refactor identity traits form to use new dynamic-form component
This commit is contained in:
parent
152ec171c5
commit
45b3961891
1 changed files with 89 additions and 63 deletions
|
@ -1,82 +1,108 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Form, FormControl, FormField, FormItem, FormLabel } from '@/components/ui/form';
|
import { KratosSchema, kratosSchemaToZod } from '@/lib/forms/identity-form';
|
||||||
import { Input } from '@/components/ui/input';
|
import { useForm } from 'react-hook-form';
|
||||||
import { generateZodSchema, KratosSchema, KratosSchemaProperties } from '@/lib/forms/identity-form';
|
|
||||||
import { useForm, UseFormReturn } from 'react-hook-form';
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { toast } from 'sonner';
|
|
||||||
import { Identity } from '@ory/client';
|
import { Identity } from '@ory/client';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { toast } from 'sonner';
|
||||||
|
import DynamicForm from '@/components/dynamic-form';
|
||||||
|
import { FormControl, FormDescription, FormField, FormItem, FormLabel } from '@/components/ui/form';
|
||||||
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
|
import { zu } from 'zod_utilz';
|
||||||
|
import { updateIdentity } from '@/app/(inside)/user/action';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
interface IdentityTraitFormProps {
|
interface IdentityTraitFormProps {
|
||||||
schema: KratosSchema;
|
schema: KratosSchema;
|
||||||
identity: Identity;
|
identity: Identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderUiNodes(form: UseFormReturn, properties: KratosSchemaProperties, prefix?: string): any {
|
|
||||||
|
|
||||||
let keyPrefix = prefix ? prefix + '.' : '';
|
|
||||||
|
|
||||||
return Object.entries(properties).map(([key, value]) => {
|
|
||||||
if (value.type === 'object') {
|
|
||||||
return renderUiNodes(form, value.properties!, key);
|
|
||||||
} else if (value.type === 'boolean') {
|
|
||||||
return (
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name={keyPrefix + key}
|
|
||||||
key={key}
|
|
||||||
className="space-y-0"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem className="flex items-center space-x-2 space-y-0">
|
|
||||||
<Checkbox {...field} checked={field.value}/>
|
|
||||||
<FormLabel>{value.title}</FormLabel>
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name={keyPrefix + key}
|
|
||||||
key={key}
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>{value.title}</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input placeholder={value.title} readOnly {...field} />
|
|
||||||
</FormControl>
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function IdentityTraitForm({ schema, identity }: IdentityTraitFormProps) {
|
export function IdentityTraitForm({ schema, identity }: IdentityTraitFormProps) {
|
||||||
|
|
||||||
const zodIdentitySchema = generateZodSchema(schema);
|
const [currentIdentity, setCurrentIdentity] = useState(identity);
|
||||||
const form = useForm<z.infer<typeof zodIdentitySchema>>({
|
|
||||||
defaultValues: identity.traits,
|
const generated = kratosSchemaToZod(schema);
|
||||||
resolver: zodResolver(zodIdentitySchema),
|
const metadata = z.object({
|
||||||
|
metadata_public: zu.stringToJSON(),
|
||||||
|
metadata_admin: zu.stringToJSON(),
|
||||||
});
|
});
|
||||||
|
|
||||||
function onSubmit(values: z.infer<typeof zodIdentitySchema>) {
|
const zodIdentitySchema = generated.merge(metadata);
|
||||||
toast.message(JSON.stringify(values, null, 4));
|
|
||||||
}
|
const form = useForm<z.infer<typeof zodIdentitySchema>>({
|
||||||
|
resolver: zodResolver(zodIdentitySchema),
|
||||||
|
defaultValues: {
|
||||||
|
...currentIdentity.traits,
|
||||||
|
metadata_public: currentIdentity.metadata_public ? JSON.stringify(currentIdentity.metadata_public) : '',
|
||||||
|
metadata_admin: currentIdentity.metadata_admin ? JSON.stringify(currentIdentity.metadata_admin) : '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onValid = (data: z.infer<typeof zodIdentitySchema>) => {
|
||||||
|
|
||||||
|
const traits = structuredClone(data);
|
||||||
|
delete traits['metadata_public'];
|
||||||
|
delete traits['metadata_admin'];
|
||||||
|
|
||||||
|
updateIdentity({
|
||||||
|
id: currentIdentity.id,
|
||||||
|
body: {
|
||||||
|
schema_id: currentIdentity.schema_id,
|
||||||
|
state: currentIdentity.state!,
|
||||||
|
traits: traits,
|
||||||
|
metadata_public: data.metadata_public,
|
||||||
|
metadata_admin: data.metadata_admin,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((identity) => {
|
||||||
|
setCurrentIdentity(identity);
|
||||||
|
toast.success('Identity updated');
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
toast.error('Updating identity failed');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onInvalid = (data: z.infer<typeof zodIdentitySchema>) => {
|
||||||
|
console.log('data', data);
|
||||||
|
toast.error('Invalid values');
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form {...form}>
|
<DynamicForm
|
||||||
<form onSubmit={onSubmit} className="grid grid-cols-1 gap-4">
|
form={form}
|
||||||
{
|
properties={schema.properties.traits.properties}
|
||||||
renderUiNodes(form, schema.properties.traits.properties)
|
onValid={onValid}
|
||||||
}
|
onInvalid={onInvalid}
|
||||||
</form>
|
submitLabel="Update Identity"
|
||||||
</Form>
|
>
|
||||||
|
<FormField
|
||||||
|
{...form.register('metadata_public')}
|
||||||
|
key={'metadata_public'}
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Public Metadata</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Textarea placeholder="Public Metadata" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>This has to be valid JSON</FormDescription>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
{...form.register('metadata_admin')}
|
||||||
|
key={'metadata_admin'}
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Admin Metadata</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Textarea placeholder="Admin Metadata" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>This has to be valid JSON</FormDescription>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</DynamicForm>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue