/* ===== Entry Dashboard (출입 현황판) ===== */ let dashboardData = []; let currentSourceFilter = ''; let refreshTimer = null; /* ===== Source/Status badges ===== */ function sourceBadge(s) { const m = { tbm: ['badge-blue', 'TBM'], partner: ['badge-green', '협력업체'], visit: ['badge-amber', '방문'] }; const [cls, label] = m[s] || ['badge-gray', s]; return `${label}`; } function entryStatusBadge(s) { const m = { checked_in: ['badge-blue', '체크인'], checked_out: ['badge-gray', '체크아웃'], approved: ['badge-green', '승인'], training_completed: ['badge-blue', '교육완료'], absent: ['badge-red', '불참'] }; const [cls, label] = m[s] || ['badge-gray', s]; return `${label}`; } /* ===== Load dashboard data ===== */ async function loadDashboard() { const date = document.getElementById('dashboardDate').value; try { const [dashRes, statsRes] = await Promise.all([ api('/visit-requests/entry-dashboard?date=' + date), api('/visit-requests/entry-dashboard/stats?date=' + date) ]); dashboardData = dashRes.data || []; updateStats(statsRes.data || {}); renderDashboard(); } catch (e) { showToast('대시보드 로드 실패: ' + e.message, 'error'); } } function updateStats(stats) { const total = stats.external_visit + stats.internal_visit + stats.partner + stats.tbm; document.getElementById('statTotal').textContent = total; document.getElementById('statTbm').textContent = stats.tbm; document.getElementById('statPartner').textContent = stats.partner; document.getElementById('statExternal').textContent = stats.external_visit; document.getElementById('statInternal').textContent = stats.internal_visit; } /* ===== Render table ===== */ function renderDashboard() { const tbody = document.getElementById('dashboardBody'); const filtered = currentSourceFilter ? dashboardData.filter(r => r.source === currentSourceFilter) : dashboardData; if (!filtered.length) { tbody.innerHTML = '데이터가 없습니다'; return; } tbody.innerHTML = filtered.map(r => { const name = escapeHtml(r.visitor_name || '-'); const org = escapeHtml(r.visitor_company || '-'); const workplace = escapeHtml(r.workplace_name || '-'); const inTime = r.check_in_time ? String(r.check_in_time).substring(11, 16) : (r.entry_time ? String(r.entry_time).substring(0, 5) : '-'); const outTime = r.check_out_time ? String(r.check_out_time).substring(11, 16) : '-'; const purpose = escapeHtml(r.purpose_name || '-'); const note = r.source_note ? `${escapeHtml(r.source_note)}` : ''; const count = r.visitor_count > 1 ? ` (${r.visitor_count}명)` : ''; return ` ${sourceBadge(r.source)} ${name}${count} ${org} ${workplace} ${inTime} ${outTime} ${purpose} ${entryStatusBadge(r.status)} ${note} `; }).join(''); } /* ===== Tab filter ===== */ function filterSource(source) { currentSourceFilter = source; document.querySelectorAll('.source-tab').forEach(t => { t.classList.toggle('active', t.dataset.source === source); }); renderDashboard(); } /* ===== Auto refresh ===== */ function setupAutoRefresh() { const cb = document.getElementById('autoRefresh'); cb.addEventListener('change', () => { if (cb.checked) startAutoRefresh(); else stopAutoRefresh(); }); startAutoRefresh(); } function startAutoRefresh() { stopAutoRefresh(); refreshTimer = setInterval(loadDashboard, 180000); // 3분 } function stopAutoRefresh() { if (refreshTimer) { clearInterval(refreshTimer); refreshTimer = null; } } /* ===== Init ===== */ function initEntryDashboard() { if (!initAuth()) return; const today = new Date().toISOString().substring(0, 10); document.getElementById('dashboardDate').value = today; document.getElementById('dashboardDate').addEventListener('change', loadDashboard); // Source tab styling const style = document.createElement('style'); style.textContent = `.source-tab { border-bottom-color: transparent; color: #6b7280; cursor: pointer; } .source-tab:hover { color: #374151; background: #f9fafb; } .source-tab.active { border-bottom-color: #2563eb; color: #2563eb; font-weight: 600; }`; document.head.appendChild(style); loadDashboard(); setupAutoRefresh(); }