Files
lotteryAdmin/src/modules/settlement/agent-settlement-reports-panel.tsx
kang 24fd7c10bd feat(settlement, admin): introduce new types and functions for downline share and settlement period hints
Added new types for downline share breakdown and settlement period open hints to enhance the agent settlement API. Updated the admin console components to support these new features, improving the user experience with better data presentation and interaction. Additionally, refined the date range field to accommodate new calendar markers and hints, ensuring a more intuitive interface for managing settlement periods.
2026-06-12 16:01:42 +08:00

129 lines
3.8 KiB
TypeScript

"use client";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import {
getAgentSettlementReport,
type AgentSettlementReportResponse,
type AgentSettlementReportType,
} from "@/api/admin-agent-settlement";
import { AdminLoadingState } from "@/components/admin/admin-loading-state";
import { AgentSettlementReportView } from "@/modules/settlement/agent-settlement-report-view";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useAdminProfile } from "@/stores/admin-session";
const ALL_REPORT_TYPES: AgentSettlementReportType[] = [
"summary",
"player_win_loss",
"agent_share",
"rebate",
"credit",
"unpaid_bills",
"overdue",
"platform_pnl",
"draw_period",
];
type AgentSettlementReportsPanelProps = {
adminSiteId: number;
settlementPeriodId: number | null;
currencyCode: string;
};
export function AgentSettlementReportsPanel({
adminSiteId,
settlementPeriodId,
currencyCode,
}: AgentSettlementReportsPanelProps): React.ReactElement {
const { t } = useTranslation(["agents", "common"]);
const profile = useAdminProfile();
const reportTypes = useMemo(
() =>
profile?.agent != null
? ALL_REPORT_TYPES.filter((type) => type !== "platform_pnl")
: ALL_REPORT_TYPES,
[profile?.agent],
);
const [reportType, setReportType] = useState<AgentSettlementReportType>("summary");
const [response, setResponse] = useState<AgentSettlementReportResponse | null>(null);
const [loading, setLoading] = useState(false);
const load = useCallback(async () => {
setLoading(true);
try {
const res = await getAgentSettlementReport({
type: reportType,
settlement_period_id: settlementPeriodId ?? undefined,
admin_site_id: adminSiteId,
});
setResponse(res);
} finally {
setLoading(false);
}
}, [adminSiteId, reportType, settlementPeriodId]);
useEffect(() => {
void load();
}, [load]);
const reportTypeLabel = (type: AgentSettlementReportType): string =>
t(`settlementReports.types.${type}`, { defaultValue: type });
return (
<div className="space-y-4 rounded-lg border border-border/60 p-4">
<div className="flex flex-wrap items-end gap-3">
<div className="space-y-1">
<Label>{t("settlementReports.type", { defaultValue: "报表类型" })}</Label>
<Select
modal={false}
value={reportType}
onValueChange={(v) => setReportType(v as AgentSettlementReportType)}
>
<SelectTrigger className="w-52">
<SelectValue>{() => reportTypeLabel(reportType)}</SelectValue>
</SelectTrigger>
<SelectContent>
{reportTypes.map((key) => (
<SelectItem key={key} value={key}>
{reportTypeLabel(key)}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{settlementPeriodId === null ? (
<p className="text-xs text-muted-foreground pb-1">
{t("settlementReports.noPeriodHint", {
defaultValue: "未选具体账期时使用近 7 日区间;平台盈亏需选择账期。",
})}
</p>
) : null}
</div>
<p className="text-xs text-muted-foreground">
{t("settlementReports.footnote", {
defaultValue: "本组报表为信用占成盘账期口径,与「佣金/回水」旧钱包报表不同。",
})}
</p>
{loading ? (
<AdminLoadingState minHeight="8rem" />
) : response ? (
<AgentSettlementReportView
reportType={reportType}
data={response.data}
currencyCode={currencyCode}
/>
) : null}
</div>
);
}