Files
nashel-frontend/src/features/auth/RegisterForm.tsx
T

306 lines
14 KiB
TypeScript

"use client"
import * as React from "react"
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
import { Loader2 } from "lucide-react"
import { useRouter } from "next/navigation"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { RichTextEditor } from "@/components/ui/rich-text-editor"
import { Checkbox } from "@/components/ui/checkbox"
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { useSessionStore } from "@/entities/session/store"
const registerSchema = z.object({
phone: z.string().min(10, "Номер телефона должен содержать минимум 10 цифр"),
firstName: z.string()
.min(2, "Имя должно содержать минимум 2 символа")
.regex(/^[^0-9]*$/, "Имя не должно содержать цифры"),
lastName: z.string()
.min(2, "Фамилия должна содержать минимум 2 символа")
.regex(/^[^0-9]*$/, "Фамилия не должна содержать цифры"),
isCompany: z.boolean(),
companyName: z.string().optional(),
inn: z.string().optional(),
description: z.string()
.max(2048, "Описание не может превышать 2048 символов")
.optional(),
password: z.string().min(6, "Пароль должен быть не менее 6 символов"),
confirmPassword: z.string().min(6),
}).refine((data) => data.password === data.confirmPassword, {
message: "Пароли не совпадают",
path: ["confirmPassword"],
}).refine((data) => !data.isCompany || (data.companyName && data.companyName.length >= 2), {
message: "Название компании обязательно",
path: ["companyName"],
}).refine((data) => !data.isCompany || (data.inn && data.inn.length === 10), {
message: "ИНН должен содержать 10 цифр",
path: ["inn"],
})
type RegisterValues = z.infer<typeof registerSchema>
export function RegisterForm() {
const router = useRouter()
const { register, isLoading } = useSessionStore()
const form = useForm<RegisterValues>({
resolver: zodResolver(registerSchema),
defaultValues: {
phone: "",
firstName: "",
lastName: "",
isCompany: false,
companyName: "",
inn: "",
description: "",
password: "",
confirmPassword: "",
},
})
const isCompany = form.watch("isCompany")
async function onSubmit(values: RegisterValues) {
try {
const submitData: any = {
phone: values.phone,
firstName: values.firstName,
lastName: values.lastName,
password: values.password,
confirmPassword: values.confirmPassword,
role: values.isCompany ? "Company" : "User"
};
// Добавляем данные компании только если регистрируемся как компания
if (values.isCompany) {
if (values.companyName) {
submitData.companyName = values.companyName;
}
if (values.inn) {
submitData.inn = values.inn;
}
}
// Добавляем описание
if (values.description) {
submitData.description = values.description;
}
await register(submitData)
router.push("/auth/login")
} catch (error) {
console.error(error)
form.setError("root", { message: "Ошибка при регистрации. Возможно, номер уже занят." })
}
}
return (
<Card className="w-full max-w-md mx-auto">
<CardHeader>
<CardTitle className="text-2xl">Регистрация</CardTitle>
<CardDescription>
Создайте аккаунт, чтобы начать пользоваться сервисом.
</CardDescription>
</CardHeader>
<CardContent>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="firstName"
render={({ field }) => (
<FormItem>
<FormLabel>Имя</FormLabel>
<FormControl>
<Input
placeholder="Иван"
value={field.value || ""}
onChange={field.onChange}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="lastName"
render={({ field }) => (
<FormItem>
<FormLabel>Фамилия</FormLabel>
<FormControl>
<Input
placeholder="Иванов"
value={field.value || ""}
onChange={field.onChange}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name="phone"
render={({ field }) => (
<FormItem>
<FormLabel>Телефон</FormLabel>
<FormControl>
<Input
placeholder="+7 (999) 000-00-00"
value={field.value || ""}
onChange={field.onChange}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="isCompany"
render={({ field }) => (
<FormItem className="flex flex-row items-center gap-4 space-y-0 rounded-md border p-4">
<FormControl>
<Checkbox
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<FormLabel className="text-sm font-medium cursor-pointer peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
Я представитель компании
</FormLabel>
</FormItem>
)}
/>
{isCompany && (
<>
<FormField
control={form.control}
name="companyName"
render={({ field }) => (
<FormItem>
<FormLabel>Название компании</FormLabel>
<FormControl>
<Input
placeholder="ООО 'Ромашка'"
value={field.value || ""}
onChange={field.onChange}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="inn"
render={({ field }) => (
<FormItem>
<FormLabel>ИНН</FormLabel>
<FormControl>
<Input
placeholder="1234567890"
maxLength={10}
value={field.value || ""}
onChange={field.onChange}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</>
)}
<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<FormLabel>Описание (необязательно)</FormLabel>
<FormControl>
<RichTextEditor
content={field.value || ""}
onChange={field.onChange}
placeholder={isCompany
? "Расскажите о вашей компании...\n\nВы можете использовать кнопки на панели для форматирования текста."
: "Расскажите о себе и вашем опыте...\n\nВы можете использовать кнопки на панели для форматирования текста."
}
maxLength={2048}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Пароль</FormLabel>
<FormControl>
<Input
type="password"
placeholder="******"
value={field.value || ""}
onChange={field.onChange}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="confirmPassword"
render={({ field }) => (
<FormItem>
<FormLabel>Подтвердите пароль</FormLabel>
<FormControl>
<Input
type="password"
placeholder="******"
value={field.value || ""}
onChange={field.onChange}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{form.formState.errors.root && (
<p className="text-sm font-medium text-destructive">
{form.formState.errors.root.message}
</p>
)}
<Button type="submit" className="w-full bg-blue-600 hover:bg-blue-700" disabled={isLoading}>
{isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
Зарегистрироваться
</Button>
</form>
</Form>
</CardContent>
</Card>
)
}