"use client"; import { useCallback, useMemo, useState, type ReactElement } from "react"; import { useTranslation } from "react-i18next"; import { BarChart3, RefreshCw, TrendingUp, Users, Wallet } from "lucide-react"; import { getAdminDashboard } from "@/api/admin-dashboard"; import { useAsyncEffect } from "@/hooks/use-async-effect"; 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 { adminHasAnyPermission } from "@/lib/admin-permissions"; import { PRD_REPORTS_VIEW_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 } 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 { formatDashboardMoneyMinor, formatDashboardSignedMoneyMinor, } from "@/modules/dashboard/use-dashboard-analytics"; import type { AdminDashboardSiteOverview } from "@/types/api/admin-dashboard"; import type { DrawCurrentSnapshot } from "@/types/api/public-draw"; import { LotteryApiBizError } from "@/types/api/errors"; function SiteMetric({ label, value, }: { label: string; value: string; }): ReactElement { return (

{label}

{value}

); } export function SiteDashboardConsole(): ReactElement { const { t, i18n } = useTranslation(["dashboard", "common"]); const tRef = useTranslationRef(["dashboard", "common"]); const formatDt = useAdminDateTimeFormatter(); const profile = useAdminProfile(); const site = profile?.site ?? null; const permissions = useMemo(() => profile?.permissions ?? [], [profile?.permissions]); const todayLabel = useMemo(() => { const locale = normalizeAdminLanguage(i18n.resolvedLanguage ?? i18n.language); const weekday = t(`date.weekdays.${adminWeekdayKeyForDate()}`, { ns: "common" }); return formatAdminCalendarToday(locale, weekday); }, [i18n.language, i18n.resolvedLanguage, t]); const playOptions = useCachedPlayTypeOptions(); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const [error, setError] = useState(null); const [hall, setHall] = useState(null); const [drawId, setDrawId] = useState(null); const [overview, setOverview] = useState(null); const analyticsScope = useMemo( () => ({ siteCode: site?.code ?? overview?.site_code ?? "", agentNodeId: undefined, }), [overview?.site_code, site?.code], ); const canAnalytics = adminHasAnyPermission(permissions, [...PRD_REPORTS_VIEW_ACCESS_ANY]); const load = useCallback(async (isRefresh = false) => { if (isRefresh) { setRefreshing(true); } else { setLoading(true); } setError(null); try { const d = await getAdminDashboard(); setHall(d.hall); setOverview(d.site_overview); if (d.resolved_draw != null) { setDrawId(d.resolved_draw.id); } else { setDrawId(null); } } catch (e) { const msg = e instanceof LotteryApiBizError ? e.message : tRef.current("warnings.loadFailed"); setError(msg); } finally { setLoading(false); setRefreshing(false); } }, [tRef]); useAsyncEffect(() => { void load(false); }, []); const displayCurrency = overview?.currency_code ?? "NPR"; return (

{t("site.title")}

{site ? t("site.subtitle", { name: site.name || site.code }) : todayLabel}

{error ? ( {t("notice")} {error} ) : null} {loading ? (
{Array.from({ length: 4 }).map((_, i) => ( ))}
) : overview ? (
} hint={ overview.latest_bet_at ? t("site.latestBetAt", { time: formatDt(overview.latest_bet_at) }) : t("site.noBetToday") } /> } hint={t("site.profitScopeHint")} valueClassName={signedMoneyClass(overview.today_profit_minor, true)} /> } hint={t("site.betOrdersTodayHint", { count: overview.bet_order_count_today })} /> } hint={t("site.pendingUnpaid", { amount: formatDashboardMoneyMinor(overview.pending_unpaid_minor, displayCurrency), })} accent={overview.pending_bill_count > 0 ? "destructive" : "muted"} />
{t("site.sevenDayTitle")}
{t("site.todayBet")} {formatDashboardMoneyMinor(overview.seven_day_bet_minor, displayCurrency)}
{t("site.sevenDayProfit")} {formatDashboardSignedMoneyMinor(overview.seven_day_profit_minor, displayCurrency)}
{t("site.scaleTitle")} {overview.top_agent_today ? (
{t("site.topAgentToday", { name: overview.top_agent_today.agent_name || overview.top_agent_today.agent_code, amount: formatDashboardMoneyMinor( overview.top_agent_today.total_bet_minor, displayCurrency, ), })}
) : null}
) : null} {canAnalytics ? ( ) : null}
); }