import { useState, useCallback } from "react";
import { Button } from "@/Components/ui/button";
import { Input } from "@/Components/ui/input";
import { Label } from "@/Components/ui/label";
import {
Download,
Calendar,
Filter,
Package,
RotateCcw,
FileSpreadsheet,
ArrowUpFromLine,
ArrowDownToLine,
ArrowRightLeft,
TrendingUp,
ArrowUpDown,
ArrowUp,
ArrowDown
} from 'lucide-react';
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
import { Head, Link, router } from "@inertiajs/react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/Components/ui/table";
import { getDateRange } from "@/utils/format";
import Pagination from "@/Components/shared/Pagination";
import { SearchableSelect } from "@/Components/ui/searchable-select";
import { Can } from "@/Components/Permission/Can";
import { PageProps } from "@/types/global";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/Components/ui/tooltip";
interface ReportData {
product_code: string;
product_name: string;
category_name: string;
product_id: number;
inbound_qty: number;
outbound_qty: number;
transfer_in_qty: number;
transfer_out_qty: number;
adjust_qty: number;
net_change: number;
}
interface SummaryData {
total_inbound: number;
total_outbound: number;
total_transfer_in: number;
total_transfer_out: number;
total_adjust: number;
total_net_change: number;
}
interface InventoryReportProps extends PageProps {
reportData: {
data: ReportData[];
links: any[];
total: number;
from: number;
to: number;
current_page: number;
};
summary: SummaryData;
warehouses: { id: number; name: string }[];
categories: { id: number; name: string }[];
filters: {
date_from: string;
date_to: string;
warehouse_id: string;
category_id: string;
search: string;
per_page?: number;
sort_by?: string;
sort_order?: 'asc' | 'desc';
};
}
export default function InventoryReportIndex({ reportData, summary, warehouses, categories, filters }: InventoryReportProps) {
const [dateStart, setDateStart] = useState(filters.date_from || "");
const [dateEnd, setDateEnd] = useState(filters.date_to || "");
const [warehouseId, setWarehouseId] = useState(filters.warehouse_id || "all");
const [categoryId, setCategoryId] = useState(filters.category_id || "all");
const [search, setSearch] = useState(filters.search || "");
const [perPage, setPerPage] = useState(filters.per_page?.toString() || "10");
// Determine initial range type based on date pairs
const getInitialRangeType = () => {
const { start: todayS, end: todayE } = getDateRange('today');
const { start: yestS, end: yestE } = getDateRange('yesterday');
const { start: weekS, end: weekE } = getDateRange('this_week');
const { start: monthS, end: monthE } = getDateRange('this_month');
const { start: lastMS, end: lastME } = getDateRange('last_month');
const fS = filters.date_from || "";
const fE = filters.date_to || "";
if (fS === todayS && fE === todayE) return "today";
if (fS === yestS && fE === yestE) return "yesterday";
if (fS === weekS && fE === weekE) return "this_week";
if (fS === monthS && fE === monthE) return "this_month";
if (fS === lastMS && fE === lastME) return "last_month";
return "custom";
};
const [dateRangeType, setDateRangeType] = useState(getInitialRangeType());
const handleDateRangeChange = (type: string) => {
setDateRangeType(type);
if (type === "custom") return;
const { start, end } = getDateRange(type);
setDateStart(start);
setDateEnd(end);
};
const handleFilter = useCallback(() => {
router.get(
route("inventory.report.index"),
{
date_from: dateStart,
date_to: dateEnd,
warehouse_id: warehouseId === "all" ? "" : warehouseId,
category_id: categoryId === "all" ? "" : categoryId,
search: search,
per_page: perPage,
},
{ preserveState: true, preserveScroll: true }
);
}, [dateStart, dateEnd, warehouseId, categoryId, search, perPage]);
const handlePerPageChange = (value: string) => {
setPerPage(value);
router.get(
route("inventory.report.index"),
{
date_from: dateStart,
date_to: dateEnd,
warehouse_id: warehouseId === "all" ? "" : warehouseId,
category_id: categoryId === "all" ? "" : categoryId,
search: search,
per_page: value,
},
{ preserveState: true, preserveScroll: true }
);
};
const handleClearFilters = () => {
// Service defaults: -7 days to today.
// Let's just clear params and let backend decide or set explicitly.
// Or simply reset to "daily" and "all"
setWarehouseId("all");
setCategoryId("all");
setSearch("");
setDateStart(""); // Will trigger service default
setDateEnd("");
setDateRangeType("custom");
setPerPage("10");
router.get(route("inventory.report.index"));
};
const handleExport = () => {
const query: any = {
date_from: dateStart,
date_to: dateEnd,
warehouse_id: warehouseId === "all" ? "" : warehouseId,
category_id: categoryId === "all" ? "" : categoryId,
search: search,
sort_by: filters.sort_by,
sort_order: filters.sort_order,
};
window.location.href = route("inventory.report.export", query);
};
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;
}
}
router.get(
route("inventory.report.index"),
{
date_from: dateStart,
date_to: dateEnd,
warehouse_id: warehouseId === "all" ? "" : warehouseId,
category_id: categoryId === "all" ? "" : categoryId,
search: search,
per_page: perPage,
sort_by: newSortBy,
sort_order: newSortOrder,
},
{ preserveState: true, preserveScroll: true }
);
};
const SortIcon = ({ field }: { field: string }) => {
if (filters.sort_by !== field) {
return
統計區間: {filters.date_from && filters.date_to ? ( <>{filters.date_from} 至 {filters.date_to}> ) : ( 全部期間 )} 內的進貨、出貨與庫存變動匯總
{Number(summary?.total_inbound || 0).toLocaleString()}
{Number(summary?.total_outbound || 0).toLocaleString()}
{Number(summary?.total_transfer_in || 0).toLocaleString()}
{Number(summary?.total_transfer_out || 0).toLocaleString()}
{Number(summary?.total_adjust || 0).toLocaleString()}
{summary?.total_net_change > 0 ? "+" : ""}{Number(summary?.total_net_change || 0).toLocaleString()}