diff --git a/src/app/(main)/m/admin/orders/page.tsx b/src/app/(main)/m/admin/orders/page.tsx index 1bdb68a..69f9a88 100644 --- a/src/app/(main)/m/admin/orders/page.tsx +++ b/src/app/(main)/m/admin/orders/page.tsx @@ -173,6 +173,10 @@ export default function AdminOrdersPage() { const previousLocked = lockedOrderRef.current; if (previousLocked && previousLocked !== activeId) { releaseLock(previousLocked); + // 옵티미스틱: 리스트에서 이전 락 즉시 제거 + setOrders((prev) => prev.map((o) => + o.OBJID === previousLocked ? { ...o, EDITING_BY: null, EDITING_BY_NAME: null } : o + )); lockedOrderRef.current = ""; } // 이전 heartbeat 정지 @@ -205,6 +209,10 @@ export default function AdminOrdersPage() { setLockedByMe(true); setLockedByOther(null); lockedOrderRef.current = activeId; + // 옵티미스틱: 리스트에 내 락 즉시 반영 + setOrders((prev) => prev.map((o) => + o.OBJID === activeId ? { ...o, EDITING_BY: lj.lockedBy || myUserId, EDITING_BY_NAME: lj.lockedByName || "(나)" } : o + )); // 30초마다 heartbeat heartbeatRef.current = setInterval(async () => { try { @@ -224,6 +232,10 @@ export default function AdminOrdersPage() { } else if (lj.locked) { setLockedByMe(false); setLockedByOther({ name: lj.lockedByName || lj.lockedBy || "다른 담당자" }); + // 옵티미스틱: 리스트에 락 정보 반영 + setOrders((prev) => prev.map((o) => + o.OBJID === activeId ? { ...o, EDITING_BY: lj.lockedBy || "other", EDITING_BY_NAME: lj.lockedByName || "다른 담당자" } : o + )); Swal.fire({ icon: "warning", title: "수정 중인 발주", @@ -236,7 +248,7 @@ export default function AdminOrdersPage() { })(); return () => { cancelled = true; }; - }, [activeId, releaseLock]); + }, [activeId, releaseLock, myUserId]); // 페이지 떠날 때 락 해제 (best-effort) — sendBeacon 으로 keepalive useEffect(() => {