/* ===== Visit Management (출입 관리 - 관리자) ===== */ let allRequests = []; let actionRequestId = null; /* ===== Status badge for visit requests ===== */ function vrStatusBadge(s) { const m = { pending: ['badge-amber', '대기중'], approved: ['badge-green', '승인됨'], rejected: ['badge-red', '반려됨'], training_completed: ['badge-blue', '교육완료'] }; const [cls, label] = m[s] || ['badge-gray', s]; return `${label}`; } /* ===== Load requests ===== */ async function loadRequests() { try { const params = new URLSearchParams(); const status = document.getElementById('filterStatus').value; const dateFrom = document.getElementById('filterDateFrom').value; const dateTo = document.getElementById('filterDateTo').value; if (status) params.set('status', status); if (dateFrom) params.set('start_date', dateFrom); if (dateTo) params.set('end_date', dateTo); const res = await api('/visit-requests/requests?' + params.toString()); allRequests = res.data || []; renderStats(); renderRequestsTable(); } catch (e) { showToast('데이터 로드 실패: ' + e.message, 'error'); } } function renderStats() { const counts = { pending: 0, approved: 0, rejected: 0, training_completed: 0 }; allRequests.forEach(r => { if (counts[r.status] !== undefined) counts[r.status]++; }); document.getElementById('statPending').textContent = counts.pending; document.getElementById('statApproved').textContent = counts.approved; document.getElementById('statRejected').textContent = counts.rejected; document.getElementById('statTrainingDone').textContent = counts.training_completed; } function renderRequestsTable() { const tbody = document.getElementById('requestsTableBody'); if (!allRequests.length) { tbody.innerHTML = '
업체: ${escapeHtml(r.visitor_company)}
방문일: ${formatDate(r.visit_date)} ${r.visit_time ? String(r.visit_time).substring(0, 5) : ''}
작업장: ${escapeHtml(r.workplace_name || '-')}
인원: ${r.visitor_count}명
이 출입 신청을 승인하시겠습니까?
`; document.getElementById('approveModal').classList.remove('hidden'); } function closeApproveModal() { document.getElementById('approveModal').classList.add('hidden'); actionRequestId = null; } async function confirmApprove() { if (!actionRequestId) return; try { await api('/visit-requests/requests/' + actionRequestId + '/approve', { method: 'PUT', body: JSON.stringify({}) }); showToast('승인되었습니다'); closeApproveModal(); await loadRequests(); } catch (e) { showToast(e.message, 'error'); } } /* ===== Reject Modal ===== */ function openRejectModal(id) { const r = allRequests.find(x => x.request_id === id); if (!r) return; actionRequestId = id; document.getElementById('rejectDetail').innerHTML = `업체: ${escapeHtml(r.visitor_company)}
방문일: ${formatDate(r.visit_date)} ${r.visit_time ? String(r.visit_time).substring(0, 5) : ''}
작업장: ${escapeHtml(r.workplace_name || '-')}
`; document.getElementById('rejectionReason').value = ''; document.getElementById('rejectModal').classList.remove('hidden'); } function closeRejectModal() { document.getElementById('rejectModal').classList.add('hidden'); actionRequestId = null; } async function confirmReject() { if (!actionRequestId) return; const reason = document.getElementById('rejectionReason').value.trim(); if (!reason) { showToast('반려 사유를 입력해주세요', 'error'); return; } try { await api('/visit-requests/requests/' + actionRequestId + '/reject', { method: 'PUT', body: JSON.stringify({ rejection_reason: reason }) }); showToast('반려되었습니다'); closeRejectModal(); await loadRequests(); } catch (e) { showToast(e.message, 'error'); } } /* ===== Detail Modal ===== */ function openDetailModal(id) { const r = allRequests.find(x => x.request_id === id); if (!r) return; document.getElementById('detailContent').innerHTML = `관리자 권한이 필요합니다