From f1651f31e870d08496ada4534f0b0d508d666885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Sun, 22 Mar 2026 11:52:52 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20[=EC=9E=AC=EA=B3=A0=EB=AA=A9=EB=A1=9D]?= =?UTF-8?q?=20=ED=96=89=20=ED=81=B4=EB=A6=AD=20=EB=A9=94=EB=89=B4=EB=A5=BC?= =?UTF-8?q?=20=ED=94=8C=EB=A1=9C=ED=8C=85=20=ED=8C=9D=EC=98=A4=EB=B2=84?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20(=EC=95=84=EC=BD=94=EB=94=94?= =?UTF-8?q?=EC=96=B8=E2=86=92float)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../material/StockStatus/StockStatusList.tsx | 81 +++++++++++-------- 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/src/components/material/StockStatus/StockStatusList.tsx b/src/components/material/StockStatus/StockStatusList.tsx index 9d407023..0b330c3c 100644 --- a/src/components/material/StockStatus/StockStatusList.tsx +++ b/src/components/material/StockStatus/StockStatusList.tsx @@ -154,18 +154,32 @@ export function StockStatusList() { return true; }); - // ===== 행 클릭 → 액션 메뉴 ===== - const [actionMenuItemId, setActionMenuItemId] = useState(null); + // ===== 행 클릭 → 플로팅 액션 메뉴 ===== + const [actionMenu, setActionMenu] = useState<{ item: StockItem; x: number; y: number } | null>(null); const [usageModalItem, setUsageModalItem] = useState(null); const [usageData, setUsageData] = useState(null); const [usageLoading, setUsageLoading] = useState(false); - const handleRowClick = (item: StockItem) => { - setActionMenuItemId(prev => prev === item.id ? null : item.id); + const handleRowClick = (item: StockItem, e?: React.MouseEvent) => { + if (actionMenu?.item.id === item.id) { + setActionMenu(null); + return; + } + const x = e?.clientX ?? 200; + const y = e?.clientY ?? 200; + setActionMenu({ item, x, y }); }; + // 외부 클릭 시 닫기 + useEffect(() => { + if (!actionMenu) return; + const close = () => setActionMenu(null); + window.addEventListener('click', close, { once: true }); + return () => window.removeEventListener('click', close); + }, [actionMenu]); + const handleViewUsage = async (item: StockItem) => { - setActionMenuItemId(null); + setActionMenu(null); setUsageModalItem(item); setUsageLoading(true); const result = await getStockTransactions(item.id); @@ -323,11 +337,10 @@ export function StockStatusList() { handlers: SelectionHandlers & RowClickHandlers ) => { return ( - <> handleRowClick(item)} + className={`cursor-pointer hover:bg-muted/50 ${handlers.isSelected ? 'bg-blue-50' : ''}`} + onClick={(e) => handleRowClick(item, e)} > e.stopPropagation()}> - {actionMenuItemId === item.id && ( - - -
- - -
-
-
- )} - ); }; @@ -571,6 +559,33 @@ export function StockStatusList() { onSearchChange={setSearchTerm} /> + {/* 플로팅 액션 메뉴 */} + {actionMenu && ( +
e.stopPropagation()} + > + + +
+ )} + {/* 사용현황 모달 */} { if (!open) { setUsageModalItem(null); setUsageData(null); } }}>