t-convex-nextjs-saas/src/app/sign-up/page.tsx

119 lines
3.6 KiB
TypeScript
Raw Normal View History

'use client';
import { Button } from '@/components/ui/button';
import {
Field,
FieldError,
FieldGroup,
FieldLabel,
} from '@/components/ui/field';
import { Input } from '@/components/ui/input';
2026-04-01 16:14:52 +00:00
import { deafultPasswordValidator } from '@/constants';
import { authClient } from '@/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>
);
}