/* ===== 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();
}