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()}
)) : (
無庫存資料
)}
{/* 熱銷數量排行 */}

熱銷數量 Top 5

{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}
)) : (
目前無即將過期商品
)}
); }