"use client"; import { useCallback, useEffect, useMemo, useState } from "react"; import { zodResolver } from "@hookform/resolvers/zod"; import { CheckIcon, ChevronsUpDownIcon } from "lucide-react"; import { Controller, type Resolver, useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod/v4"; import { type AdminAgentTeam, type CreateAdminAgentTeamPayload, fetchAgentTeam, fetchUsersAll, type AdminUser, } from "@/lib/api/admin"; import { OptionCombobox } from "@/components/option-combobox"; import { Button } from "@/components/ui/button"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Field, FieldContent, FieldError, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Textarea } from "@/components/ui/textarea"; import { useI18n } from "@/i18n/provider"; import { Status } from "@/lib/generated/enums"; type TFunction = (key: string, values?: Record) => string; type TeamEditDialogProps = { open: boolean; saving: boolean; itemId: number | null; onOpenChange: (open: boolean) => void; onSubmit: (payload: CreateAdminAgentTeamPayload) => Promise; }; const emptyForm: EditForm = { name: "", leaderUserId: "0", status: String(Status.Ok), description: "", remark: "", }; type EditForm = { name: string; leaderUserId: string; status: string; description: string; remark: string; }; function createEditFormSchema(t: TFunction) { return z.object({ name: z.string().trim().min(1, t("agentProfile.teamNameRequired")), leaderUserId: z.string().trim().regex(/^\d+$/, t("agentProfile.leaderInvalid")), status: z.enum([String(Status.Ok), String(Status.Disabled)], { message: t("agentProfile.teamStatusRequired"), }), description: z.string().trim(), remark: z.string().trim(), }); } function getStatusOptions(t: TFunction) { return [ { value: String(Status.Ok), label: t("agentProfile.enabled") }, { value: String(Status.Disabled), label: t("agentProfile.disabled") }, ]; } function buildForm(item: AdminAgentTeam | null): EditForm { if (!item) { return emptyForm; } return { name: item.name, leaderUserId: String(item.leaderUserId), status: String(item.status), description: item.description || "", remark: item.remark || "", }; } function buildPayload(form: EditForm): CreateAdminAgentTeamPayload { return { name: form.name.trim(), leaderUserId: Number(form.leaderUserId), status: Number(form.status), description: form.description.trim(), remark: form.remark.trim(), }; } export function EditDialog({ open, saving, itemId, onOpenChange, onSubmit, }: TeamEditDialogProps) { return ( {open ? ( ) : null} ); } type TeamEditDialogBodyProps = Omit; function TeamEditDialogBody({ saving, itemId, onOpenChange, onSubmit, }: TeamEditDialogBodyProps) { const t = useI18n(); const [users, setUsers] = useState([]); const [userSelectOpen, setUserSelectOpen] = useState(false); const [loading, setLoading] = useState(false); const userOptions = users.map((user) => ({ value: String(user.id), label: `${user.nickname || user.username} (${user.username})`, })); const statusOptions = useMemo(() => getStatusOptions(t), [t]); const loadUsers = useCallback(async () => { try { const data = await fetchUsersAll(); setUsers(data); } catch (error) { toast.error(error instanceof Error ? error.message : t("agentProfile.loadUsersFailed")); } }, [t]); const editFormSchema = useMemo(() => createEditFormSchema(t), [t]); const editFormResolver = useMemo( () => zodResolver(editFormSchema) as Resolver, [editFormSchema], ); const form = useForm({ resolver: editFormResolver, defaultValues: emptyForm, }); const { control, handleSubmit, reset, register, formState: { errors }, } = form; useEffect(() => { async function loadDetail() { if (!itemId) { reset(emptyForm); return; } setLoading(true); try { const data = await fetchAgentTeam(itemId); reset(buildForm(data)); } catch (error) { toast.error(error instanceof Error ? error.message : t("agentProfile.loadTeamDetailFailed")); } finally { setLoading(false); } } void loadDetail(); }, [itemId, reset, t]); useEffect(() => { void loadUsers(); }, [loadUsers]); async function onFormSubmit(values: EditForm) { await onSubmit(buildPayload(values)); } return ( {itemId ? t("agentProfile.teamEditTitle") : t("agentProfile.teamCreateTitle")} {loading ? (
{t("agentProfile.loading")}
) : (
{t("agentProfile.teamName")} {t("agentProfile.leader")} ( } > {field.value === "0" ? t("agentProfile.noLeader") : userOptions.find((option) => option.value === field.value)?.label ?? t("agentProfile.selectLeader")} {t("agentProfile.emptyUser")} { field.onChange("0"); setUserSelectOpen(false); }} > {t("agentProfile.noLeader")} {userOptions.map((option) => ( { field.onChange(option.value); setUserSelectOpen(false); }} > {option.label} ))} )} /> {t("agentProfile.status")} ( )} /> {t("agentProfile.description")} {t("agentProfile.remark")}