Added new translations for agent management and settlement features in English, Nepali, and Chinese, improving multi-language support. Updated the agents console to reflect changes in funding modes and player details, enhancing user experience. Refactored the admin permission gate to include new logic for handling bound line agents, ensuring better permission management. Additionally, streamlined the UI for agent-related pages and improved navigation to the settlement center, consolidating related functionalities for better accessibility.
173 lines
6.6 KiB
TypeScript
173 lines
6.6 KiB
TypeScript
"use client";
|
||
|
||
import { useTranslation } from "react-i18next";
|
||
|
||
import type { SettlementLedgerRow } from "@/api/admin-agent-settlement";
|
||
import { AdminNoResourceState } from "@/components/admin/admin-no-resource-state";
|
||
import { AdminLoadingState } from "@/components/admin/admin-loading-state";
|
||
import { AdminStatusBadge } from "@/components/admin/admin-status-badge";
|
||
import { PlayerLedgerSourceBadge } from "@/components/admin/player-funding-badges";
|
||
import { useAdminDateTimeFormatter } from "@/hooks/use-admin-datetime-formatter";
|
||
import { formatDashboardMoneyMinor } from "@/modules/dashboard/use-dashboard-analytics";
|
||
import { SettlementLedgerRowActions } from "@/modules/settlement/settlement-ledger-row-actions";
|
||
import {
|
||
creditLedgerReasonLabel,
|
||
settlementAdjustmentTypeLabel,
|
||
settlementBillStatusLabel,
|
||
} from "@/modules/settlement/settlement-status-label";
|
||
import {
|
||
Table,
|
||
TableBody,
|
||
TableCell,
|
||
TableHead,
|
||
TableHeader,
|
||
TableRow,
|
||
} from "@/components/ui/table";
|
||
|
||
type SettlementCreditLedgerTableProps = {
|
||
rows: SettlementLedgerRow[];
|
||
loading: boolean;
|
||
currencyCode: string;
|
||
canManage: boolean;
|
||
onOpenBill: (billId: number) => void;
|
||
onRefresh: () => void;
|
||
showStatusColumn?: boolean;
|
||
};
|
||
|
||
function ledgerBizLabel(
|
||
row: SettlementLedgerRow,
|
||
t: ReturnType<typeof useTranslation<["settlementCenter", "agents"]>>["t"],
|
||
): string {
|
||
if (row.entry_kind === "payment") {
|
||
return t("creditLedger.reason.payment_record", { defaultValue: "账单收付" });
|
||
}
|
||
if (row.entry_kind === "adjustment") {
|
||
return settlementAdjustmentTypeLabel(row.biz_type, t);
|
||
}
|
||
|
||
return creditLedgerReasonLabel(row.biz_type, t);
|
||
}
|
||
|
||
function ledgerSourceForBadge(row: SettlementLedgerRow): string | null {
|
||
if (row.entry_kind === "credit") {
|
||
return "credit_ledger";
|
||
}
|
||
if (row.entry_kind === "payment") {
|
||
return "wallet_txn";
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
export function SettlementCreditLedgerTable({
|
||
rows,
|
||
loading,
|
||
currencyCode,
|
||
canManage,
|
||
onOpenBill,
|
||
onRefresh,
|
||
showStatusColumn = false,
|
||
}: SettlementCreditLedgerTableProps): React.ReactElement {
|
||
const { t } = useTranslation(["settlementCenter", "agents", "common"]);
|
||
const formatDt = useAdminDateTimeFormatter();
|
||
|
||
if (loading) {
|
||
return <AdminLoadingState />;
|
||
}
|
||
|
||
if (rows.length === 0) {
|
||
return <AdminNoResourceState />;
|
||
}
|
||
|
||
return (
|
||
<div className="admin-table-shell overflow-x-auto">
|
||
<Table>
|
||
<TableHeader>
|
||
<TableRow>
|
||
<TableHead>{t("creditLedger.columns.txn", { defaultValue: "流水号" })}</TableHead>
|
||
<TableHead>{t("creditLedger.columns.player", { defaultValue: "玩家" })}</TableHead>
|
||
<TableHead>{t("creditLedger.columns.reason", { defaultValue: "业务类型" })}</TableHead>
|
||
<TableHead>{t("creditLedger.columns.ref", { defaultValue: "关联" })}</TableHead>
|
||
<TableHead className="text-right">
|
||
{t("creditLedger.columns.amount", { defaultValue: "金额" })}
|
||
</TableHead>
|
||
<TableHead>{t("creditLedger.columns.channel", { defaultValue: "渠道" })}</TableHead>
|
||
{showStatusColumn ? (
|
||
<TableHead>{t("creditLedger.columns.status", { defaultValue: "状态" })}</TableHead>
|
||
) : null}
|
||
<TableHead>{t("creditLedger.columns.time", { defaultValue: "时间" })}</TableHead>
|
||
<TableHead className="sticky right-0 z-10 w-14 bg-muted text-center shadow-[-1px_0_0_rgba(203,213,225,0.7)]">
|
||
{t("common:table.actions", { defaultValue: "操作" })}
|
||
</TableHead>
|
||
</TableRow>
|
||
</TableHeader>
|
||
<TableBody>
|
||
{rows.map((row) => {
|
||
const signed = row.signed_amount ?? (row.direction === 1 ? row.amount : -row.amount);
|
||
const playerLabel =
|
||
row.username?.trim() ||
|
||
row.nickname?.trim() ||
|
||
row.site_player_id?.trim() ||
|
||
`#${row.player_id}`;
|
||
const badgeSource = ledgerSourceForBadge(row);
|
||
|
||
return (
|
||
<TableRow key={row.row_key ?? `${row.entry_kind}-${row.id}`}>
|
||
<TableCell className="font-mono text-xs">{row.txn_no}</TableCell>
|
||
<TableCell>
|
||
<span className="font-medium">{playerLabel}</span>
|
||
<span className="ml-1 text-xs text-muted-foreground">#{row.player_id}</span>
|
||
</TableCell>
|
||
<TableCell>{ledgerBizLabel(row, t)}</TableCell>
|
||
<TableCell className="text-xs text-muted-foreground">
|
||
{row.biz_no ?? (row.settlement_bill_id ? `bill#${row.settlement_bill_id}` : "—")}
|
||
</TableCell>
|
||
<TableCell
|
||
className={`text-right tabular-nums font-medium ${signed < 0 ? "text-destructive" : "text-emerald-700"}`}
|
||
>
|
||
{signed < 0 ? "−" : "+"}
|
||
{formatDashboardMoneyMinor(Math.abs(signed), row.currency_code || currencyCode)}
|
||
</TableCell>
|
||
<TableCell className="text-xs text-muted-foreground">
|
||
{badgeSource ? (
|
||
<PlayerLedgerSourceBadge ledgerSource={badgeSource} />
|
||
) : (
|
||
t("creditLedger.entryKind.adjustment", { defaultValue: "调账流水" })
|
||
)}
|
||
</TableCell>
|
||
{showStatusColumn ? (
|
||
<TableCell>
|
||
{row.bill_status ? (
|
||
<AdminStatusBadge status={row.bill_status}>
|
||
{settlementBillStatusLabel(row.bill_status, t)}
|
||
</AdminStatusBadge>
|
||
) : (
|
||
<AdminStatusBadge status="posted">
|
||
{t("ledgerPanel.rowPosted", { defaultValue: "已记账" })}
|
||
</AdminStatusBadge>
|
||
)}
|
||
</TableCell>
|
||
) : null}
|
||
<TableCell className="text-xs text-muted-foreground whitespace-nowrap">
|
||
{row.created_at ? formatDt(row.created_at) : "—"}
|
||
</TableCell>
|
||
<TableCell
|
||
className="sticky right-0 z-10 bg-card text-center shadow-[-1px_0_0_rgba(203,213,225,0.7)]"
|
||
onClick={(e) => e.stopPropagation()}
|
||
>
|
||
<SettlementLedgerRowActions
|
||
row={row}
|
||
canManage={canManage}
|
||
onOpenBill={onOpenBill}
|
||
onRefresh={onRefresh}
|
||
/>
|
||
</TableCell>
|
||
</TableRow>
|
||
);
|
||
})}
|
||
</TableBody>
|
||
</Table>
|
||
</div>
|
||
);
|
||
}
|