feat(orders/admin): 발주 리스트 30초 자동 갱신 + 본인 락은 초록 ✏️ "내가 수정 중"
Deploy momo-erp / deploy (push) Successful in 1m56s
Deploy momo-erp / deploy (push) Successful in 1m56s
- load() 를 30초 setInterval 로 주기적 호출 → 누가 새로 락을 잡았는지 실시간 반영 - 카드/테이블 row 모두: • 본인 락 (EDITING_BY === myUserId): 초록 배경 + ✏️ "내가 수정 중" • 다른 사람 락: 빨강 배경 + 🔒 보유자명 (기존) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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 (
|
||||
<div
|
||||
key={o.OBJID}
|
||||
onClick={() => 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"}`}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2 mb-1.5">
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
@@ -445,6 +452,9 @@ export default function AdminOrdersPage() {
|
||||
className="accent-emerald-600 disabled:opacity-30"
|
||||
/>
|
||||
<span className="font-bold text-sm text-slate-800 truncate">{o.ORDER_NO}</span>
|
||||
{lockedByMeRow && (
|
||||
<span className="text-[10px] font-bold text-emerald-700" title="내가 수정 중">✏️</span>
|
||||
)}
|
||||
{lockedByOtherUser && (
|
||||
<span className="text-[10px] font-bold text-rose-700" title={`${o.EDITING_BY_NAME} 수정 중`}>🔒</span>
|
||||
)}
|
||||
@@ -455,6 +465,9 @@ export default function AdminOrdersPage() {
|
||||
</div>
|
||||
<div className="text-[11px] text-slate-500">{o.ORDER_DATE}</div>
|
||||
<div className="text-xs text-slate-700 truncate" title={o.COMPANY_NAME}>{o.COMPANY_NAME}</div>
|
||||
{lockedByMeRow && (
|
||||
<div className="text-[10px] font-bold text-emerald-700 mt-0.5">✏️ 내가 수정 중</div>
|
||||
)}
|
||||
{lockedByOtherUser && (
|
||||
<div className="text-[10px] font-bold text-rose-700 mt-0.5">🔒 {o.EDITING_BY_NAME} 수정 중</div>
|
||||
)}
|
||||
@@ -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 (
|
||||
<tr
|
||||
key={o.OBJID}
|
||||
onClick={() => 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} 님이 수정 중` : ""}
|
||||
>
|
||||
<td className="px-2 py-2 text-center" onClick={(e) => e.stopPropagation()}>
|
||||
<input
|
||||
@@ -505,12 +519,14 @@ export default function AdminOrdersPage() {
|
||||
/>
|
||||
</td>
|
||||
<td className="px-1.5 py-1.5 font-semibold text-slate-800 whitespace-nowrap text-[11px]">
|
||||
{lockedByMeRow && <span className="mr-1 text-emerald-700" title="내가 수정 중">✏️</span>}
|
||||
{lockedByOtherUser && <span className="mr-1" title={`${o.EDITING_BY_NAME} 수정 중`}>🔒</span>}
|
||||
{o.ORDER_NO}
|
||||
</td>
|
||||
<td className="px-1.5 py-1.5 text-slate-600 whitespace-nowrap text-[11px]">{o.ORDER_DATE}</td>
|
||||
<td className="px-1.5 py-1.5 truncate max-w-[100px] text-[11px]" title={o.COMPANY_NAME}>
|
||||
{o.COMPANY_NAME}
|
||||
{lockedByMeRow && <div className="text-[9px] font-bold text-emerald-700">✏️ 내가 수정 중</div>}
|
||||
{lockedByOtherUser && <div className="text-[9px] font-bold text-rose-600">🔒 {o.EDITING_BY_NAME}</div>}
|
||||
</td>
|
||||
<td className="px-1.5 py-1.5 text-right tabular-nums font-semibold whitespace-nowrap text-[11px]">₩{fmt(o.TOTAL_AMOUNT)}</td>
|
||||
|
||||
Reference in New Issue
Block a user