www_site/components/admin/overview.tsx

52 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useEffect, useState } from "react";
import { getUsageSummary } from "@/lib/admin";
import { StatusCard } from "@/components/ui";
type Summary = {
quota: { used: number; reserved: number; adjustment: number };
ledger_total: number;
tasks: { total: number; by_status: Record<string, number>; failed: number };
};
export function OverviewPanel() {
const [data, setData] = useState<Summary | null>(null);
const [error, setError] = useState("");
useEffect(() => {
getUsageSummary()
.then(setData)
.catch((e) => setError(e instanceof Error ? e.message : "无法加载概览"));
}, []);
if (error) return <div className="rounded-xl border border-danger/30 bg-danger/10 p-4 text-sm text-danger">{error}</div>;
if (!data) return <StatusCard title="正在加载概览" description="正在汇总额度与任务。" tone="info" />;
const statusLabels: Record<string, string> = { queued: "排队", running: "进行中", succeeded: "成功", failed: "失败" };
return (
<div className="space-y-6">
<div className="grid gap-5 md:grid-cols-3">
<StatusCard title="累计使用" description={`${data.quota.used.toLocaleString()} 字符`} tone="success" />
<StatusCard title="冻结中" description={`${data.quota.reserved.toLocaleString()} 字符`} tone="warning" />
<StatusCard title="手动调整" description={`${data.quota.adjustment.toLocaleString()} 字符`} tone="info" />
</div>
<div className="grid gap-5 md:grid-cols-3">
<StatusCard title="任务总数" description={`${data.tasks.total}`} />
<StatusCard title={statusLabels.succeeded} description={`${data.tasks.by_status.succeeded ?? 0}`} tone="success" />
<StatusCard title="失败任务" description={`${data.tasks.failed}`} tone="warning" />
</div>
<div className="rounded-2xl border border-line bg-panel/50 p-5">
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-subtle"></p>
<dl className="mt-3 grid gap-3 text-sm sm:grid-cols-3">
<div className="flex justify-between gap-4 border-b border-line pb-3 sm:border-0 sm:pb-0"><dt className="text-muted"></dt><dd className="text-copy">{data.ledger_total.toLocaleString()}</dd></div>
<div className="flex justify-between gap-4 sm:justify-start"><dt className="text-muted">quota_accounts.used</dt><dd className="text-copy">{data.quota.used.toLocaleString()}</dd></div>
<div className="flex justify-between gap-4 sm:justify-start"><dt className="text-muted"></dt><dd className="text-copy">{data.quota.adjustment.toLocaleString()}</dd></div>
</dl>
<p className="mt-3 text-xs leading-5 text-subtle"></p>
</div>
</div>
);
}