feat: 實作庫存列表展開狀態保留 (使用 sessionStorage) 改良顯示與修正相關問題
This commit is contained in:
@@ -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 { AlertTriangle, Trash2, Eye, ChevronDown, ChevronRight, CheckCircle, Package } from "lucide-react";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
@@ -47,10 +48,29 @@ export default function InventoryTable({
|
|||||||
// 判斷是否為販賣機倉庫
|
// 判斷是否為販賣機倉庫
|
||||||
const isVending = warehouse?.type === "vending";
|
const isVending = warehouse?.type === "vending";
|
||||||
|
|
||||||
// 每個商品的展開/折疊狀態
|
// 每個商品的展開/折疊狀態 - 使用 sessionStorage 保留狀態 (改用 Array 以利序列化)
|
||||||
const [expandedProducts, setExpandedProducts] = useState<Set<string>>(new Set());
|
// 解決使用 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) {
|
if (inventories.length === 0) {
|
||||||
return (
|
return (
|
||||||
@@ -68,13 +88,11 @@ export default function InventoryTable({
|
|||||||
|
|
||||||
const toggleProduct = (productId: string) => {
|
const toggleProduct = (productId: string) => {
|
||||||
setExpandedProducts((prev) => {
|
setExpandedProducts((prev) => {
|
||||||
const newSet = new Set(prev);
|
if (prev.includes(productId)) {
|
||||||
if (newSet.has(productId)) {
|
return prev.filter(id => id !== productId);
|
||||||
newSet.delete(productId);
|
|
||||||
} else {
|
} else {
|
||||||
newSet.add(productId);
|
return [...prev, productId];
|
||||||
}
|
}
|
||||||
return newSet;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,7 +129,7 @@ export default function InventoryTable({
|
|||||||
const status = group.status;
|
const status = group.status;
|
||||||
|
|
||||||
const isLowStock = status === "低於";
|
const isLowStock = status === "低於";
|
||||||
const isExpanded = expandedProducts.has(group.productId);
|
const isExpanded = expandedProducts.includes(group.productId);
|
||||||
const hasInventory = group.batches.length > 0;
|
const hasInventory = group.batches.length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default function TransactionTable({ transactions, showBatchNumber = false
|
|||||||
<th className="px-4 py-3">類型</th>
|
<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>
|
||||||
<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>
|
||||||
<th className="px-4 py-3">原因/備註</th>
|
<th className="px-4 py-3">原因/備註</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -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 AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
|
||||||
import {
|
import {
|
||||||
Search,
|
Search,
|
||||||
@@ -120,10 +121,9 @@ export default function StockQueryIndex({
|
|||||||
warehouses,
|
warehouses,
|
||||||
categories,
|
categories,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const [search, setSearch] = useRemember(filters.search || "", "StockQuery/search");
|
const [search, setSearch] = useState(filters.search || "");
|
||||||
const [perPage, setPerPage] = useRemember(
|
const [perPage, setPerPage] = useState<string>(
|
||||||
filters.per_page || "10",
|
filters.per_page || "10"
|
||||||
"StockQuery/perPage"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 執行篩選
|
// 執行篩選
|
||||||
|
|||||||
Reference in New Issue
Block a user