feat: 워크스페이스 탭 자동복원 + 주문 입금확인 토글 + 메뉴 개명(전화접수→주문접수)
종량제3 세션 작업. - 워크스페이스 탭 계정별 저장·자동복원(member_workspace_tabs 자동생성, pref/workspace-tabs) - 주문접수 관리 입금확인(so_paid) 수동 토글(phoneOrderMarkPaid, order/phone/manage/paid) - 메뉴 '전화 접수 관리' → '주문접수관리' 개명(피드백 #35) + 시드/개명 SQL Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -69,12 +69,14 @@
|
||||
<input type="date" lang="ko" name="so_delivery_date" id="detail-delivery-date-input" class="border border-gray-300 rounded px-2 py-0.5 text-sm"/>
|
||||
</div>
|
||||
<div><span class="font-semibold text-gray-700 inline-block w-20">상태</span> <span id="detail-status">-</span></div>
|
||||
<div><span class="font-semibold text-gray-700 inline-block w-20">입금상태</span> <span id="detail-paid-status" class="font-semibold">-</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center justify-between gap-2 px-1">
|
||||
<span class="text-sm font-semibold text-gray-700">접수 품목 내역</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<button type="button" id="btn-toggle-paid" class="border border-emerald-300 text-emerald-700 px-3 py-1 rounded-sm text-sm hover:bg-emerald-50" disabled>입금확인</button>
|
||||
<button type="submit" id="btn-save" class="bg-btn-search text-white px-3 py-1 rounded-sm text-sm shadow hover:opacity-90" disabled>주문 수정 저장</button>
|
||||
<button type="button" id="btn-receipt" class="border border-gray-300 text-gray-700 px-3 py-1 rounded-sm text-sm hover:bg-gray-50" disabled>입금자 영수증 출력</button>
|
||||
<button type="submit" id="btn-cancel-order" form="order-cancel-form" class="border border-red-300 text-red-600 px-3 py-1 rounded-sm text-sm hover:bg-red-50" disabled>주문 취소</button>
|
||||
@@ -238,6 +240,8 @@
|
||||
const btnSave = document.getElementById('btn-save');
|
||||
const btnCancel = document.getElementById('btn-cancel-order');
|
||||
const btnReceipt = document.getElementById('btn-receipt');
|
||||
const btnTogglePaid = document.getElementById('btn-toggle-paid');
|
||||
const paidApi = new URL('<?= base_url('bag/order/phone/manage/paid') ?>', window.location.href).pathname;
|
||||
const receiptBase = '<?= base_url('bag/order/phone/receipt') ?>';
|
||||
btnReceipt?.addEventListener('click', () => {
|
||||
const id = inputSoIdx.value;
|
||||
@@ -252,6 +256,43 @@
|
||||
|
||||
const nf = (n) => new Intl.NumberFormat('ko-KR').format(n || 0);
|
||||
|
||||
function paintPaidButton(order) {
|
||||
if (!btnTogglePaid) return;
|
||||
const paid = order && Number(order.so_paid) === 1;
|
||||
btnTogglePaid.textContent = paid ? '입금확인 취소' : '입금확인';
|
||||
btnTogglePaid.className = paid
|
||||
? 'border border-gray-300 text-gray-600 px-3 py-1 rounded-sm text-sm hover:bg-gray-50'
|
||||
: 'border border-emerald-300 text-emerald-700 px-3 py-1 rounded-sm text-sm hover:bg-emerald-50';
|
||||
}
|
||||
|
||||
btnTogglePaid?.addEventListener('click', async () => {
|
||||
const id = inputSoIdx.value;
|
||||
if (!id) return;
|
||||
const o = orderMap.get(String(id));
|
||||
if (!o) return;
|
||||
const nextPaid = Number(o.so_paid) === 1 ? 0 : 1;
|
||||
if (nextPaid === 0 && !confirm('입금확인을 취소하면 이 주문은 포장(스캔)이 차단됩니다.\n계속할까요?')) return;
|
||||
const body = new URLSearchParams();
|
||||
body.set(csrfName, csrfHash);
|
||||
body.set('so_idx', String(id));
|
||||
body.set('paid', String(nextPaid));
|
||||
btnTogglePaid.disabled = true;
|
||||
try {
|
||||
const res = await fetch(paidApi, { method: 'POST', credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' }, body });
|
||||
const data = await res.json();
|
||||
if (data && data.csrf) csrfHash = data.csrf;
|
||||
if (!data || !data.ok) { alert((data && data.message) || '처리에 실패했습니다.'); btnTogglePaid.disabled = false; return; }
|
||||
o.so_paid = nextPaid;
|
||||
setHeader(o);
|
||||
paintPaidButton(o);
|
||||
btnTogglePaid.disabled = false;
|
||||
renderList(); // 리스트의 입금 표시 갱신
|
||||
} catch (e) {
|
||||
alert('네트워크 오류로 처리하지 못했습니다.');
|
||||
btnTogglePaid.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
function setHeader(order) {
|
||||
var t = function (id, v) { document.getElementById(id).textContent = (v === undefined || v === null || v === '') ? '-' : v; };
|
||||
t('detail-so-no', order ? displayNo(order) : '');
|
||||
@@ -263,6 +304,12 @@
|
||||
t('detail-shop-addr', order ? order.ds_addr : '');
|
||||
t('detail-order-date', order ? order.so_order_date : '');
|
||||
t('detail-status', order ? ((order.so_status === 'cancelled') ? '취소' : '정상') : '');
|
||||
var ps = document.getElementById('detail-paid-status');
|
||||
if (ps) {
|
||||
var paid = order && Number(order.so_paid) === 1;
|
||||
ps.textContent = order ? (paid ? '입금완료' : '미입금') : '-';
|
||||
ps.style.color = order ? (paid ? '#059669' : '#e11d48') : '';
|
||||
}
|
||||
// 배달일 — 수정 가능한 date 입력
|
||||
var dd = document.getElementById('detail-delivery-date-input');
|
||||
if (dd) {
|
||||
@@ -346,6 +393,7 @@
|
||||
btnSave.disabled = isCancelled;
|
||||
btnCancel.disabled = isCancelled;
|
||||
if (btnReceipt) btnReceipt.disabled = false;
|
||||
if (btnTogglePaid) { btnTogglePaid.disabled = isCancelled; paintPaidButton(order); }
|
||||
|
||||
renderPacking(order); // 포장 명세 탭 동기화
|
||||
|
||||
|
||||
Reference in New Issue
Block a user