{t("agents:lineProvision.description", { defaultValue: - "将一级代理绑定到已有接入站点,并配置后台登录账号与占成、授信、回水。代理编码创建后不可修改。", + "将一级代理绑定到已有接入站点,并配置后台登录账号与占成、授信、回水。", })}{" "} -
+ {t("lineUi.awaitingRootAgentTitle", { + defaultValue: "本站尚未开通一级代理", + })} +
++ {t("lineUi.awaitingRootAgentHint", { + defaultValue: + "一级代理需由平台超级管理员在「开通一级代理」中创建。开通后您可在此管理下级代理、占成与授信。", + })} +
+{t("title", { defaultValue: "代理管理" })} diff --git a/src/modules/dashboard/agent-dashboard-console.tsx b/src/modules/dashboard/agent-dashboard-console.tsx index c9cc869..8513116 100644 --- a/src/modules/dashboard/agent-dashboard-console.tsx +++ b/src/modules/dashboard/agent-dashboard-console.tsx @@ -1,20 +1,8 @@ "use client"; -import Link from "next/link"; import { useCallback, useMemo, useState, type ReactElement } from "react"; import { useTranslation } from "react-i18next"; -import { - BarChart3, - Flame, - Landmark, - Network, - RefreshCw, - Sparkles, - Ticket, - TrendingUp, - Users, - Wallet, -} from "lucide-react"; +import { BarChart3, RefreshCw, TrendingUp, Users, Wallet } from "lucide-react"; import { getAdminDashboard } from "@/api/admin-dashboard"; import { useAsyncEffect } from "@/hooks/use-async-effect"; @@ -22,24 +10,18 @@ import { useAdminDateTimeFormatter } from "@/hooks/use-admin-datetime-formatter" import { useTranslationRef } from "@/hooks/use-translation-ref"; import { useCachedPlayTypeOptions } from "@/hooks/use-cached-play-type-options"; import { useAdminCurrencyCatalog } from "@/hooks/use-admin-currency-catalog"; -import { adminHasAnyPermission } from "@/lib/admin-permissions"; -import { - PRD_AGENT_HUB_ACCESS_ANY, - PRD_PLAYERS_ACCESS_ANY, - PRD_REPORTS_VIEW_ACCESS_ANY, - PRD_SETTLEMENT_AGENT_ACCESS_ANY, - PRD_TICKETS_ACCESS_ANY, -} from "@/lib/admin-prd"; import { normalizeAdminLanguage } from "@/i18n"; import { adminWeekdayKeyForDate, formatAdminCalendarToday } from "@/lib/admin-datetime"; +import { signedMoneyClass } from "@/lib/admin-signed-money"; import { cn } from "@/lib/utils"; import { useAdminProfile } from "@/stores/admin-session"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; -import { Button, buttonVariants } from "@/components/ui/button"; +import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Skeleton } from "@/components/ui/skeleton"; import { DashboardCurrentDrawCard } from "@/modules/dashboard/dashboard-current-draw-card"; import { DashboardAnalyticsPanel } from "@/modules/dashboard/dashboard-analytics-panel"; +import { DashboardKpiCard } from "@/modules/dashboard/dashboard-visuals"; import { formatDashboardCreditMajor, formatDashboardMoneyMinor, @@ -49,14 +31,27 @@ import type { AdminDashboardAgentOverview } from "@/types/api/admin-dashboard"; import type { DrawCurrentSnapshot } from "@/types/api/public-draw"; import { LotteryApiBizError } from "@/types/api/errors"; +function AgentMetric({ + label, + value, +}: { + label: string; + value: string; +}): ReactElement { + return ( +
{label}
+{value}
+- {t("agent.heroEyebrow")} -
-+ {formatDashboardCreditMajor(overview.credit_limit, displayCurrency)} +
++ {t("agent.creditAvailable", { + amount: formatDashboardCreditMajor(overview.available_credit, displayCurrency), + })} +
++ {t("agent.lineMeta", { + depth: overview.depth, + childAgent: overview.can_create_child_agent ? t("agent.yes") : t("agent.no"), + player: overview.can_create_player ? t("agent.yes") : t("agent.no"), + })} +
+{t("agent.todayBet")}
-- {formatDashboardMoneyMinor(overview.today_bet_minor, displayCurrency)} -
-{t("agent.todayPayout")}
-- {formatDashboardMoneyMinor(overview.today_payout_minor, displayCurrency)} -
-{t("agent.todayShareProfit")}
-- {formatDashboardSignedMoneyMinor(overview.today_profit_minor, displayCurrency)} -
-{t("agent.activePlayersToday")}
-{overview.active_player_count_today}
-{t("agent.betOrdersToday")}
-{overview.bet_order_count_today}
-{t("agent.pendingBills")}
-{overview.pending_bill_count}
-- {formatDashboardCreditMajor(overview.credit_limit, displayCurrency)} -
-- {t("agent.creditAvailable", { - amount: formatDashboardCreditMajor(overview.available_credit, displayCurrency), - })} -
-{t("agent.creditAllocatedLabel")}
-- {formatDashboardCreditMajor(overview.allocated_credit, displayCurrency)} -
-{t("agent.creditUsedLabel")}
-- {formatDashboardCreditMajor(overview.used_credit, displayCurrency)} -
-- {t("agent.pendingUnpaid", { - amount: formatDashboardMoneyMinor(overview.pending_unpaid_minor, displayCurrency), - })} -
-- {formatDashboardMoneyMinor(overview.seven_day_bet_minor, displayCurrency)} -
-- {t("agent.sevenDayPayout", { - amount: formatDashboardMoneyMinor(overview.seven_day_payout_minor, displayCurrency), - })} -
-- {t("agent.sevenDayShareProfit", { - amount: formatDashboardSignedMoneyMinor(overview.seven_day_profit_minor, displayCurrency), - })} -
-{t("agent.directChildren")}
-{overview.direct_child_count}
-{t("agent.subtreeAgents")}
-{overview.subtree_agent_count}
-{t("agent.directPlayers")}
-{overview.direct_player_count}
-{t("agent.teamPlayers")}
-{overview.team_player_count}
-{overview.pending_bill_count}
-- {t("agent.pendingUnpaid", { - amount: formatDashboardMoneyMinor(overview.pending_unpaid_minor, displayCurrency), - })} -
-- {overview.top_agent_today.agent_name || overview.top_agent_today.agent_code} -
-- {formatDashboardMoneyMinor(overview.top_agent_today.total_bet_minor, displayCurrency)} -
-- {t("agent.topMomentumPayout", { - amount: formatDashboardMoneyMinor( - overview.top_agent_today.total_payout_minor, - displayCurrency, - ), - })} -
- > - ) : ( -{t("agent.noBetToday")}
- )} -{t("agent.focusBet")}
-- {formatDashboardMoneyMinor(overview.today_bet_minor, displayCurrency)} -
-{t("agent.focusPlayers")}
-{overview.active_player_count_today}
-{t("agent.focusBills")}
-{overview.pending_bill_count}
-{label}
-+
{value}
{deltaLabel ?{label}
+{value}
++ {site + ? t("site.subtitle", { name: site.name || site.code }) + : todayLabel} +
+{t("overviewProfitLoss")}
-+
{formatAdminMinorUnits( financeSummary?.approx_house_gross_minor ?? data.profit_loss_minor ?? 0, financeCurrency, diff --git a/src/modules/draws/draw-finance-console.tsx b/src/modules/draws/draw-finance-console.tsx index 07141aa..1f2ade0 100644 --- a/src/modules/draws/draw-finance-console.tsx +++ b/src/modules/draws/draw-finance-console.tsx @@ -24,6 +24,7 @@ import { TableRow, } from "@/components/ui/table"; import { adminHasAnyPermission } from "@/lib/admin-permissions"; +import { signedMoneyClass } from "@/lib/admin-signed-money"; import { cn } from "@/lib/utils"; import { useAdminProfile } from "@/stores/admin-session"; import { LotteryApiBizError } from "@/types/api/errors"; @@ -140,12 +141,7 @@ export function DrawFinanceConsole({ drawId }: { drawId: string }): React.ReactE
= 0 ? "text-emerald-600" : "text-destructive", - )} - > +
{formatMoney(data.approx_house_gross_minor)}