import { useState, useCallback } from "react";
import { Button } from "@/Components/ui/button";
import { Input } from "@/Components/ui/input";
import { Label } from "@/Components/ui/label";
import {
Filter,
Package,
RotateCcw,
BarChart3,
AlertTriangle,
CheckCircle2,
Clock,
ArrowUpDown,
ArrowUp,
ArrowDown,
XCircle
} from 'lucide-react';
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
import { Head, router } from "@inertiajs/react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/Components/ui/table";
import Pagination from "@/Components/shared/Pagination";
import { SearchableSelect } from "@/Components/ui/searchable-select";
import { PageProps } from "@/types/global";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/Components/ui/tooltip";
import { StatusBadge, StatusVariant } from "@/Components/shared/StatusBadge";
interface AnalysisItem {
id: number;
code: string;
name: string;
category_name: string;
current_stock: string; // decimal string from DB
sales_30d: string;
last_sale_date: string | null;
turnover_days: number;
turnover_days_display: string;
status: 'dead' | 'slow' | 'normal' | 'out_of_stock';
status_label: string;
}
interface KPIProps {
total_stock_value: number;
dead_stock_value: number;
dead_stock_count: number;
avg_turnover_days: number;
}
interface PagePropsWithData extends PageProps {
analysisData: {
data: AnalysisItem[];
links: any[];
total: number;
from: number;
to: number;
current_page: number;
};
kpis: KPIProps;
warehouses: { id: number; name: string }[];
categories: { id: number; name: string }[];
filters: {
warehouse_id?: string;
category_id?: string;
search?: string;
per_page?: string;
sort_by?: string;
sort_order?: 'asc' | 'desc';
status?: string;
};
}
// Define status mapping
const getStatusVariant = (status: string): StatusVariant => {
switch (status) {
case 'dead': return 'destructive';
case 'slow': return 'warning';
case 'normal': return 'success';
case 'out_of_stock': return 'neutral';
default: return 'neutral';
}
};
const getStatusLabel = (status: string): string => {
switch (status) {
case 'dead': return '滯銷';
case 'slow': return '週轉慢';
case 'normal': return '正常';
case 'out_of_stock': return '缺貨';
default: return status;
}
};
const statusOptions = [
{ label: "全部狀態", value: "all" },
{ label: "滯銷 (>90天)", value: "dead" },
{ label: "週轉慢 (>60天)", value: "slow" },
{ label: "正常", value: "normal" }
];
export default function InventoryAnalysisIndex({ analysisData, kpis, warehouses, categories, filters }: PagePropsWithData) {
const [warehouseId, setWarehouseId] = useState(filters.warehouse_id || "all");
const [categoryId, setCategoryId] = useState(filters.category_id || "all");
const [search, setSearch] = useState(filters.search || "");
const [status, setStatus] = useState(filters.status || "all");
const [perPage, setPerPage] = useState(filters.per_page?.toString() || "10");
const handleFilter = useCallback(() => {
router.get(
route("inventory.analysis.index"),
{
warehouse_id: warehouseId === "all" ? "" : warehouseId,
category_id: categoryId === "all" ? "" : categoryId,
status: status === "all" ? "" : status,
search: search,
per_page: perPage,
sort_by: filters.sort_by,
sort_order: filters.sort_order,
},
{ preserveState: true, preserveScroll: true }
);
}, [warehouseId, categoryId, status, search, perPage, filters.sort_by, filters.sort_order]);
const handleClearFilters = () => {
setWarehouseId("all");
setCategoryId("all");
setStatus("all");
setSearch("");
setPerPage("10");
router.get(route("inventory.analysis.index"));
};
const handleSort = (field: string) => {
let newSortBy: string | undefined = field;
let newSortOrder: 'asc' | 'desc' | undefined = 'asc';
if (filters.sort_by === field) {
if (filters.sort_order === 'asc') {
newSortOrder = 'desc';
} else {
newSortBy = undefined;
newSortOrder = undefined;
}
} else {
// Default sort order for numeric fields might be desc
if (['turnover_days', 'current_stock', 'sales_30d'].includes(field)) {
newSortOrder = 'desc';
}
}
router.get(
route("inventory.analysis.index"),
{
warehouse_id: warehouseId === "all" ? "" : warehouseId,
category_id: categoryId === "all" ? "" : categoryId,
status: status === "all" ? "" : status,
search: search,
per_page: perPage,
sort_by: newSortBy,
sort_order: newSortOrder,
},
{ preserveState: true, preserveScroll: true }
);
};
const handlePerPageChange = (value: string) => {
setPerPage(value);
// Trigger filter immediately
router.get(
route("inventory.analysis.index"),
{
warehouse_id: warehouseId === "all" ? "" : warehouseId,
category_id: categoryId === "all" ? "" : categoryId,
status: status === "all" ? "" : status,
search: search,
per_page: value,
sort_by: filters.sort_by,
sort_order: filters.sort_order,
},
{ preserveState: true, preserveScroll: true }
);
};
const SortIcon = ({ field }: { field: string }) => {
if (filters.sort_by !== field) {
return
分析商品庫存週轉率、滯銷品項與庫存健康度
平均週轉天數
{kpis.avg_turnover_days} 天
滯銷品項數
{kpis.dead_stock_count} 項
滯銷庫存成本
${Number(kpis.dead_stock_value).toLocaleString()}
在此定義為庫存大於 0 且超過 90 天未銷售的商品成本總和
庫存總成本
${Number(kpis.total_stock_value).toLocaleString()}