feat: 實作庫存列表展開狀態保留 (使用 sessionStorage) 改良顯示與修正相關問題

This commit is contained in:
2026-02-10 13:02:11 +08:00
parent e098e40fb8
commit 8b950f6529
3 changed files with 33 additions and 15 deletions

View File

@@ -3,7 +3,8 @@
* 顯示庫存項目列表(依商品分組並支援折疊)
*/
import { useState } from "react";
import { useState, useEffect } from "react";
import { AlertTriangle, Trash2, Eye, ChevronDown, ChevronRight, CheckCircle, Package } from "lucide-react";
import {
Table,
@@ -47,10 +48,29 @@ export default function InventoryTable({
// 判斷是否為販賣機倉庫
const isVending = warehouse?.type === "vending";
// 每個商品的展開/折疊狀態
const [expandedProducts, setExpandedProducts] = useState<Set<string>>(new Set());
// 每個商品的展開/折疊狀態 - 使用 sessionStorage 保留狀態 (改用 Array 以利序列化)
// 解決使用 Link 返回時 State 被重置的問題
const storageKey = `inventory_expanded_${warehouse.id}`;
const [expandedProducts, setExpandedProducts] = useState<string[]>(() => {
if (typeof window === 'undefined') return [];
try {
const saved = sessionStorage.getItem(storageKey);
return saved ? JSON.parse(saved) : [];
} catch (e) {
console.error("Failed to parse expanded state", e);
return [];
}
});
useEffect(() => {
try {
sessionStorage.setItem(storageKey, JSON.stringify(expandedProducts));
} catch (e) {
console.error("Failed to save expanded state", e);
}
}, [expandedProducts, storageKey]);
// console.log('InventoryTable Rendered', { warehouseId: warehouse.id, expandedProducts });
if (inventories.length === 0) {
return (
@@ -68,13 +88,11 @@ export default function InventoryTable({
const toggleProduct = (productId: string) => {
setExpandedProducts((prev) => {
const newSet = new Set(prev);
if (newSet.has(productId)) {
newSet.delete(productId);
if (prev.includes(productId)) {
return prev.filter(id => id !== productId);
} else {
newSet.add(productId);
return [...prev, productId];
}
return newSet;
});
};
@@ -111,7 +129,7 @@ export default function InventoryTable({
const status = group.status;
const isLowStock = status === "低於";
const isExpanded = expandedProducts.has(group.productId);
const isExpanded = expandedProducts.includes(group.productId);
const hasInventory = group.batches.length > 0;
return (

View File

@@ -42,7 +42,7 @@ export default function TransactionTable({ transactions, showBatchNumber = false
<th className="px-4 py-3"></th>
<th className="px-4 py-3 text-right"></th>
<th className="px-4 py-3 text-right"></th>
{shouldShowSlot && <th className="px-4 py-3"></th>}
{shouldShowSlot && <th className="px-4 py-3"></th>}
<th className="px-4 py-3"></th>
<th className="px-4 py-3">/</th>
</tr>

View File

@@ -1,4 +1,5 @@
import { Head, router, useRemember } from "@inertiajs/react";
import { useState } from "react";
import { Head, router } from "@inertiajs/react";
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
import {
Search,
@@ -120,10 +121,9 @@ export default function StockQueryIndex({
warehouses,
categories,
}: Props) {
const [search, setSearch] = useRemember(filters.search || "", "StockQuery/search");
const [perPage, setPerPage] = useRemember(
filters.per_page || "10",
"StockQuery/perPage"
const [search, setSearch] = useState(filters.search || "");
const [perPage, setPerPage] = useState<string>(
filters.per_page || "10"
);
// 執行篩選