feat(ui): enhance table and admin components with improved layout and status display
- Updated global CSS to center-align table headers and cells, ensuring a consistent layout. - Modified admin table components to replace switches with status badges for better clarity. - Enhanced internationalization support by adding new strings for version actions and validation messages in multiple locales. - Refactored configuration document screens to include version selection and improved user feedback on status changes.
This commit is contained in:
@@ -312,20 +312,25 @@ function parsePositiveInteger(value: string): number | null {
|
||||
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;
|
||||
}
|
||||
|
||||
async function resolveDraw(filters: ReportFilters): Promise<{ id: number; draw_no: string }> {
|
||||
async function resolveDraw(
|
||||
filters: ReportFilters,
|
||||
t: (key: string, options?: { ns?: string; drawNo?: string }) => string,
|
||||
): Promise<{ id: number; draw_no: string }> {
|
||||
if (filters.drawId && filters.drawNo.trim()) {
|
||||
return { id: filters.drawId, draw_no: filters.drawNo.trim() };
|
||||
}
|
||||
|
||||
const drawNo = filters.drawNo.trim();
|
||||
if (!drawNo) {
|
||||
throw new LotteryApiBizError("请输入期号", -1, null);
|
||||
throw new LotteryApiBizError(t("validation.drawNoRequired", { ns: "reports" }), -1, null);
|
||||
}
|
||||
|
||||
const data = await getAdminDraws({ draw_no: drawNo, page: 1, per_page: 1 });
|
||||
const matched = data.items.find((item) => item.draw_no === drawNo) ?? data.items[0];
|
||||
if (!matched) {
|
||||
throw new LotteryApiBizError("未找到期号", -1, { drawNo });
|
||||
throw new LotteryApiBizError(t("validation.drawNoNotFound", { ns: "reports", drawNo }), -1, {
|
||||
drawNo,
|
||||
});
|
||||
}
|
||||
return { id: matched.id, draw_no: matched.draw_no };
|
||||
}
|
||||
@@ -459,7 +464,7 @@ export function ReportsConsole() {
|
||||
try {
|
||||
switch (selectedReport.key) {
|
||||
case "draw_profit": {
|
||||
const draw = await resolveDraw(filters);
|
||||
const draw = await resolveDraw(filters, t);
|
||||
const summary = await getAdminDrawFinanceSummary(draw.id);
|
||||
setResult({
|
||||
key: "draw_profit",
|
||||
@@ -580,7 +585,7 @@ export function ReportsConsole() {
|
||||
if (!filters.number.trim()) {
|
||||
throw new LotteryApiBizError(t("validation.drawNoNumberRequired"), -1, null);
|
||||
}
|
||||
const draw = await resolveDraw(filters);
|
||||
const draw = await resolveDraw(filters, t);
|
||||
const detail = await getAdminRiskPoolDetail(draw.id, filters.number.trim(), { page, per_page: perPage });
|
||||
const rows: ExportRow[] = [
|
||||
{
|
||||
@@ -627,7 +632,7 @@ export function ReportsConsole() {
|
||||
break;
|
||||
}
|
||||
case "sold_out_number": {
|
||||
const draw = await resolveDraw(filters);
|
||||
const draw = await resolveDraw(filters, t);
|
||||
const payload = await getAdminRiskPools(draw.id, { page, per_page: perPage, sold_out_only: true, sort: "number_asc" });
|
||||
const rows = payload.items.map((item) => ({
|
||||
draw_id: payload.draw_id,
|
||||
@@ -1022,22 +1027,22 @@ export function ReportsConsole() {
|
||||
<TableRow>
|
||||
<TableCell className="font-medium">{summary.draw_no}</TableCell>
|
||||
<TableCell>{summary.draw_status}</TableCell>
|
||||
<TableCell className="text-right">{summary.order_count}</TableCell>
|
||||
<TableCell className="text-right">{summary.ticket_item_count}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(summary.total_bet_minor, summary.currency_code)}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(summary.total_payout_minor, summary.currency_code)}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(summary.approx_house_gross_minor, summary.currency_code)}</TableCell>
|
||||
<TableCell className="text-center">{summary.order_count}</TableCell>
|
||||
<TableCell className="text-center">{summary.ticket_item_count}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(summary.total_bet_minor, summary.currency_code)}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(summary.total_payout_minor, summary.currency_code)}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(summary.approx_house_gross_minor, summary.currency_code)}</TableCell>
|
||||
<TableCell>{summary.settlement_batches.length}</TableCell>
|
||||
</TableRow>
|
||||
{summary.settlement_batches.map((batch) => (
|
||||
<TableRow key={batch.id} className="bg-muted/15">
|
||||
<TableCell>#{batch.id}</TableCell>
|
||||
<TableCell>{batch.status}</TableCell>
|
||||
<TableCell className="text-right">{batch.total_ticket_count}</TableCell>
|
||||
<TableCell className="text-right">{batch.total_win_count}</TableCell>
|
||||
<TableCell className="text-right">-</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(batch.total_payout_amount, summary.currency_code)}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(batch.total_jackpot_payout_amount, summary.currency_code)}</TableCell>
|
||||
<TableCell className="text-center">{batch.total_ticket_count}</TableCell>
|
||||
<TableCell className="text-center">{batch.total_win_count}</TableCell>
|
||||
<TableCell className="text-center">-</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(batch.total_payout_amount, summary.currency_code)}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(batch.total_jackpot_payout_amount, summary.currency_code)}</TableCell>
|
||||
<TableCell>{formatTs(batch.finished_at)}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
@@ -1052,7 +1057,7 @@ export function ReportsConsole() {
|
||||
<TableCell>{optionText(item.username, item.nickname) || item.player_id}</TableCell>
|
||||
<TableCell>{item.direction}</TableCell>
|
||||
<TableCell>{item.status}</TableCell>
|
||||
<TableCell className="text-right">{item.currency_code} {item.amount}</TableCell>
|
||||
<TableCell className="text-center">{item.currency_code} {item.amount}</TableCell>
|
||||
<TableCell>{item.external_ref_no || "-"}</TableCell>
|
||||
<TableCell>{item.fail_reason || "-"}</TableCell>
|
||||
<TableCell>{formatTs(item.created_at)}</TableCell>
|
||||
@@ -1066,9 +1071,9 @@ export function ReportsConsole() {
|
||||
<TableRow>
|
||||
<TableCell className="font-medium">{result.raw.pool.normalized_number}</TableCell>
|
||||
<TableCell>{result.raw.draw_no}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(result.raw.pool.total_cap_amount, result.raw.currency_code)}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(result.raw.pool.locked_amount, result.raw.currency_code)}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(result.raw.pool.remaining_amount, result.raw.currency_code)}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(result.raw.pool.total_cap_amount, result.raw.currency_code)}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(result.raw.pool.locked_amount, result.raw.currency_code)}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(result.raw.pool.remaining_amount, result.raw.currency_code)}</TableCell>
|
||||
<TableCell>{result.raw.pool.is_sold_out ? t("yes") : t("no")}</TableCell>
|
||||
<TableCell>{result.raw.pool.usage_ratio == null ? "-" : `${result.raw.pool.usage_ratio}%`}</TableCell>
|
||||
<TableCell>v{result.raw.pool.version}</TableCell>
|
||||
@@ -1077,7 +1082,7 @@ export function ReportsConsole() {
|
||||
<TableRow key={item.id} className="bg-muted/15">
|
||||
<TableCell className="font-mono text-xs">#{item.id}</TableCell>
|
||||
<TableCell>{item.action_type}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.amount, result.raw.currency_code)}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.amount, result.raw.currency_code)}</TableCell>
|
||||
<TableCell>{playCodeLabel(item.play_code)}</TableCell>
|
||||
<TableCell>{item.ticket_no || "-"}</TableCell>
|
||||
<TableCell>{item.player_id || "-"}</TableCell>
|
||||
@@ -1094,9 +1099,9 @@ export function ReportsConsole() {
|
||||
<TableRow key={item.normalized_number}>
|
||||
<TableCell className="font-medium">{item.normalized_number}</TableCell>
|
||||
<TableCell>{filters.drawNo}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.total_cap_amount, null)}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.locked_amount, null)}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.remaining_amount, null)}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.total_cap_amount, null)}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.locked_amount, null)}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.remaining_amount, null)}</TableCell>
|
||||
<TableCell>{item.is_sold_out ? t("yes") : t("no")}</TableCell>
|
||||
<TableCell>{item.usage_ratio == null ? "-" : `${item.usage_ratio}%`}</TableCell>
|
||||
<TableCell>v{item.version}</TableCell>
|
||||
@@ -1109,9 +1114,9 @@ export function ReportsConsole() {
|
||||
<TableRow key={item.business_date}>
|
||||
<TableCell className="font-medium">{item.business_date}</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.total_bet_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.total_payout_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.approx_house_gross_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.total_bet_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.total_payout_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.approx_house_gross_minor, "NPR")}</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
@@ -1124,9 +1129,9 @@ export function ReportsConsole() {
|
||||
<TableRow key={item.player_id}>
|
||||
<TableCell className="font-medium">{item.username}</TableCell>
|
||||
<TableCell>ID {item.player_id}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.total_bet_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.total_payout_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.net_win_loss_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.total_bet_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.total_payout_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.net_win_loss_minor, "NPR")}</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
@@ -1139,9 +1144,9 @@ export function ReportsConsole() {
|
||||
<TableRow key={`${item.play_code}-${item.dimension}`}>
|
||||
<TableCell className="font-medium">{playCodeLabel(item.play_code)}</TableCell>
|
||||
<TableCell>{item.dimension}D</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.total_bet_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.total_payout_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.approx_house_gross_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.total_bet_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.total_payout_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.approx_house_gross_minor, "NPR")}</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
@@ -1154,8 +1159,8 @@ export function ReportsConsole() {
|
||||
<TableRow key={item.play_code}>
|
||||
<TableCell className="font-medium">{playCodeLabel(item.play_code)}</TableCell>
|
||||
<TableCell>{item.order_count}</TableCell>
|
||||
<TableCell className="text-right">{formatPlainMoney(item.total_rebate_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-right">{item.ticket_item_count}</TableCell>
|
||||
<TableCell className="text-center">{formatPlainMoney(item.total_rebate_minor, "NPR")}</TableCell>
|
||||
<TableCell className="text-center">{item.ticket_item_count}</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
<TableCell>-</TableCell>
|
||||
@@ -1294,9 +1299,9 @@ export function ReportsConsole() {
|
||||
<TableRow>
|
||||
<TableHead>{t("preview.columns.primary")}</TableHead>
|
||||
<TableHead>{t("preview.columns.secondary")}</TableHead>
|
||||
<TableHead className="text-right">{t("preview.columns.metricA")}</TableHead>
|
||||
<TableHead className="text-right">{t("preview.columns.metricB")}</TableHead>
|
||||
<TableHead className="text-right">{t("preview.columns.metricC")}</TableHead>
|
||||
<TableHead className="text-center">{t("preview.columns.metricA")}</TableHead>
|
||||
<TableHead className="text-center">{t("preview.columns.metricB")}</TableHead>
|
||||
<TableHead className="text-center">{t("preview.columns.metricC")}</TableHead>
|
||||
<TableHead>{t("preview.columns.status")}</TableHead>
|
||||
<TableHead>{t("preview.columns.extra")}</TableHead>
|
||||
<TableHead>{t("preview.columns.time")}</TableHead>
|
||||
|
||||
Reference in New Issue
Block a user