"use client" import { useEffect, useMemo, useState } from "react" import { zodResolver } from "@hookform/resolvers/zod" import { Resolver, useForm } from "react-hook-form" import { z } from "zod/v4" import { type AdminUser, type UpdateAdminUserPayload, fetchUserDetail, } from "@/lib/api/admin" import { useI18n } from "@/i18n/provider" import { Button } from "@/components/ui/button" import { Drawer, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, } from "@/components/ui/drawer" import { Field, FieldContent, FieldError, FieldLabel, } from "@/components/ui/field" import { Input } from "@/components/ui/input" type UserEditDrawerProps = { open: boolean saving: boolean itemId: number | null onOpenChange: (open: boolean) => void onSubmit: (payload: UpdateAdminUserPayload) => Promise } const emptyForm: EditForm = { nickname: "", avatar: "", mobile: "", email: "", } type EditForm = { nickname: string avatar: string mobile: string email: string } function toNullableString(value: string) { const output = value.trim() return output ? output : null } function buildForm(item: AdminUser | null): EditForm { if (!item) { return emptyForm } return { nickname: item.nickname || "", avatar: item.avatar || "", mobile: item.mobile || "", email: item.email || "", } } function buildPayload(userId: number, form: EditForm): UpdateAdminUserPayload { return { id: userId, nickname: form.nickname.trim(), avatar: form.avatar.trim(), mobile: toNullableString(form.mobile), email: toNullableString(form.email), remark: "", } } export function EditDrawer({ open, saving, itemId, onOpenChange, onSubmit, }: UserEditDrawerProps) { return ( {open ? ( ) : null} ) } type UserEditDrawerBodyProps = { saving: boolean itemId: number | null onOpenChange: (open: boolean) => void onSubmit: (payload: UpdateAdminUserPayload) => Promise } function UserEditDrawerBody({ saving, itemId, onOpenChange, onSubmit, }: UserEditDrawerBodyProps) { const t = useI18n() const [loading, setLoading] = useState(false) const [item, setItem] = useState(null) const editFormSchema = useMemo( () => z.object({ nickname: z.string().trim().min(1, t("user.nicknameRequired")), avatar: z .string() .trim() .refine( (value) => value.length === 0 || /^https?:\/\/\S+$/i.test(value), t("user.avatarInvalid") ), mobile: z .string() .trim() .refine( (value) => value.length === 0 || /^[0-9+\-\s]{6,20}$/.test(value), t("user.mobileInvalid") ), email: z .string() .trim() .refine( (value) => value.length === 0 || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value), t("user.emailInvalid") ), }), [t] ) const editFormResolver = useMemo( () => zodResolver(editFormSchema as never) as Resolver, [editFormSchema] ) const form = useForm({ resolver: editFormResolver, defaultValues: emptyForm, }) const { handleSubmit, reset, register, formState: { errors }, } = form useEffect(() => { async function loadDetail() { if (!itemId) { setItem(null) reset(emptyForm) return } setLoading(true) try { const data = await fetchUserDetail(itemId) setItem(data) reset(buildForm(data)) } catch (error) { console.error("Failed to load user:", error) } finally { setLoading(false) } } void loadDetail() }, [itemId, reset]) async function onFormSubmit(values: EditForm) { if (!itemId) { return } await onSubmit(buildPayload(itemId, values)) } return ( {t("user.editTitle")} {t("user.currentUser", { username: item?.username || "-" })} {loading ? (
{t("user.loading")}
) : (
{t("user.nickname")} {t("user.avatar")} {t("user.mobile")} {t("user.email")}
)}
); }