refactor(admin-reports, i18n): remove rebate commission report and enhance localization
Removed the `getAdminReportRebateCommission` function and its references from the admin reports API and localization files. Updated CSS for improved money display handling in admin components. Enhanced localization support by adding new finance and support workspace entries in English, Nepali, and Chinese, improving user experience across the application.
This commit is contained in:
@@ -6,7 +6,6 @@ import { useTranslation } from "react-i18next";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
CalendarDays,
|
||||
CircleDollarSign,
|
||||
Database,
|
||||
FileDown,
|
||||
FileSpreadsheet,
|
||||
@@ -31,7 +30,6 @@ import {
|
||||
getAdminReportDailyProfit,
|
||||
getAdminReportPlayDimension,
|
||||
getAdminReportPlayerWinLoss,
|
||||
getAdminReportRebateCommission,
|
||||
} from "@/api/admin-reports";
|
||||
import {
|
||||
buildReportJobParameters,
|
||||
@@ -42,7 +40,13 @@ import { getAdminRiskPoolDetail, getAdminRiskPools } from "@/api/admin-risk";
|
||||
import { getAdminUsers } from "@/api/admin-users";
|
||||
import { getAdminTransferOrders } from "@/api/admin-wallet";
|
||||
import { adminHasAnyPermission } from "@/lib/admin-permissions";
|
||||
import { PRD_REPORT_EXPORT, PRD_REPORT_VIEW } from "@/lib/admin-prd";
|
||||
import {
|
||||
PRD_AUDIT_VIEW,
|
||||
PRD_REPORT_EXPORT,
|
||||
PRD_REPORT_VIEW,
|
||||
PRD_RISK_ACCESS_ANY,
|
||||
PRD_WALLET_TRANSFER_ACCESS_ANY,
|
||||
} from "@/lib/admin-prd";
|
||||
import { useAdminProfile } from "@/stores/admin-session";
|
||||
import { adminAgentDisplayLabel } from "@/components/admin/admin-agent-columns";
|
||||
import { AdminNoResourceState, AdminTableNoResourceRow } from "@/components/admin/admin-no-resource-state";
|
||||
@@ -73,6 +77,7 @@ import { useAdminCurrencyCatalog, getCachedAdminCurrencies } from "@/hooks/use-a
|
||||
import { useAdminDateTimeFormatter } from "@/hooks/use-admin-datetime-formatter";
|
||||
import { formatAdminInstant } from "@/lib/admin-datetime";
|
||||
import { getAdminRequestLocale } from "@/lib/admin-locale";
|
||||
import { AdminMoneyDisplay } from "@/components/admin/admin-money-display";
|
||||
import { signedMoneyClass } from "@/lib/admin-signed-money";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { formatAdminMinorUnits } from "@/lib/money";
|
||||
@@ -88,7 +93,6 @@ import type {
|
||||
AdminReportDailyProfitRow,
|
||||
AdminReportPlayDimensionRow,
|
||||
AdminReportPlayerWinLossRow,
|
||||
AdminReportRebateCommissionRow,
|
||||
} from "@/types/api/admin-reports";
|
||||
|
||||
export type ReportCategory = "profit" | "wallet" | "risk" | "audit";
|
||||
@@ -107,7 +111,6 @@ type ReportKey =
|
||||
| "hot_number_risk"
|
||||
| "play_dimension"
|
||||
| "sold_out_number"
|
||||
| "rebate_commission"
|
||||
| "admin_audit";
|
||||
|
||||
type ReportDefinition = {
|
||||
@@ -118,8 +121,22 @@ type ReportDefinition = {
|
||||
scope: string;
|
||||
fields: FieldKey[];
|
||||
connected: boolean;
|
||||
requiredAny: readonly string[];
|
||||
};
|
||||
|
||||
const PRD_REPORTS_VIEW_ACCESS_ANY = [PRD_REPORT_VIEW] as const;
|
||||
|
||||
const REPORTS: ReportDefinition[] = [
|
||||
{ key: "draw_profit", category: "profit", icon: Ticket, filterKind: "draw", scope: "drawNo", fields: ["drawNo"], connected: true, requiredAny: PRD_REPORTS_VIEW_ACCESS_ANY },
|
||||
{ key: "daily_profit", category: "profit", icon: CalendarDays, filterKind: "date", scope: "date", fields: ["period"], connected: true, requiredAny: PRD_REPORTS_VIEW_ACCESS_ANY },
|
||||
{ key: "player_win_loss", category: "profit", icon: Users, filterKind: "player_period", scope: "playerPeriod", fields: ["player", "period"], connected: true, requiredAny: PRD_REPORTS_VIEW_ACCESS_ANY },
|
||||
{ key: "player_transfer", category: "wallet", icon: WalletCards, filterKind: "player_period", scope: "playerPeriod", fields: ["player", "period"], connected: true, requiredAny: PRD_WALLET_TRANSFER_ACCESS_ANY },
|
||||
{ key: "hot_number_risk", category: "risk", icon: ShieldAlert, filterKind: "draw_number", scope: "drawNumber", fields: ["drawNo", "number"], connected: true, requiredAny: PRD_RISK_ACCESS_ANY },
|
||||
{ key: "play_dimension", category: "profit", icon: ListFilter, filterKind: "play_period", scope: "playPeriod", fields: ["play", "period"], connected: true, requiredAny: PRD_REPORTS_VIEW_ACCESS_ANY },
|
||||
{ key: "sold_out_number", category: "risk", icon: ShieldCheck, filterKind: "draw", scope: "drawNo", fields: ["drawNo"], connected: true, requiredAny: PRD_RISK_ACCESS_ANY },
|
||||
{ key: "admin_audit", category: "audit", icon: FileSpreadsheet, filterKind: "operator_period", scope: "operatorPeriod", fields: ["operator", "period"], connected: true, requiredAny: [PRD_AUDIT_VIEW] },
|
||||
];
|
||||
|
||||
type PreviewColumns = {
|
||||
primary: string;
|
||||
secondary: string;
|
||||
@@ -159,7 +176,6 @@ type ReportResult =
|
||||
| { key: "hot_number_risk"; rows: ExportRow[]; summary: StatCard[]; meta: ReportMeta | null; raw: AdminRiskPoolShowData }
|
||||
| { key: "play_dimension"; rows: ExportRow[]; summary: StatCard[]; meta: ReportMeta; raw: AdminReportPlayDimensionRow[] }
|
||||
| { key: "sold_out_number"; rows: ExportRow[]; summary: StatCard[]; meta: ReportMeta; raw: AdminRiskPoolRow[] }
|
||||
| { key: "rebate_commission"; rows: ExportRow[]; summary: StatCard[]; meta: ReportMeta; raw: AdminReportRebateCommissionRow[] }
|
||||
| { key: "admin_audit"; rows: ExportRow[]; summary: StatCard[]; meta: ReportMeta; raw: AdminAuditLogRow[] };
|
||||
|
||||
type StatCard = {
|
||||
@@ -182,18 +198,6 @@ type PlayOption = {
|
||||
label: string;
|
||||
};
|
||||
|
||||
const REPORTS: ReportDefinition[] = [
|
||||
{ key: "draw_profit", category: "profit", icon: Ticket, filterKind: "draw", scope: "drawNo", fields: ["drawNo"], connected: true },
|
||||
{ key: "daily_profit", category: "profit", icon: CalendarDays, filterKind: "date", scope: "date", fields: ["period"], connected: true },
|
||||
{ key: "player_win_loss", category: "profit", icon: Users, filterKind: "player_period", scope: "playerPeriod", fields: ["player", "period"], connected: true },
|
||||
{ key: "player_transfer", category: "wallet", icon: WalletCards, filterKind: "player_period", scope: "playerPeriod", fields: ["player", "period"], connected: true },
|
||||
{ key: "hot_number_risk", category: "risk", icon: ShieldAlert, filterKind: "draw_number", scope: "drawNumber", fields: ["drawNo", "number"], connected: true },
|
||||
{ key: "play_dimension", category: "profit", icon: ListFilter, filterKind: "play_period", scope: "playPeriod", fields: ["play", "period"], connected: true },
|
||||
{ key: "sold_out_number", category: "risk", icon: ShieldCheck, filterKind: "draw", scope: "drawNo", fields: ["drawNo"], connected: true },
|
||||
{ key: "rebate_commission", category: "profit", icon: CircleDollarSign, filterKind: "play_period", scope: "playPeriod", fields: ["play", "period"], connected: true },
|
||||
{ key: "admin_audit", category: "audit", icon: FileSpreadsheet, filterKind: "operator_period", scope: "operatorPeriod", fields: ["operator", "period"], connected: true },
|
||||
];
|
||||
|
||||
const emptyFilters: ReportFilters = {
|
||||
drawNo: "",
|
||||
drawId: null,
|
||||
@@ -414,38 +418,6 @@ function buildPlayDimensionRowsAndSummary(
|
||||
};
|
||||
}
|
||||
|
||||
function buildRebateCommissionRowsAndSummary(
|
||||
items: AdminReportRebateCommissionRow[],
|
||||
total: number,
|
||||
t: (key: string) => string,
|
||||
pageScopedLabel: (statKey: string) => string,
|
||||
currencyCode: string,
|
||||
): Pick<Extract<ReportResult, { key: "rebate_commission" }>, "rows" | "summary"> {
|
||||
let totalRebate = 0;
|
||||
let totalOrders = 0;
|
||||
|
||||
const rows = items.map((item) => {
|
||||
totalRebate += item.total_rebate_minor;
|
||||
totalOrders += item.order_count;
|
||||
return {
|
||||
play_code: item.play_code,
|
||||
total_rebate_minor: item.total_rebate_minor,
|
||||
order_count: item.order_count,
|
||||
ticket_item_count: item.ticket_item_count,
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
rows,
|
||||
summary: [
|
||||
{ label: t("preview.stats.records"), value: String(total) },
|
||||
{ label: t("preview.stats.currentPage"), value: String(items.length) },
|
||||
{ label: pageScopedLabel("rebate"), value: formatPlainMoney(totalRebate, currencyCode) },
|
||||
{ label: pageScopedLabel("orders"), value: String(totalOrders) },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
function metaFromList(meta: { current_page: number; per_page: number; total: number; last_page: number }): ReportMeta {
|
||||
return {
|
||||
total: meta.total,
|
||||
@@ -612,13 +584,6 @@ function defaultSummaryCards(
|
||||
{ label: t("preview.stats.currency"), value: t("preview.stats.notQueried") },
|
||||
{ label: t("preview.stats.usage"), value: t("preview.stats.notQueried") },
|
||||
];
|
||||
case "rebate_commission":
|
||||
return [
|
||||
{ label: t("preview.stats.records"), value: t("preview.stats.notQueried") },
|
||||
{ label: t("fields.play"), value: filters.play || t("filterAll") },
|
||||
{ label: t("preview.stats.rebate"), value: t("preview.stats.notQueried") },
|
||||
{ label: t("preview.stats.orders"), value: t("preview.stats.notQueried") },
|
||||
];
|
||||
case "admin_audit":
|
||||
return [
|
||||
{ label: t("preview.stats.records"), value: t("preview.stats.notQueried") },
|
||||
@@ -641,14 +606,15 @@ export function ReportsConsole({ initialCategory }: { initialCategory?: ReportCa
|
||||
const profile = useAdminProfile();
|
||||
const canViewReports = adminHasAnyPermission(profile?.permissions, [PRD_REPORT_VIEW]);
|
||||
const canExportReports = adminHasAnyPermission(profile?.permissions, [PRD_REPORT_EXPORT]);
|
||||
const permissionSlugs = useMemo(() => profile?.permissions ?? [], [profile?.permissions]);
|
||||
useAdminCurrencyCatalog();
|
||||
useAdminPlayTypeCatalog();
|
||||
const playCodeLabel = useAdminPlayCodeLabel();
|
||||
const formatTs = useAdminDateTimeFormatter();
|
||||
const filteredReports = useMemo(
|
||||
() => (initialCategory ? REPORTS.filter((report) => report.category === initialCategory) : REPORTS),
|
||||
[initialCategory],
|
||||
);
|
||||
const filteredReports = useMemo(() => {
|
||||
const visible = REPORTS.filter((report) => adminHasAnyPermission(permissionSlugs, report.requiredAny));
|
||||
return initialCategory ? visible.filter((report) => report.category === initialCategory) : visible;
|
||||
}, [initialCategory, permissionSlugs]);
|
||||
const [selectedKey, setSelectedKey] = useState<ReportKey>(
|
||||
filteredReports[0]?.key ?? REPORTS[0].key,
|
||||
);
|
||||
@@ -758,17 +724,6 @@ export function ReportsConsole({ initialCategory }: { initialCategory?: ReportCa
|
||||
extra: t("preview.columns.soldOut.extra"),
|
||||
time: t("preview.columns.soldOut.time"),
|
||||
};
|
||||
case "rebate_commission":
|
||||
return {
|
||||
primary: t("preview.columns.rebateCommission.primary"),
|
||||
secondary: t("preview.columns.rebateCommission.secondary"),
|
||||
metricA: t("preview.columns.rebateCommission.metricA"),
|
||||
metricB: t("preview.columns.rebateCommission.metricB"),
|
||||
metricC: t("preview.columns.rebateCommission.metricC"),
|
||||
status: t("preview.columns.rebateCommission.status"),
|
||||
extra: t("preview.columns.rebateCommission.extra"),
|
||||
time: t("preview.columns.rebateCommission.time"),
|
||||
};
|
||||
case "admin_audit":
|
||||
return {
|
||||
primary: t("preview.columns.adminAudit.primary"),
|
||||
@@ -1057,22 +1012,6 @@ export function ReportsConsole({ initialCategory }: { initialCategory?: ReportCa
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "rebate_commission": {
|
||||
const payload = await getAdminReportRebateCommission(
|
||||
reportListParams(filters, page, perPage),
|
||||
);
|
||||
const currencyCode = resolveDisplayCurrency(payload.currency_code);
|
||||
setDisplayCurrency(currencyCode);
|
||||
const next = buildRebateCommissionRowsAndSummary(payload.items, payload.meta.total, t, pageScopedLabel, currencyCode);
|
||||
setResult({
|
||||
key: "rebate_commission",
|
||||
raw: payload.items,
|
||||
rows: next.rows,
|
||||
meta: metaFromList(payload.meta),
|
||||
summary: next.summary,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "admin_audit": {
|
||||
const operatorId = filters.operatorId ?? parsePositiveInteger(filters.operator);
|
||||
const payload = await getAdminAuditLogs({
|
||||
@@ -1134,10 +1073,10 @@ export function ReportsConsole({ initialCategory }: { initialCategory?: ReportCa
|
||||
...prev,
|
||||
drawNo: drawNoFromUrl || prev.drawNo,
|
||||
}));
|
||||
if (drawNoFromUrl) {
|
||||
if (drawNoFromUrl && filteredReports.some((report) => report.key === "draw_profit")) {
|
||||
setSelectedKey("draw_profit");
|
||||
}
|
||||
}, [drawNoFromUrl]);
|
||||
}, [drawNoFromUrl, filteredReports]);
|
||||
|
||||
useEffect(() => {
|
||||
queueMicrotask(() => {
|
||||
@@ -1563,21 +1502,6 @@ export function ReportsConsole({ initialCategory }: { initialCategory?: ReportCa
|
||||
));
|
||||
}
|
||||
|
||||
if (result.key === "rebate_commission") {
|
||||
return result.raw.map((item) => (
|
||||
<TableRow key={item.play_code}>
|
||||
<TableCell className="font-medium">{playCodeLabel(item.play_code)}</TableCell>
|
||||
<TableCell>{item.order_count}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.total_rebate_minor, displayCurrency)}</TableCell>
|
||||
<TableCell className="text-center">{item.ticket_item_count}</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
</TableRow>
|
||||
));
|
||||
}
|
||||
|
||||
if (result.key === "admin_audit") {
|
||||
return result.raw.map((item) => (
|
||||
<TableRow key={item.id}>
|
||||
@@ -1598,6 +1522,10 @@ export function ReportsConsole({ initialCategory }: { initialCategory?: ReportCa
|
||||
|
||||
return (
|
||||
<div className="mx-auto flex w-full max-w-7xl flex-col gap-4">
|
||||
{filteredReports.length === 0 ? (
|
||||
<AdminNoResourceState message={t("empty")} />
|
||||
) : (
|
||||
<>
|
||||
<Card className="admin-list-card">
|
||||
<CardHeader className="admin-list-header pb-3">
|
||||
<div className="flex flex-col gap-3">
|
||||
@@ -1652,11 +1580,13 @@ export function ReportsConsole({ initialCategory }: { initialCategory?: ReportCa
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="grid gap-2 md:grid-cols-4">
|
||||
<div className="grid min-w-0 gap-2 md:grid-cols-4">
|
||||
{(result?.summary ?? defaultSummaryCards(selectedReport.key, filters, t)).map((item) => (
|
||||
<div key={item.label} className={cn("rounded-md border px-3 py-2.5", statTone(item.tone))}>
|
||||
<div key={item.label} className={cn("min-w-0 rounded-md border px-3 py-2.5", statTone(item.tone))}>
|
||||
<div className="text-xs text-muted-foreground">{item.label}</div>
|
||||
<div className="mt-0.5 truncate text-base font-semibold tabular-nums">{item.value}</div>
|
||||
<AdminMoneyDisplay as="div" value={item.value} size="md" className="mt-0.5">
|
||||
{item.value}
|
||||
</AdminMoneyDisplay>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -1722,6 +1652,8 @@ export function ReportsConsole({ initialCategory }: { initialCategory?: ReportCa
|
||||
) : null}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user