diff --git a/src/app/admin/(shell)/admin-roles/page.tsx b/src/app/admin/(shell)/admin-roles/page.tsx
index 0fac604..a30a8be 100644
--- a/src/app/admin/(shell)/admin-roles/page.tsx
+++ b/src/app/admin/(shell)/admin-roles/page.tsx
@@ -1,11 +1,9 @@
import { ModuleScaffold } from "@/components/admin/module-scaffold";
import { AdminRolesConsole } from "@/modules/admin-roles/admin-roles-console";
-import { adminRolesModuleMeta } from "@/modules/admin-roles/meta";
+import { buildPageMetadata } from "@/lib/page-metadata";
import type { Metadata } from "next";
-export const metadata: Metadata = {
- title: adminRolesModuleMeta.title,
-};
+export const metadata: Metadata = buildPageMetadata("adminRoles", "title");
export default function AdminRolesPage() {
return (
diff --git a/src/app/admin/(shell)/admin-users/page.tsx b/src/app/admin/(shell)/admin-users/page.tsx
index 56f030e..97b6f67 100644
--- a/src/app/admin/(shell)/admin-users/page.tsx
+++ b/src/app/admin/(shell)/admin-users/page.tsx
@@ -1,11 +1,9 @@
import { ModuleScaffold } from "@/components/admin/module-scaffold";
import { AdminUsersConsole } from "@/modules/admin-users/admin-users-console";
-import { adminUsersModuleMeta } from "@/modules/admin-users/meta";
+import { buildPageMetadata } from "@/lib/page-metadata";
import type { Metadata } from "next";
-export const metadata: Metadata = {
- title: adminUsersModuleMeta.title,
-};
+export const metadata: Metadata = buildPageMetadata("adminUsers", "title");
export default function AdminUsersPage() {
return (
diff --git a/src/app/admin/(shell)/audit-logs/page.tsx b/src/app/admin/(shell)/audit-logs/page.tsx
index 520eada..6b2923b 100644
--- a/src/app/admin/(shell)/audit-logs/page.tsx
+++ b/src/app/admin/(shell)/audit-logs/page.tsx
@@ -1,11 +1,9 @@
import { ModuleScaffold } from "@/components/admin/module-scaffold";
-import { auditLogsModuleMeta } from "@/modules/audit/meta";
import { AuditLogsConsole } from "@/modules/audit/audit-logs-console";
+import { buildPageMetadata } from "@/lib/page-metadata";
import type { Metadata } from "next";
-export const metadata: Metadata = {
- title: auditLogsModuleMeta.title,
-};
+export const metadata: Metadata = buildPageMetadata("audit", "title");
export default function AdminAuditLogsPage() {
return (
diff --git a/src/app/admin/(shell)/config/jackpot/page.tsx b/src/app/admin/(shell)/config/jackpot/page.tsx
index 527d678..6a8ad54 100644
--- a/src/app/admin/(shell)/config/jackpot/page.tsx
+++ b/src/app/admin/(shell)/config/jackpot/page.tsx
@@ -1,19 +1,5 @@
-import { Suspense } from "react";
+import { redirect } from "next/navigation";
-import { JackpotConfigScreen } from "@/modules/jackpot/jackpot-config-screen";
-import { jackpotModuleMeta } from "@/modules/jackpot/meta";
-import type { Metadata } from "next";
-
-export const metadata: Metadata = {
- title: jackpotModuleMeta.title,
-};
-
-export default function AdminConfigJackpotPage() {
- return (
-
{error}
: null} {loadingDetail || loadingTypes ? ( @@ -489,7 +494,7 @@ export function OddsConfigDocScreen() {{t("odds.missingScopeRow", { ns: "config", scope })}
@@ -547,11 +554,17 @@ export function OddsConfigDocScreen() { {rebatePercentUi} )} -{t("odds.rebateRateHint", { ns: "config" })}
+ {!embedded ? ( +{t("odds.rebateRateHint", { ns: "config" })}
+ ) : null}{t("states.loading", { ns: "common" })}
) : null} + > + ); + + if (embedded) { + return ( +{v.toFixed(2)}%
-{t("capUsage")}
-{t("noPoolData")}
- ) : ( - rows.map((row) => { - const u = row.usage_ratio ?? 0; - const h = Math.max(8, (u / maxU) * 100); - return ( -{t("numbersByUsage")}
-{t("noSoldOutNumbers")}
-{total}
-{t("soldOutTotal")}
-{t("states.noData", { ns: "common" })}
+ )} +{t("states.noData", { ns: "common" })}
+ )} +{t("todayBetTotal")}
-- {finance ? formatMoneyMinor(finance.total_bet_minor, currency) : "—"} -
-
-
{t("currentPayout")}
-- {finance ? formatMoneyMinor(finance.total_payout_minor, currency) : "—"} -
-
-
{t("currentProfit")}
-- {finance ? formatSignedMoneyMinor(finance.approx_house_gross_minor, currency) : "—"} -
-
-
{t("currentDraw")}
-{hall?.draw_no ?? "—"}
-- {t("drawSequence", { sequence: hall?.sequence_no ?? "—" })} - · - - - {hallStatusLabel} - -
- {drawId != null ? ( - - {t("drawDetails")} - - ) : null} -{t("ticketCount")}
-- {finance != null ? finance.ticket_item_count.toLocaleString("zh-CN") : "—"} -
-- {t("relatedBetAmount")}{" "} - - {finance ? formatMoneyMinor(finance.total_bet_minor, currency) : "—"} - -
-{t("riskCapUsage")}
-- {t("lockedAndCap", { - locked: formatMoneyMinor(riskLocked, currency), - cap: formatMoneyMinor(riskCap, currency), - })} -
-{t("states.noData", { ns: "common" })}
+{t("states.noData", { ns: "common" })}
)}{t("states.noData", { ns: "common" })}
+ )} +{t("states.noData", { ns: "common" })}
+ )} +{t("pendingReviewResults")}
-- {pendingReview ?? "—"} -
+{t("pendingReviewResults")}
+{pendingReview ?? "—"}
{t("abnormalTransferOrders")}
-- {abnormalTransferTotal ?? "—"} -
+{t("abnormalTransferOrders")}
+{abnormalTransferTotal ?? "—"}
{label}
+{value}
+ {hint ?+ {t("lockedAndCap", { + locked: formatMoney(locked, currency), + cap: formatMoney(cap, currency), + })} +
+{t("noFinanceActivity")}
; + } + + const winW = (win / bet) * 100; + const jpW = (jackpot / bet) * 100; + const grossW = Math.max(0, (gross / bet) * 100); + const payoutRate = ((payout / bet) * 100).toFixed(1); + + const segments = [ + { key: "win", width: winW, className: "bg-chart-2", label: t("winPayout"), value: win }, + { key: "jackpot", width: jpW, className: "bg-chart-4", label: t("jackpotPayout"), value: jackpot }, + { key: "gross", width: grossW, className: "bg-primary", label: t("houseGross"), value: gross }, + ].filter((s) => s.width > 0.05); + + return ( ++ {t("payoutRateOfBet", { rate: payoutRate })} +
+{s.label}
+{formatMoney(s.value, currency)}
+{t("noPayoutYet")}
; + } + + const winPct = (win / total) * 100; + const items = [ + { label: t("winPayout"), value: win, pct: winPct, className: "bg-chart-2" }, + { label: t("jackpotPayout"), value: jackpot, pct: 100 - winPct, className: "bg-chart-4" }, + ]; + + return ( +{formatMoney(item.value, currency)}
+{t("noPoolData")}
; + } + + return ( +{t("noSoldOutNumbers")}
; + } + + let acc = 0; + const parts = entries + .filter((e) => buckets[e.key] > 0) + .map((e) => { + const frac = buckets[e.key] / total; + const start = acc; + acc += frac; + return { ...e, frac, start }; + }); + + const gradientStops = + parts.length === 1 + ? `${parts[0].color} 0deg 360deg` + : parts + .map((p) => { + const a0 = p.start * 360; + const a1 = (p.start + p.frac) * 360; + return `${p.color} ${a0}deg ${a1}deg`; + }) + .join(", "); + + return ( +{total}
+{t("soldOutTotal")}
+{pending_review}
+{t("batchPending")}
+{published}
+{t("batchPublished")}
+{total}
+{t("batchTotal")}
+{t("noSettlementBatches")}
; + } + + const counts = new Map