2023-12-05 06:34:02 +00:00
|
|
|
"use client"
|
|
|
|
|
|
|
|
|
|
import * as React from "react"
|
|
|
|
|
|
2023-12-05 08:15:04 +00:00
|
|
|
import { zodResolver } from "@hookform/resolvers/zod"
|
|
|
|
|
import { useForm } from "react-hook-form"
|
|
|
|
|
import * as z from "zod"
|
|
|
|
|
|
2023-12-05 06:34:02 +00:00
|
|
|
import { cn } from "@/lib/utils"
|
|
|
|
|
import { IconSpinner } from "@/components/ui/icons"
|
|
|
|
|
import { Button } from "@/components/ui/button"
|
|
|
|
|
import { Input } from "@/components/ui/input"
|
2023-12-05 08:15:04 +00:00
|
|
|
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"
|
|
|
|
|
|
|
|
|
|
const formSchema = z.object({
|
|
|
|
|
email: z.string().email("Invalid email address"),
|
|
|
|
|
password1: z.string(),
|
|
|
|
|
password2: z.string(),
|
|
|
|
|
invitationCode: z.string().optional(),
|
|
|
|
|
}).refine((data) => data.password1 === data.password2, {
|
|
|
|
|
message: "Passwords don't match",
|
|
|
|
|
path: ["password2"],
|
|
|
|
|
});
|
2023-12-05 06:34:02 +00:00
|
|
|
|
2023-12-05 07:52:57 +00:00
|
|
|
interface UserAuthFormProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
|
|
invitationCode?: string
|
|
|
|
|
}
|
2023-12-05 06:34:02 +00:00
|
|
|
|
2023-12-05 07:52:57 +00:00
|
|
|
export function UserAuthForm({ className, invitationCode, ...props }: UserAuthFormProps) {
|
2023-12-05 08:15:04 +00:00
|
|
|
const form = useForm<z.infer<typeof formSchema>>({
|
|
|
|
|
resolver: zodResolver(formSchema),
|
|
|
|
|
defaultValues: {
|
|
|
|
|
email: "",
|
|
|
|
|
password1: "",
|
|
|
|
|
password2: "",
|
|
|
|
|
invitationCode,
|
|
|
|
|
}
|
|
|
|
|
})
|
2023-12-05 06:34:02 +00:00
|
|
|
|
2023-12-05 08:15:04 +00:00
|
|
|
const { isSubmitSuccessful, isSubmitting } = form.formState;
|
2023-12-05 06:34:02 +00:00
|
|
|
|
2023-12-05 08:15:04 +00:00
|
|
|
async function onSubmit(values: z.infer<typeof formSchema>) {
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 500000))
|
2023-12-05 06:34:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className={cn("grid gap-6", className)} {...props}>
|
2023-12-05 08:15:04 +00:00
|
|
|
<Form {...form}>
|
|
|
|
|
<form className="grid gap-2" onSubmit={form.handleSubmit(onSubmit)}>
|
|
|
|
|
<FormField control={form.control} name="email" render={({ field }) => (
|
|
|
|
|
<FormItem>
|
|
|
|
|
<FormLabel>Email</FormLabel>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
placeholder=""
|
|
|
|
|
type="email"
|
|
|
|
|
autoCapitalize="none"
|
|
|
|
|
autoComplete="email"
|
|
|
|
|
autoCorrect="off"
|
|
|
|
|
{...field}
|
|
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</FormItem>
|
|
|
|
|
)} />
|
|
|
|
|
<FormField control={form.control} name="password1" render={({ field }) => (
|
|
|
|
|
<FormItem>
|
|
|
|
|
<FormLabel>Password</FormLabel>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input type="password" {...field} />
|
|
|
|
|
</FormControl>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</FormItem>
|
|
|
|
|
)} />
|
|
|
|
|
<FormField control={form.control} name="password2" render={({ field }) => (
|
|
|
|
|
<FormItem>
|
|
|
|
|
<FormLabel>Confirm Password</FormLabel>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input type="password" {...field} />
|
|
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)} />
|
|
|
|
|
<FormField control={form.control} name="invitationCode" render={({ field }) => (
|
|
|
|
|
<FormItem>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input type="hidden" {...field} />
|
|
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)} />
|
|
|
|
|
<Button type="submit" disabled={isSubmitting}>
|
|
|
|
|
{isSubmitting && (
|
2023-12-05 06:34:02 +00:00
|
|
|
<IconSpinner className="mr-2 h-4 w-4 animate-spin" />
|
|
|
|
|
)}
|
|
|
|
|
Sign In
|
|
|
|
|
</Button>
|
2023-12-05 08:15:04 +00:00
|
|
|
</form>
|
|
|
|
|
</Form>
|
2023-12-05 06:34:02 +00:00
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|