"use client";
import { useCallback, useEffect, useMemo, useState } from "react";
import {
fetchAnalyticsSummary,
type AnalyticsDailyRow,
type AnalyticsSummaryResponse,
} from "@/features/agent/services/analyticsApi";
import { Button } from "@/components/ui/button";
import { toast } from "@/hooks/useToast";
function formatPercent(n: number) {
if (Number.isNaN(n)) return "—";
return `${n.toFixed(2)}%`;
}
function StatCard({
title,
value,
sub,
}: {
title: string;
value: string | number;
sub?: string;
}) {
return (
{title}
{value}
{sub ?
{sub}
: null}
);
}
function DailyBars({
daily,
field,
label,
color,
}: {
daily: AnalyticsDailyRow[];
field: keyof Pick<
AnalyticsDailyRow,
"widget_opens" | "sessions" | "messages" | "ai_replies"
>;
label: string;
color: string;
}) {
const max = useMemo(() => {
let m = 1;
for (const row of daily) {
const v = Number(row[field]) || 0;
if (v > m) m = v;
}
return m;
}, [daily, field]);
if (daily.length === 0) {
return 暂无数据
;
}
return (
{label}
{daily.map((row) => {
const v = Number(row[field]) || 0;
const h = Math.round((v / max) * 100);
return (
0 ? 8 : 0)}%`,
backgroundColor: color,
minHeight: v > 0 ? 4 : 0,
}}
/>
{row.date.slice(5)}
);
})}
);
}
export default function AnalyticsPage(_props: { embedded?: boolean }) {
const [from, setFrom] = useState(() => {
const d = new Date();
d.setDate(d.getDate() - 6);
return d.toISOString().slice(0, 10);
});
const [to, setTo] = useState(() => new Date().toISOString().slice(0, 10));
const [data, setData] = useState
(null);
const [loading, setLoading] = useState(true);
const load = useCallback(async () => {
setLoading(true);
try {
const res = await fetchAnalyticsSummary(from, to);
setData(res);
} catch (e) {
toast.error((e as Error).message);
setData(null);
} finally {
setLoading(false);
}
}, [from, to]);
useEffect(() => {
void load();
}, [load]);
const t = data?.totals;
return (
{data && (
{data.note}
)}
{t && (
<>
>
)}
{!loading && !t && (
暂无数据或加载失败
)}
);
}