Refactor agents console and related components
Some checks failed
lotteryadmin CI / build (push) Has been cancelled

- Simplified share rate calculation in AgentsConsole by removing unnecessary checks and directly setting the profile share rate.
- Updated the use of `profileParentCaps` to always return total share rate in the agent profile.
- Removed unused variables and memoized calculations for improved performance.
- Cleaned up imports in various files, removing unused components and optimizing the code structure.
- Added `tRef` dependency to several useEffect hooks to ensure proper reactivity to translation changes.
- Enhanced report preview tables with better label handling for various statuses and actions.
- Updated wallet filter options to align with player-side transaction types.
- Introduced new properties in types for better type safety and clarity.
This commit is contained in:
2026-06-30 17:55:00 +08:00
parent 6c3ded5b75
commit 4484a7a77a
56 changed files with 320 additions and 158 deletions

View File

@@ -9,11 +9,11 @@ import { Download, RefreshCw } from "lucide-react";
import { downloadAdminReportJob, getAdminReportJobs } from "@/api/admin-report-jobs";
import { AdminRowActionsMenu } from "@/components/admin/admin-row-actions-menu";
import { AdminNoResourceState, AdminTableNoResourceRow } from "@/components/admin/admin-no-resource-state";
import { AdminTableNoResourceRow } from "@/components/admin/admin-no-resource-state";
import { AdminStatusBadge } from "@/components/admin/admin-status-badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { AdminLoadingState, AdminLoadingInline, AdminTableLoadingRow } from "@/components/admin/admin-loading-state";
import { AdminTableLoadingRow } from "@/components/admin/admin-loading-state";
import {
Table,
TableBody,

View File

@@ -7,7 +7,8 @@ import { AdminNoResourceState, AdminTableNoResourceRow } from "@/components/admi
import { AdminStatusBadge } from "@/components/admin/admin-status-badge";
import { AdminLoadingInline, AdminTableLoadingRow } from "@/components/admin/admin-loading-state";
import { DrawStatusBadge } from "@/modules/draws/draw-status-badge";
import { drawStatusLabel } from "@/modules/draws/draw-display";
import { drawStatusLabel, settlementBatchStatusLabel } from "@/modules/draws/draw-display";
import { riskActionTypeLabel } from "@/modules/risk/risk-display";
import { useAdminPlayCodeLabel } from "@/hooks/use-admin-play-type-catalog";
import { useAdminDateTimeFormatter } from "@/hooks/use-admin-datetime-formatter";
import {
@@ -36,6 +37,18 @@ type ReportPreviewTableProps = {
displayCurrency: string;
};
function reportValueLabel(
scope: string,
value: string | null | undefined,
t: (key: string, options?: { defaultValue?: string }) => string,
): string {
if (value == null || value === "") {
return "—";
}
return t(`labels.${scope}.${value}`, { defaultValue: value });
}
export function ReportPreviewTable({
report,
result,
@@ -135,7 +148,9 @@ export function ReportPreviewTable({
<TableRow key={batch.id} className="bg-muted/10">
<TableCell>#{batch.id}</TableCell>
<TableCell>
<AdminStatusBadge status={batch.status}>{batch.status}</AdminStatusBadge>
<AdminStatusBadge status={batch.status}>
{settlementBatchStatusLabel(batch.status, t)}
</AdminStatusBadge>
</TableCell>
<TableCell className="text-right">{batch.total_ticket_count}</TableCell>
<TableCell className="text-right">{batch.total_win_count}</TableCell>
@@ -269,9 +284,11 @@ export function ReportPreviewTable({
<TableRow key={item.id}>
<TableCell className="font-mono text-xs">{item.transfer_no}</TableCell>
<TableCell>{optionText(item.username, item.nickname) || item.player_id}</TableCell>
<TableCell>{item.direction}</TableCell>
<TableCell>{reportValueLabel("transferDirection", item.direction, t)}</TableCell>
<TableCell>
<AdminStatusBadge status={item.status}>{item.status}</AdminStatusBadge>
<AdminStatusBadge status={item.status}>
{reportValueLabel("transferStatus", item.status, t)}
</AdminStatusBadge>
</TableCell>
<TableCell className="text-right">
{item.currency_code} {item.amount}
@@ -333,7 +350,7 @@ export function ReportPreviewTable({
{result.raw.logs.items.map((item) => (
<TableRow key={item.id}>
<TableCell className="font-mono text-xs">#{item.id}</TableCell>
<TableCell>{item.action_type}</TableCell>
<TableCell>{riskActionTypeLabel(item.action_type, t)}</TableCell>
<TableCell className="text-right">
{formatPlainMoney(item.amount, result.raw.currency_code)}
</TableCell>
@@ -402,11 +419,11 @@ export function ReportPreviewTable({
{result.raw.map((item) => (
<TableRow key={item.id}>
<TableCell className="font-mono text-xs">#{item.id}</TableCell>
<TableCell>{item.operator_type}</TableCell>
<TableCell>{reportValueLabel("operatorType", item.operator_type, t)}</TableCell>
<TableCell>{item.operator_id}</TableCell>
<TableCell>{item.module_code}</TableCell>
<TableCell>{item.action_code}</TableCell>
<TableCell>{item.target_type || "—"}</TableCell>
<TableCell>{item.module_label || item.module_code}</TableCell>
<TableCell>{item.action_label || item.action_code}</TableCell>
<TableCell>{item.target_label || item.target_type || "—"}</TableCell>
<TableCell>{formatTs(item.created_at)}</TableCell>
</TableRow>
))}
@@ -417,4 +434,4 @@ export function ReportPreviewTable({
default:
return <AdminLoadingInline />;
}
}
}

View File

@@ -71,7 +71,6 @@ import {
drawRowsFromSummary,
emptyFilters,
emptySearch,
formatExportInstant,
formatPlainMoney,
formatUsagePercent,
headlineStats,
@@ -434,6 +433,7 @@ export function ReportsConsole({ initialCategory = "profit" }: ReportsConsolePro
return;
}
void queryReport();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [page, perPage]);
function updateFilter<K extends keyof ReportFilters>(key: K, value: ReportFilters[K]): void {

View File

@@ -19,7 +19,7 @@ import type {
AdminReportPlayerWinLossRow,
} from "@/types/api/admin-reports";
import type { FieldKey, ReportDefinition, ReportKey } from "@/modules/reports/reports-definitions";
import type { ReportDefinition, ReportKey } from "@/modules/reports/reports-definitions";
export type ExportCell = string | number | null;
export type ExportRow = Record<string, ExportCell>;
@@ -128,7 +128,8 @@ export function formatPlainMoney(value: number, currencyCode: string | null | un
return formatAdminMinorUnits(value, currencyCode || "NPR");
}
export function signedProfitCell(amount: number, currencyCode: string | null | undefined): string {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function signedProfitCell(amount: number, _currencyCode: string | null | undefined): string {
return cn("tabular-nums", signedMoneyClass(amount, true));
}
@@ -238,13 +239,9 @@ export function buildDailyProfitRowsAndSummary(
pageScopedLabel: (statKey: string) => string,
currencyCode: string,
): Pick<Extract<ReportResult, { key: "daily_profit" }>, "rows" | "summary"> {
let totalBet = 0;
let totalPayout = 0;
let totalGross = 0;
const rows = items.map((item) => {
totalBet += item.total_bet_minor;
totalPayout += item.total_payout_minor;
totalGross += item.approx_house_gross_minor;
return {
business_date: item.business_date,
@@ -306,11 +303,9 @@ export function buildPlayDimensionRowsAndSummary(
t: (key: string) => string,
currencyCode: string,
): Pick<Extract<ReportResult, { key: "play_dimension" }>, "rows" | "summary"> {
let totalBet = 0;
let totalGross = 0;
const rows = items.map((item) => {
totalBet += item.total_bet_minor;
totalGross += item.approx_house_gross_minor;
return {
play_code: item.play_code,