From 585b7d45770c7604ce3b9bddf1f9729fb5f2eb8b Mon Sep 17 00:00:00 2001 From: chpark Date: Wed, 20 May 2026 23:22:14 +0900 Subject: [PATCH] =?UTF-8?q?feat(orders/admin):=20=EB=B0=9C=EC=A3=BC=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=2030=EC=B4=88=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=20=EA=B0=B1=EC=8B=A0=20+=20=EB=B3=B8=EC=9D=B8=20=EB=9D=BD?= =?UTF-8?q?=EC=9D=80=20=EC=B4=88=EB=A1=9D=20=E2=9C=8F=EF=B8=8F=20"?= =?UTF-8?q?=EB=82=B4=EA=B0=80=20=EC=88=98=EC=A0=95=20=EC=A4=91"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - load() 를 30초 setInterval 로 주기적 호출 → 누가 새로 락을 잡았는지 실시간 반영 - 카드/테이블 row 모두: • 본인 락 (EDITING_BY === myUserId): 초록 배경 + ✏️ "내가 수정 중" • 다른 사람 락: 빨강 배경 + 🔒 보유자명 (기존) Co-Authored-By: Claude Opus 4.7 (1M context) --- src/app/(main)/m/admin/orders/page.tsx | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/app/(main)/m/admin/orders/page.tsx b/src/app/(main)/m/admin/orders/page.tsx index d648fef..1bdb68a 100644 --- a/src/app/(main)/m/admin/orders/page.tsx +++ b/src/app/(main)/m/admin/orders/page.tsx @@ -148,6 +148,12 @@ export default function AdminOrdersPage() { // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => { load(); }, [load]); + // 발주 리스트 30초마다 자동 갱신 — 락 상태(누가 수정 중) 실시간 반영 + useEffect(() => { + const id = setInterval(() => { load(); }, 30000); + return () => clearInterval(id); + }, [load]); + const reloadDetail = useCallback(async () => { if (!activeId) { setDetail(null); return; } const res = await fetch("/api/m/orders/detail", { @@ -427,12 +433,13 @@ export default function AdminOrdersPage() { {orders.map((o) => { const checked = selected.has(o.OBJID); const active = o.OBJID === activeId; + const lockedByMeRow = !!o.EDITING_BY && o.EDITING_BY === myUserId; const lockedByOtherUser = !!o.EDITING_BY && o.EDITING_BY !== myUserId; return (
setActiveId(o.OBJID)} - className={`border rounded-lg p-3 cursor-pointer transition ${active ? "border-emerald-500 bg-emerald-50/60 shadow-sm" : lockedByOtherUser ? "border-rose-200 bg-rose-50/40" : "border-slate-200 bg-white hover:bg-slate-50"}`} + className={`border rounded-lg p-3 cursor-pointer transition ${active ? "border-emerald-500 bg-emerald-50/60 shadow-sm" : lockedByMeRow ? "border-emerald-300 bg-emerald-50/30" : lockedByOtherUser ? "border-rose-200 bg-rose-50/40" : "border-slate-200 bg-white hover:bg-slate-50"}`} >
@@ -445,6 +452,9 @@ export default function AdminOrdersPage() { className="accent-emerald-600 disabled:opacity-30" /> {o.ORDER_NO} + {lockedByMeRow && ( + ✏️ + )} {lockedByOtherUser && ( 🔒 )} @@ -455,6 +465,9 @@ export default function AdminOrdersPage() {
{o.ORDER_DATE}
{o.COMPANY_NAME}
+ {lockedByMeRow && ( +
✏️ 내가 수정 중
+ )} {lockedByOtherUser && (
🔒 {o.EDITING_BY_NAME} 수정 중
)} @@ -486,13 +499,14 @@ export default function AdminOrdersPage() { ) : orders.map((o) => { const checked = selected.has(o.OBJID); const active = o.OBJID === activeId; + const lockedByMeRow = !!o.EDITING_BY && o.EDITING_BY === myUserId; const lockedByOtherUser = !!o.EDITING_BY && o.EDITING_BY !== myUserId; return ( setActiveId(o.OBJID)} - className={`border-t border-slate-100 cursor-pointer ${active ? "bg-emerald-50/60" : lockedByOtherUser ? "bg-rose-50/30 hover:bg-rose-50/60" : "hover:bg-slate-50"}`} - title={lockedByOtherUser ? `🔒 ${o.EDITING_BY_NAME} 님이 수정 중` : ""} + className={`border-t border-slate-100 cursor-pointer ${active ? "bg-emerald-50/60" : lockedByMeRow ? "bg-emerald-50/30 hover:bg-emerald-50/50" : lockedByOtherUser ? "bg-rose-50/30 hover:bg-rose-50/60" : "hover:bg-slate-50"}`} + title={lockedByMeRow ? "✏️ 내가 수정 중" : lockedByOtherUser ? `🔒 ${o.EDITING_BY_NAME} 님이 수정 중` : ""} > e.stopPropagation()}> + {lockedByMeRow && ✏️} {lockedByOtherUser && 🔒} {o.ORDER_NO} {o.ORDER_DATE} {o.COMPANY_NAME} + {lockedByMeRow &&
✏️ 내가 수정 중
} {lockedByOtherUser &&
🔒 {o.EDITING_BY_NAME}
} ₩{fmt(o.TOTAL_AMOUNT)}