"use client" import { zodResolver } from "@hookform/resolvers/zod" import { useCallback, useEffect, useState } from "react" import { Controller, Resolver, useForm } from "react-hook-form" import { toast } from "sonner" import { z } from "zod/v4" import { Button } from "@/components/ui/button" 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 { OptionCombobox } from "@/components/option-combobox" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Textarea } from "@/components/ui/textarea" import { type AdminAgentTeam, type AdminAgentTeamSchedule, type CreateAdminAgentTeamSchedulePayload, fetchAgentTeamSchedule, fetchAgentTeamsAll } from "@/lib/api/admin" type ScheduleEditDialogProps = { open: boolean saving: boolean itemId: number | null onOpenChange: (open: boolean) => void onSubmit: (payload: CreateAdminAgentTeamSchedulePayload) => Promise } const sourceTypeOptions = [ { value: "manual", label: "手工录入" }, { value: "batch_import", label: "批量导入" }, { value: "template_generate", label: "模板生成" }, ] as const const emptyForm: EditForm = { teamId: "", startAt: "", endAt: "", sourceType: "manual", remark: "", } const editFormSchema = z.object({ teamId: z.string().trim().regex(/^\d+$/, "请选择客服组"), startAt: z.string().trim().min(1, "开始时间不能为空"), endAt: z.string().trim().min(1, "结束时间不能为空"), sourceType: z.enum(["manual", "batch_import", "template_generate"], { message: "请选择排班来源" }), remark: z.string().trim(), }) type EditForm = z.infer const editFormResolver = zodResolver(editFormSchema as never) as Resolver< z.input, undefined, z.output > function toDateTimeLocal(value?: string) { if (!value) { return "" } return value.replace(" ", "T").slice(0, 16) } function buildForm(item: AdminAgentTeamSchedule | null): EditForm { if (!item) { return emptyForm } return { teamId: String(item.teamId), startAt: toDateTimeLocal(item.startAt), endAt: toDateTimeLocal(item.endAt), sourceType: item.sourceType as EditForm["sourceType"], remark: item.remark || "", } } function buildPayload(form: EditForm): CreateAdminAgentTeamSchedulePayload { return { teamId: Number(form.teamId), startAt: form.startAt.trim(), endAt: form.endAt.trim(), sourceType: form.sourceType, remark: form.remark.trim(), } } export function EditDialog({ open, saving, itemId, onOpenChange, onSubmit, }: ScheduleEditDialogProps) { return ( {open ? ( ) : null} ) } type ScheduleEditDialogBodyProps = Omit function ScheduleEditDialogBody({ saving, itemId, onOpenChange, onSubmit, }: ScheduleEditDialogBodyProps) { const [teams, setTeams] = useState([]) const [loading, setLoading] = useState(false) const loadOptions = useCallback(async () => { try { const teamsData = await fetchAgentTeamsAll() setTeams(teamsData) } catch (error) { toast.error(error instanceof Error ? error.message : "加载选项失败") } }, []) const form = useForm< z.input, undefined, z.output >({ 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 fetchAgentTeamSchedule(itemId) reset(buildForm(data)) } catch (error) { toast.error(error instanceof Error ? error.message : "加载客服组排班详情失败") } finally { setLoading(false) } } void loadDetail() }, [itemId, reset]) useEffect(() => { void loadOptions() }, [loadOptions]) async function onFormSubmit(values: EditForm) { await onSubmit(buildPayload(values)) } return ( {itemId ? "编辑客服组排班" : "新建客服组排班"} {loading ? (
加载中...
) : (
客服组 ( ({ value: String(team.id), label: team.name, }))} placeholder="请选择客服组" searchPlaceholder="搜索客服组" onChange={field.onChange} /> )} />
开始时间 结束时间
排班来源 ( )} />
备注