From 280495d7415566683dd866f0a86f5113e1d70316 Mon Sep 17 00:00:00 2001 From: chpark Date: Thu, 14 May 2026 22:09:19 +0900 Subject: [PATCH] =?UTF-8?q?feat(stock):=20=EC=B0=BD=EA=B3=A0=EB=B3=84=20?= =?UTF-8?q?=EC=9E=AC=EA=B3=A0=20=ED=98=84=ED=99=A9=20=E2=80=94=20=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=20=ED=86=A0=EA=B8=80=20(=EC=B0=BD=EA=B3=A0=20?= =?UTF-8?q?=EA=B0=80=EB=A1=9C=20=E2=86=94=20=ED=92=88=EB=AA=A9=20=EA=B0=80?= =?UTF-8?q?=EB=A1=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 토글 버튼 2개로 표시 형식 전환: - '창고 가로' (기본): 헤더=창고 7개, 행=품목 (가로로 김) - '품목 가로': 헤더=품목, 행=창고 7줄 (오른쪽으로 길게, 좌측 sticky) 각 모드에서 동일하게 셀당 '발주수량(현재고) / 여유분' 2행. 여유분 음수면 rose 강조. --- .../(main)/m/admin/wh-stock-status/page.tsx | 167 ++++++++++++------ 1 file changed, 117 insertions(+), 50 deletions(-) diff --git a/src/app/(main)/m/admin/wh-stock-status/page.tsx b/src/app/(main)/m/admin/wh-stock-status/page.tsx index c72f4e9..eac542d 100644 --- a/src/app/(main)/m/admin/wh-stock-status/page.tsx +++ b/src/app/(main)/m/admin/wh-stock-status/page.tsx @@ -1,7 +1,7 @@ "use client"; import { useCallback, useEffect, useState } from "react"; -import { RefreshCcw, Warehouse, Download } from "lucide-react"; +import { RefreshCcw, Warehouse, Download, LayoutGrid, Columns3 } from "lucide-react"; import { downloadXlsx } from "@/lib/xlsx-export"; interface Wh { OBJID: string; WH_CODE: string; WH_NAME: string } @@ -31,6 +31,8 @@ export default function WhStockStatusPage() { const [warehouses, setWarehouses] = useState([]); const [items, setItems] = useState([]); const [loading, setLoading] = useState(false); + // 보기 모드: by-wh = 헤더가 창고(가로로 김) / by-item = 헤더가 품목(오른쪽으로 길게) + const [viewMode, setViewMode] = useState<"by-wh" | "by-item">("by-wh"); const load = useCallback(async () => { setLoading(true); @@ -80,7 +82,18 @@ export default function WhStockStatusPage() { 기간 내 발주(출고요청/완료/계산서/입금) 수량과 현재고를 창고별로 나란히. 발주수량 = 현재 보유 재고, 여유분 = 현재고 − 기간 내 발주된 출고 예정 수량 (해당 창고 기준).

-
+
+ {/* 보기 모드 토글 */} +
+ + +
setRange([e.target.value, dateTo])} className="h-9 px-3 rounded border border-slate-300 text-sm" /> ~ @@ -100,54 +113,108 @@ export default function WhStockStatusPage() {
- - - - - - {warehouses.map((w) => ( - - ))} - - - - {items.length === 0 ? ( - - ) : items.flatMap((it) => [ - - - - {warehouses.map((w) => { - const v = Number(it.STOCK[w.WH_CODE] ?? 0); - return ( - - ); - })} - , - - - {warehouses.map((w) => { - const v = Number(it.AVAILABLE[w.WH_CODE] ?? 0); - const negative = v < 0; - return ( - - ); - })} - , - ])} - -
품목분류 - {w.WH_NAME} -
- {loading ? "조회 중..." : "데이터가 없습니다."} -
- {it.ITEM_NAME} -
{it.ITEM_CODE}
-
발주수량 - {v === 0 ? "-" : fmt(v)} -
여유분 - {v === 0 ? "-" : fmt(v)} -
+ {viewMode === "by-wh" ? ( + /* 보기 1: 헤더=창고(가로), 행=품목 */ + + + + + + {warehouses.map((w) => ( + + ))} + + + + {items.length === 0 ? ( + + ) : items.flatMap((it) => [ + + + + {warehouses.map((w) => { + const v = Number(it.STOCK[w.WH_CODE] ?? 0); + return ( + + ); + })} + , + + + {warehouses.map((w) => { + const v = Number(it.AVAILABLE[w.WH_CODE] ?? 0); + const negative = v < 0; + return ( + + ); + })} + , + ])} + +
품목분류 + {w.WH_NAME} +
+ {loading ? "조회 중..." : "데이터가 없습니다."} +
+ {it.ITEM_NAME} +
{it.ITEM_CODE}
+
발주수량 + {v === 0 ? "-" : fmt(v)} +
여유분 + {v === 0 ? "-" : fmt(v)} +
+ ) : ( + /* 보기 2: 헤더=품목(가로), 행=창고 7줄 — 전치 */ + + + + + + {items.map((it) => ( + + ))} + + + + {items.length === 0 || warehouses.length === 0 ? ( + + ) : warehouses.flatMap((w) => [ + + + + {items.map((it) => { + const v = Number(it.STOCK[w.WH_CODE] ?? 0); + return ( + + ); + })} + , + + + {items.map((it) => { + const v = Number(it.AVAILABLE[w.WH_CODE] ?? 0); + const negative = v < 0; + return ( + + ); + })} + , + ])} + +
창고분류 +
{it.ITEM_NAME}
+
{it.ITEM_CODE}
+
+ {loading ? "조회 중..." : "데이터가 없습니다."} +
+ {w.WH_NAME} +
{w.WH_CODE}
+
발주수량 + {v === 0 ? "-" : fmt(v)} +
여유분 + {v === 0 ? "-" : fmt(v)} +
+ )}
);