import { Head, Link } from "@inertiajs/react";
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
import {
AlertTriangle,
MinusCircle,
Clock,
LayoutDashboard,
TrendingUp,
DollarSign,
ClipboardCheck,
Trophy,
Package,
} from "lucide-react";
import {
AreaChart,
Area,
XAxis,
YAxis,
CartesianGrid,
Tooltip as RechartsTooltip,
ResponsiveContainer,
} from "recharts";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/Components/ui/tooltip";
interface Props {
stats: {
totalItems: number;
lowStockCount: number;
negativeCount: number;
expiringCount: number;
totalInventoryValue: number;
thisMonthRevenue: number;
pendingOrdersCount: number;
pendingTransferCount: number;
pendingProductionCount: number;
todoCount: number;
salesTrend: { date: string; amount: number }[];
topSellingProducts: { name: string; amount: number }[];
topInventoryValue: { name: string; code: string; value: number }[];
topSellingByQuantity: { name: string; code: string; value: number }[];
expiringSoon: { name: string; batch_number: string; expiry_date: string; quantity: number }[];
};
}
export default function Dashboard({ stats }: Props) {
const mainCards = [
{
label: "庫存總值",
value: `NT$ ${Math.round(stats.totalInventoryValue).toLocaleString()}`,
description: `品項總數: ${stats.totalItems}`,
icon: ,
color: "text-blue-600",
bgColor: "bg-blue-50",
borderColor: "border-blue-100",
},
{
label: "本月銷售營收",
value: `NT$ ${Math.round(stats.thisMonthRevenue).toLocaleString()}`,
description: "基於銷售導入數據",
icon: ,
color: "text-emerald-600",
bgColor: "bg-emerald-50",
borderColor: "border-emerald-100",
},
{
label: "待辦任務",
value: stats.todoCount,
description: (
採購: {stats.pendingOrdersCount}
|
生產: {stats.pendingProductionCount}
|
調撥: {stats.pendingTransferCount}
),
icon: ,
color: "text-purple-600",
bgColor: "bg-purple-50",
borderColor: "border-purple-100",
alert: stats.todoCount > 0,
},
];
const alertCards = [
{
label: "低庫存",
value: stats.lowStockCount,
icon: ,
color: "text-amber-600",
bgColor: "bg-amber-50",
borderColor: "border-amber-200",
href: "/inventory/stock-query?status=low_stock",
alert: stats.lowStockCount > 0,
},
{
label: "負庫存",
value: stats.negativeCount,
icon: ,
color: "text-red-600",
bgColor: "bg-red-50",
borderColor: "border-red-200",
href: "/inventory/stock-query?status=negative",
alert: stats.negativeCount > 0,
},
{
label: "即將過期",
value: stats.expiringCount,
icon: ,
color: "text-yellow-600",
bgColor: "bg-yellow-50",
borderColor: "border-yellow-200",
href: "/inventory/stock-query?status=expiring",
alert: stats.expiringCount > 0,
},
];
return (
{alertCards.map((card) => (
{card.icon}
{card.label}
{card.value}
))}
{mainCards.map((card) => (
{card.icon}
{card.alert && (
)}
{card.label}
{card.value}
{card.description}
))}
{/* 銷售趨勢 & 熱銷排行 */}
{/* 銷售趨勢 - Area Chart */}
近 30 日銷售趨勢
`$${value / 1000}k`} />
`NT$ ${Number(value).toLocaleString()}`} />
{/* 熱銷商品排行 (金額) - Bar Chart */}
熱銷金額 Top 5
{stats.topSellingProducts.length > 0 ? (
(() => {
const maxAmount = Math.max(...stats.topSellingProducts.map(p => p.amount));
return stats.topSellingProducts.map((product, index) => (
{product.name}
{product.name}
NT$ {product.amount.toLocaleString()}
));
})()
) : (
暫無銷售數據
)}
{/* 其他排行資訊 */}
{/* 庫存積壓排行 */}
庫存積壓 Top 5
{stats.topInventoryValue.length > 0 ? stats.topInventoryValue.map((item, idx) => (
{item.name}
{item.name}
{item.code}
NT$ {item.value.toLocaleString()}
)) : (
無庫存資料
)}
{/* 熱銷數量排行 */}
{stats.topSellingByQuantity.length > 0 ? stats.topSellingByQuantity.map((item, idx) => (
{item.name}
{item.name}
{item.code}
{item.value.toLocaleString()} 件
)) : (
無銷售資料
)}
{/* 即將過期商品 */}
即將過期 Top 5
{stats.expiringSoon.length > 0 ? stats.expiringSoon.map((item, idx) => (
{item.name}
{item.name}
批號: {item.batch_number}
{item.expiry_date}
庫存: {item.quantity}
)) : (
目前無即將過期商品
)}
);
}