'use client'; import { useEffect, useState, useCallback } from 'react'; import { z } from 'zod'; import dayjs from 'dayjs'; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from '@/components/ui/form'; import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; import { Gender } from '@/types/user'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Label } from '@/components/ui/label'; import { calculateAge, getDaysInMonth } from '@/lib/utils'; import { Textarea } from '@/components/ui/textarea'; import { Button } from '@/components/ui/button'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog'; const currentYear = dayjs().year(); const years = Array.from({ length: currentYear - 1950 + 1 }, (_, i) => `${1950 + i}`); const months = Array.from({ length: 12 }, (_, i) => `${i + 1}`.padStart(2, '0')); const monthTexts = Array.from({ length: 12 }, (_, i) => dayjs().month(i).format('MMM')); const characterFormSchema = z .object({ nickname: z .string() .trim() .min(1, 'Please Enter nickname') .min(2, 'Nickname must be between 2 and 20 characters') .max(20, 'Nickname must be less than 20 characters'), sex: z.enum(Gender, { message: 'Please select gender' }), year: z.string().min(1, 'Please select year'), month: z.string().min(1, 'Please select month'), day: z.string().min(1, 'Please select day'), profile: z.string().trim().optional(), }) .refine( (data) => { const age = calculateAge(data.year, data.month, data.day); return age >= 18; }, { message: 'Character age must be at least 18 years old', path: ['year'], } ) .refine( (data) => { if (data.profile) { if (data.profile.trim().length > 300) { return false; } return data.profile.trim().length >= 10; } return true; }, { message: 'At least 10 characters', path: ['profile'], } ); export default function Personal() { // 静态数据,模拟从接口获取的数据 const chatSettingData = { nickname: 'John', sex: Gender.MALE, birthday: dayjs('1995-06-15').valueOf(), whoAmI: 'A creative and passionate developer', }; const birthday = chatSettingData?.birthday ? dayjs(chatSettingData.birthday) : undefined; const form = useForm>({ resolver: zodResolver(characterFormSchema), defaultValues: { nickname: chatSettingData?.nickname || '', sex: chatSettingData?.sex, year: birthday?.year().toString() || undefined, month: birthday?.month() !== undefined ? (birthday.month() + 1).toString().padStart(2, '0') : undefined, day: birthday?.date().toString().padStart(2, '0') || undefined, profile: chatSettingData?.whoAmI || '', }, }); const selectedYear = form.watch('year'); const selectedMonth = form.watch('month'); const days = selectedYear && selectedMonth ? getDaysInMonth(selectedYear, selectedMonth) : []; const genderTexts = [ { value: Gender.MALE, label: 'Male', }, { value: Gender.FEMALE, label: 'Female', }, { value: Gender.OTHER, label: 'Other', }, ]; const gender = form.watch('sex'); const genderText = genderTexts.find((text) => text.value === gender)?.label; return ( <>
( Nickname )} />
Gender
{genderText}
Please note: gender cannot be changed after setting
( )} /> ( )} /> ( )} />
{form.formState.errors.year?.message || form.formState.errors.month?.message || form.formState.errors.day?.message}
( My Persona (Optional)