import { ref, computed } from 'vue'; import api from '../api'; import type { AdminDashboard } from '../views/dashboard-types'; import { formatAmount, formatAmountFull } from '../utils/format-amount'; import { useAdminLocale } from './useAdminLocale'; const stats = ref(null); const loading = ref(false); const loadError = ref(false); let inflight: Promise | null = null; export function useAdminDashboard() { const { t, locale, localeTag } = useAdminLocale(); const s = computed(() => stats.value); async function load(force = false) { if (inflight && !force) return inflight; if (stats.value && !force) return; loading.value = true; loadError.value = false; inflight = (async () => { try { const { data } = await api.get('/admin/dashboard'); stats.value = data.data as AdminDashboard; } catch { stats.value = null; loadError.value = true; } finally { loading.value = false; inflight = null; } })(); return inflight; } function fmtCount(val: number | undefined) { return (val ?? 0).toLocaleString(localeTag.value, { maximumFractionDigits: 0 }); } function formatTime(v: string) { return new Date(v).toLocaleString(localeTag.value, { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', }); } function toNum(v: string | number | undefined) { const n = typeof v === 'number' ? v : parseFloat(v ?? '0'); return Number.isFinite(n) ? n : 0; } function pctChange(today: string | number, yesterday: string | number) { const t0 = toNum(today); const y = toNum(yesterday); if (y === 0) return t0 > 0 ? '+100%' : '—'; const p = ((t0 - y) / y) * 100; const sign = p > 0 ? '+' : ''; return `${sign}${p.toFixed(1)}%`; } const chartI18n = computed(() => ({ locale: locale.value, betCountSeries: t('dash.chart_bet_count'), axisAmount: t('dash.axis_amount'), axisCount: t('dash.axis_count'), countSuffix: t('dash.count_suffix'), pieTooltip: t('dash.chart_tooltip'), noData: t('common.no_data'), pieEmpty: t('dash.pie_empty'), })); const trendLabels = computed(() => s.value?.trend7d?.map((d) => d.label) ?? []); const kpiPrimary = computed(() => { if (!s.value) return []; const td = s.value.today; const y = s.value.yesterday; const yLabel = t('common.yesterday'); return [ { label: t('dash.kpi_bet_count'), value: fmtCount(td.betCount), sub: `${yLabel} ${fmtCount(y.betCount)}`, delta: pctChange(td.betCount, y.betCount), }, { label: t('dash.kpi_stake'), value: formatAmount(td.stake, 2, locale.value), sub: formatAmountFull(td.stake, locale.value), delta: pctChange(td.stake, y.stake), }, { label: t('dash.kpi_payout'), value: formatAmount(td.payout, 2, locale.value), sub: `${yLabel} ${formatAmount(y.payout, 2, locale.value)}`, delta: pctChange(td.payout, y.payout), }, { label: t('dash.kpi_ggr'), value: formatAmount(td.ggr, 2, locale.value), sub: `${yLabel} ${formatAmount(y.ggr, 2, locale.value)}`, delta: pctChange(td.ggr, y.ggr), }, ]; }); return { stats, s, loading, loadError, load, fmtCount, formatTime, toNum, chartI18n, trendLabels, kpiPrimary, }; }