"use client"; import { Check, ChevronDown, Search } from "lucide-react"; import Link from "next/link"; import { useCallback, useEffect, useState } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; import { getSettlementPeriods, type SettlementPeriodRow } from "@/api/admin-agent-settlement"; import { getAdminIntegrationSites } from "@/api/admin-integration-sites"; import { AdminLoadingState } from "@/components/admin/admin-loading-state"; import { AdminPageGuide } from "@/components/admin/admin-page-guide"; import { ADMIN_DOC_LINKS } from "@/lib/admin-doc-links"; import { AdminNoIntegrationSiteState } from "@/components/admin/admin-no-integration-site-state"; import { AgentBillDetail } from "@/modules/settlement/agent-bill-detail"; import { SettlementCenterPeriodDetail } from "@/modules/settlement/settlement-center-period-detail"; import { parseSettlementCenterView, settlementCenterListHref, settlementPeriodViewHref, type SettlementPeriodView, } from "@/modules/settlement/settlement-center-nav"; import { SettlementPeriodWorkbench } from "@/modules/settlement/settlement-period-workbench"; import { formatAdminSiteLabel } from "@/lib/admin-site-display"; import { adminHasAnyPermission } from "@/lib/admin-permissions"; import { PRD_SETTLEMENT_AGENT_MANAGE } from "@/lib/admin-prd"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Button, buttonVariants } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { ScrollArea } from "@/components/ui/scroll-area"; import { cn } from "@/lib/utils"; import { useAdminProfile } from "@/stores/admin-session"; type SiteOption = { id: number; label: string; code: string; currency_code: string }; export function SettlementCenterShell(): React.ReactElement { const { t } = useTranslation(["settlementCenter", "common"]); const router = useRouter(); const searchParams = useSearchParams(); const profile = useAdminProfile(); const boundAgent = profile?.agent ?? null; const { siteId: siteFromUrl, periodId: activePeriodId, view: activeView } = parseSettlementCenterView( searchParams.get("site"), searchParams.get("period"), searchParams.get("view"), ); const canOperateBills = profile?.is_super_admin === true || adminHasAnyPermission(profile?.permissions, [PRD_SETTLEMENT_AGENT_MANAGE]); const canManagePeriods = canOperateBills && boundAgent === null; const canFinanceAdjustments = canOperateBills && boundAgent === null; const [siteOptions, setSiteOptions] = useState([]); const [sitesReady, setSitesReady] = useState(() => boundAgent?.admin_site_id != null); const [adminSiteId, setAdminSiteId] = useState(null); const [sitePickerOpen, setSitePickerOpen] = useState(false); const [siteKeyword, setSiteKeyword] = useState(""); const [periods, setPeriods] = useState([]); const [periodsReady, setPeriodsReady] = useState(false); const [detailBillId, setDetailBillId] = useState(null); const [refreshKey, setRefreshKey] = useState(0); const [periodLookupDone, setPeriodLookupDone] = useState(false); useEffect(() => { if (boundAgent?.admin_site_id) { const label = formatAdminSiteLabel( boundAgent.admin_site_name, boundAgent.site_code ?? boundAgent.code, ); setSiteOptions([{ id: boundAgent.admin_site_id, label, code: boundAgent.site_code ?? boundAgent.code ?? "", currency_code: "NPR", }]); setAdminSiteId(boundAgent.admin_site_id); setSitesReady(true); return; } setSitesReady(false); void getAdminIntegrationSites() .then((sites) => { const options = (sites.items ?? []).map((site) => ({ id: site.id, label: formatAdminSiteLabel(site.name, site.code), code: site.code, currency_code: site.currency_code ?? "NPR", })); setSiteOptions(options); setAdminSiteId((current) => { if (siteFromUrl !== null && options.some((site) => site.id === siteFromUrl)) { return siteFromUrl; } if (current !== null && options.some((site) => site.id === current)) { return current; } return options[0]?.id ?? null; }); }) .catch(() => { setSiteOptions([]); }) .finally(() => { setSitesReady(true); }); }, [boundAgent, siteFromUrl]); const siteId = adminSiteId ?? siteOptions[0]?.id ?? null; const selectedSite = siteOptions.find((s) => s.id === siteId) ?? null; const siteLabel = selectedSite?.label ?? null; const currency = siteOptions.find((s) => s.id === siteId)?.currency_code ?? "NPR"; const filteredSites = siteKeyword.trim().toLowerCase() ? siteOptions.filter((site) => site.label.toLowerCase().includes(siteKeyword.trim().toLowerCase())) : siteOptions; const boundAgentIdentity = boundAgent !== null ? (

{t("boundAgentIdentity", { defaultValue: "经营身份:{{agent}} · 账号 {{username}}", agent: boundAgent.name || boundAgent.code, username: profile?.username ?? "—", })}

) : null; const siteSelector = siteOptions.length > 0 && siteId !== null ? ( } > {siteLabel ?? "—"} {selectedSite?.code ?? ""}
setSiteKeyword(event.target.value)} placeholder={t("siteSearch", { defaultValue: "搜索站点名称" })} className="pl-9" />
{filteredSites.map((site) => { const active = site.id === siteId; return ( ); })} {filteredSites.length === 0 ? (
{t("common:states.empty", { defaultValue: "暂无数据" })}
) : null}
) : null; const headerActions = siteSelector !== null || boundAgentIdentity !== null ? (
{siteSelector} {boundAgentIdentity}
) : null; const loadPeriods = useCallback(async (): Promise => { if (siteId === null) { return []; } try { const data = await getSettlementPeriods({ admin_site_id: siteId }); const items = data.items ?? []; setPeriods(items); setPeriodsReady(true); return items; } catch { setPeriods([]); setPeriodsReady(true); toast.error(t("periods.loadFailed", { defaultValue: "账期加载失败" })); return []; } }, [siteId, t]); useEffect(() => { setPeriodsReady(false); void loadPeriods(); }, [loadPeriods]); const activePeriod = activePeriodId !== null ? (periods.find((row) => row.id === activePeriodId) ?? null) : null; const openPeriodView = (periodId: number, view: SettlementPeriodView): void => { router.push(settlementPeriodViewHref(periodId, view, siteId)); }; const isListMode = activePeriodId === null; useEffect(() => { if (boundAgent !== null || siteId === null) { return; } if (isListMode) { if (siteFromUrl === siteId) { return; } router.replace(settlementCenterListHref(siteId)); return; } if (activePeriodId !== null && siteFromUrl !== siteId) { router.replace(settlementPeriodViewHref(activePeriodId, activeView, siteId)); } }, [activePeriodId, activeView, boundAgent, isListMode, router, siteFromUrl, siteId]); useEffect(() => { setPeriodLookupDone(false); }, [activePeriodId, siteId]); useEffect(() => { if (!periodsReady || activePeriodId === null || siteId === null) { return; } if (activePeriod !== null) { setPeriodLookupDone(true); return; } let cancelled = false; void getSettlementPeriods().then((data) => { if (cancelled) { return; } const match = (data.items ?? []).find((row) => row.id === activePeriodId); if (match?.admin_site_id && match.admin_site_id !== siteId) { setAdminSiteId(match.admin_site_id); router.replace(settlementPeriodViewHref(activePeriodId, activeView, match.admin_site_id)); return; } setPeriodLookupDone(true); }); return () => { cancelled = true; }; }, [activePeriod, activePeriodId, activeView, periodsReady, router, siteId]); const shellBootstrapping = !sitesReady || (siteId !== null && !periodsReady); return (
{shellBootstrapping ? ( ) : siteId === null && siteOptions.length === 0 && boundAgent === null ? ( ) : siteId === null ? (

{t("empty.noSite", { defaultValue: "请选择站点。" })}

) : isListMode ? ( openPeriodView(id, "bills")} onReloadPeriods={loadPeriods} onPeriodOpened={() => { setRefreshKey((n) => n + 1); }} onPeriodClosed={(result) => { setRefreshKey((n) => n + 1); const n = result?.unsettled_ticket_count ?? 0; if (n > 0) { toast.warning( t("toast.periodClosedUnsettled", { defaultValue: "已关账,仍有 {{count}} 笔注单未结算。", count: n, }), ); } }} /> ) : activePeriod === null ? ( !periodLookupDone ? ( ) : (

{t("periodDetail.notFound", { defaultValue: "账期不存在或已切换站点,请返回列表。" })}

{t("periodDetail.back", { defaultValue: "返回账期列表" })}
) ) : ( )} !open && setDetailBillId(null)}> {t("actions.billDetail", { defaultValue: "账单详情" })} {detailBillId !== null ? (
{ void loadPeriods(); setRefreshKey((n) => n + 1); }} />
) : null}
); }