'use client'; import { useState } from 'react'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { publicApi } from '@/lib/services'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; const ERROR_INPUT_CLASS = 'border-red-500 focus-visible:ring-red-500'; const schema = z.object({ name: z .string() .trim() .min(1, '请输入姓名') .max(50, '姓名不能超过 50 个字'), phone: z .string() .trim() .min(1, '请输入手机号') .regex(/^1[3-9]\d{9}$/, '请输入正确的手机号(11 位)'), email: z .string() .trim() .max(254, '邮箱长度不能超过 254') .email('邮箱格式不正确') .optional() .or(z.literal('')), content: z .string() .trim() .min(5, '留言内容至少 5 个字') .max(2000, '留言内容不能超过 2000 个字'), }); type FormData = z.infer; export function ContactForm() { const { register, handleSubmit, reset, formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(schema), mode: 'onTouched', reValidateMode: 'onChange', defaultValues: { name: '', phone: '', email: '', content: '' }, }); const [serverError, setServerError] = useState(null); const [success, setSuccess] = useState(false); const onSubmit = async (data: FormData) => { setServerError(null); setSuccess(false); try { await publicApi.submitMessage({ name: data.name, phone: data.phone, email: data.email || undefined, content: data.content, }); setSuccess(true); reset(); } catch (e) { setServerError((e as Error).message); } }; return (
{ e.preventDefault(); void handleSubmit(onSubmit)(e); }} className="space-y-4" >