119 lines
3.6 KiB
TypeScript
119 lines
3.6 KiB
TypeScript
|
|
'use client';
|
||
|
|
import { Button } from '@/components/ui/button';
|
||
|
|
import {
|
||
|
|
Field,
|
||
|
|
FieldError,
|
||
|
|
FieldGroup,
|
||
|
|
FieldLabel,
|
||
|
|
} from '@/components/ui/field';
|
||
|
|
import { Input } from '@/components/ui/input';
|
||
|
|
import { deafultPasswordValidator } from '@/src/constants';
|
||
|
|
import { authClient } from '@/src/lib/auth-client';
|
||
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||
|
|
import { Controller, useForm } from 'react-hook-form';
|
||
|
|
import { toast } from 'sonner';
|
||
|
|
import { z } from 'zod/v4';
|
||
|
|
|
||
|
|
const signUpSchema = z.object({
|
||
|
|
email: z.email(),
|
||
|
|
password: deafultPasswordValidator(),
|
||
|
|
name: z.string().min(1).max(100),
|
||
|
|
});
|
||
|
|
|
||
|
|
export default function SignUp() {
|
||
|
|
const form = useForm<z.infer<typeof signUpSchema>>({
|
||
|
|
resolver: zodResolver(signUpSchema),
|
||
|
|
defaultValues: {
|
||
|
|
email: '',
|
||
|
|
password: '',
|
||
|
|
},
|
||
|
|
});
|
||
|
|
async function onSubmit(values: z.infer<typeof signUpSchema>) {
|
||
|
|
const email = values.email;
|
||
|
|
const password = values.password;
|
||
|
|
const name = values.name;
|
||
|
|
await authClient.signUp.email(
|
||
|
|
{
|
||
|
|
email, // user email address
|
||
|
|
password, // user password -> min 8 characters by default
|
||
|
|
name,
|
||
|
|
callbackURL: '/dashboard', // A URL to redirect to after the user verifies their email (optional)
|
||
|
|
},
|
||
|
|
{
|
||
|
|
onRequest: (ctx) => {
|
||
|
|
//show loading
|
||
|
|
},
|
||
|
|
onSuccess: (ctx) => {
|
||
|
|
//redirect to the dashboard or sign in page
|
||
|
|
toast('Registered succesfully');
|
||
|
|
},
|
||
|
|
onError: (ctx) => {
|
||
|
|
// display the error message
|
||
|
|
toast(ctx.error.message);
|
||
|
|
},
|
||
|
|
},
|
||
|
|
);
|
||
|
|
}
|
||
|
|
return (
|
||
|
|
<form id="form-signup" onSubmit={form.handleSubmit(onSubmit)}>
|
||
|
|
<FieldGroup>
|
||
|
|
<Controller
|
||
|
|
name="name"
|
||
|
|
control={form.control}
|
||
|
|
render={({ field, fieldState }) => (
|
||
|
|
<Field data-invalid={fieldState.invalid}>
|
||
|
|
<FieldLabel htmlFor="form-name">Name</FieldLabel>
|
||
|
|
<Input
|
||
|
|
{...field}
|
||
|
|
id="form-name"
|
||
|
|
aria-invalid={fieldState.invalid}
|
||
|
|
placeholder="John Doe"
|
||
|
|
autoComplete="off"
|
||
|
|
/>
|
||
|
|
{fieldState.invalid && <FieldError errors={[fieldState.error]} />}
|
||
|
|
</Field>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
<Controller
|
||
|
|
name="email"
|
||
|
|
control={form.control}
|
||
|
|
render={({ field, fieldState }) => (
|
||
|
|
<Field data-invalid={fieldState.invalid}>
|
||
|
|
<FieldLabel htmlFor="form-email">Email</FieldLabel>
|
||
|
|
<Input
|
||
|
|
{...field}
|
||
|
|
id="form-email"
|
||
|
|
aria-invalid={fieldState.invalid}
|
||
|
|
placeholder="email@example.com"
|
||
|
|
autoComplete="off"
|
||
|
|
/>
|
||
|
|
{fieldState.invalid && <FieldError errors={[fieldState.error]} />}
|
||
|
|
</Field>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
<Controller
|
||
|
|
name="password"
|
||
|
|
control={form.control}
|
||
|
|
render={({ field, fieldState }) => (
|
||
|
|
<Field data-invalid={fieldState.invalid}>
|
||
|
|
<FieldLabel htmlFor="form-password">Password</FieldLabel>
|
||
|
|
<Input
|
||
|
|
{...field}
|
||
|
|
id="form-password"
|
||
|
|
type="password"
|
||
|
|
aria-invalid={fieldState.invalid}
|
||
|
|
autoComplete="off"
|
||
|
|
placeholder="******"
|
||
|
|
/>
|
||
|
|
{fieldState.invalid && <FieldError errors={[fieldState.error]} />}
|
||
|
|
</Field>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
<Button type="submit" form="form-signup">
|
||
|
|
Submit
|
||
|
|
</Button>
|
||
|
|
</FieldGroup>
|
||
|
|
</form>
|
||
|
|
);
|
||
|
|
}
|