"use client"; import { PanelLeftCloseIcon, PanelLeftOpenIcon, UserCogIcon, } from "lucide-react"; import { useCallback, useMemo, useState } from "react"; import { DashboardCrudPage, type DashboardCrudColumn, type DashboardCrudFilter, } from "@/components/dashboard/crud"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { createAgentProfile, deleteAgentProfile, fetchAgentProfiles, updateAgentProfile, type AdminAgentProfile, type AdminAgentTeam, type CreateAdminAgentProfilePayload, } from "@/lib/api/admin"; import { useI18n } from "@/i18n/provider"; import { ServiceStatus } from "@/lib/generated/enums"; import { formatDateTime } from "@/lib/utils"; import { EditDialog } from "./_components/edit"; import { AgentTeamSidebar } from "./_components/team-sidebar"; type TFunction = (key: string, values?: Record) => string; function getServiceStatusOptions(t: TFunction) { return [ { value: "all", label: t("agentProfile.allStatuses") }, { value: String(ServiceStatus.Idle), label: t("agentProfile.statusIdle") }, { value: String(ServiceStatus.Busy), label: t("agentProfile.statusBusy") }, ]; } function getStatusLabel(value: number, t: TFunction) { return ( getServiceStatusOptions(t).find((item) => item.value === String(value)) ?.label ?? String(value) ); } export default function DashboardAgentsPage() { const t = useI18n(); const serviceStatusOptions = useMemo(() => getServiceStatusOptions(t), [t]); const [selectedTeam, setSelectedTeam] = useState(null); const [sidebarCollapsed, setSidebarCollapsed] = useState(false); const handleTeamsChange = useCallback((nextTeams: AdminAgentTeam[]) => { setSelectedTeam((current) => { if (nextTeams.length === 0) { return null; } if (!current) { return nextTeams[0]; } return nextTeams.find((item) => item.id === current.id) ?? nextTeams[0]; }); }, []); const filters = useMemo( () => [ { name: "displayName", label: t("agentProfile.filterDisplayName"), placeholder: t("agentProfile.filterDisplayName"), defaultValue: "", trim: true, className: "w-full sm:w-72", }, { name: "agentCode", label: t("agentProfile.filterAgentCode"), placeholder: t("agentProfile.filterAgentCode"), defaultValue: "", trim: true, className: "w-full sm:w-44", }, { name: "serviceStatus", label: t("agentProfile.allStatuses"), type: "select", defaultValue: "all", allValue: "all", options: serviceStatusOptions, className: "w-full sm:w-36", }, ], [serviceStatusOptions, t], ); const columns = useMemo[]>( () => [ { key: "agent", label: t("agentProfile.columnAgent"), render: (item) => (
{item.avatar ? ( {item.displayName} ) : ( )}
{item.displayName}
{item.nickname || item.username || t("agentProfile.userFallback", { id: item.userId })}
{t("agentProfile.agentCode", { code: item.agentCode })}
), }, { key: "rules", label: t("agentProfile.columnRules"), render: (item) => ( <> {getStatusLabel(item.serviceStatus, t)}
{t("agentProfile.capacityPriority", { capacity: item.maxConcurrentCount, priority: item.priorityLevel, })}
), }, { key: "dispatch", label: t("agentProfile.columnDispatch"), render: (item) => (
{item.autoAssignEnabled ? t("agentProfile.autoAssign") : t("agentProfile.noAutoAssign")} {item.receiveOfflineMessage ? t("agentProfile.offlineReceive") : t("agentProfile.noOfflineReceive")}
), }, { key: "recent", label: t("agentProfile.columnRecent"), render: (item) => ( <>
{t("agentProfile.onlineAt", { time: formatDateTime(item.lastOnlineAt), })}
{t("agentProfile.statusAt", { time: formatDateTime(item.lastStatusAt), })}
), }, ], [t], ); return (
key={selectedTeam?.id ?? "all"} layout="fragment" tableShellClassName="min-h-0" filters={filters} columns={columns} fetchList={(query) => fetchAgentProfiles({ teamId: selectedTeam?.id, displayName: typeof query.displayName === "string" ? query.displayName : undefined, agentCode: typeof query.agentCode === "string" ? query.agentCode : undefined, serviceStatus: typeof query.serviceStatus === "string" ? query.serviceStatus : undefined, page: Number(query.page), limit: Number(query.limit), }) } getItemId={(item) => item.id} createItem={createAgentProfile} updateItem={(item, payload) => updateAgentProfile({ id: item.id, ...payload }) } deleteItem={(item) => deleteAgentProfile(item.id)} renderEditDialog={({ open, saving, itemId, onOpenChange, onSubmit, }) => ( )} labels={{ refresh: t("agentProfile.refresh"), create: t("agentProfile.new"), query: t("agentProfile.query"), loading: t("agentProfile.loadingRows"), empty: selectedTeam ? t("agentProfile.emptyTeamRows") : t("agentProfile.emptyRows"), actions: t("agentProfile.columnActions"), edit: t("agentProfile.edit"), delete: t("agentProfile.delete"), processing: t("agentProfile.deleting"), moreActions: (item) => t("agentProfile.moreActions", { name: item.displayName }), loadFailed: t("agentProfile.loadFailed"), saveFailed: t("agentProfile.saveFailed"), deleteFailed: t("agentProfile.deleteFailed"), created: (payload) => t("agentProfile.created", { name: payload.displayName }), updated: (item) => t("agentProfile.updated", { name: item.displayName }), deleted: (item) => t("agentProfile.deleted", { name: item.displayName }), }} />
); }