You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
2.8 KiB

"use client";
import { useEffect, useState } from "react";
import Link from "next/link";
import {
Warning,
Users,
Percent,
ListMagnifyingGlass,
} from "@phosphor-icons/react";
import { AdminLayout } from "@/components/layout/admin-layout";
import { PageHeader } from "@/components/layout/page-header";
import { Card } from "@/components/ui/card";
import { useAuth } from "@/hooks/use-auth";
import { adminGetAlerts } from "@/lib/frontend/api-client";
interface EntryCard {
href: string;
title: string;
desc: string;
icon: typeof Warning;
badge?: number;
}
export default function DashboardPage() {
const { token } = useAuth();
const [openAlerts, setOpenAlerts] = useState(0);
useEffect(() => {
if (!token) return;
void adminGetAlerts("", token, 1, 1, undefined, "open").then((res) => {
if (res.code === 0) {
setOpenAlerts(res.data.total);
}
});
}, [token]);
const entries: EntryCard[] = [
{
href: "/admin/alerts",
title: "预警中心",
desc: "查看查价失败根因与客户地址货物信息",
icon: Warning,
badge: openAlerts,
},
{
href: "/admin/queues",
title: "查价记录",
desc: "最近询价流水、成功失败与客户查询详情",
icon: ListMagnifyingGlass,
},
{
href: "/admin/customers",
title: "客户管理",
desc: "新增客户、签发 API Key 与状态管理",
icon: Users,
},
{
href: "/admin/markup",
title: "加价配置",
desc: "按客户设置报价加价比例",
icon: Percent,
},
];
return (
<AdminLayout>
<PageHeader
title="工作台"
subtitle="管理员快捷入口"
/>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
{entries.map((entry) => {
const Icon = entry.icon;
return (
<Link key={entry.href} href={entry.href}>
<Card className="cursor-pointer transition-shadow hover:shadow-modal">
<div className="flex items-start justify-between">
<div className="flex h-11 w-11 items-center justify-center rounded-md bg-primary/10 text-primary">
<Icon size={24} weight="fill" />
</div>
{entry.badge ? (
<span className="rounded-sm bg-error/10 px-2 py-0.5 text-xs text-error">
{entry.badge}
</span>
) : null}
</div>
<h3 className="mt-4 text-lg font-semibold text-text-primary">
{entry.title}
</h3>
<p className="mt-1 text-sm text-text-secondary">{entry.desc}</p>
</Card>
</Link>
);
})}
</div>
</AdminLayout>
);
}