// /js/report-viewer-ui.js /** * 데이터를 가공하여 UI에 표시하기 좋은 요약 형태로 변환합니다. * @param {Array} rawData - 서버에서 받은 원시 데이터 배열 * @param {string} selectedDate - 선택된 날짜 * @returns {object} - 요약 정보와 작업자별로 그룹화된 데이터를 포함하는 객체 */ export function processReportData(rawData, selectedDate) { if (!Array.isArray(rawData) || rawData.length === 0) { return null; } const workerGroups = {}; let totalHours = 0; let errorCount = 0; rawData.forEach(item => { const workerName = item.worker_name || '미지정'; const workHours = parseFloat(item.work_hours || 0); totalHours += workHours; if (item.work_status_id === 2) errorCount++; // '에러' 상태 ID가 2라고 가정 if (!workerGroups[workerName]) { workerGroups[workerName] = { worker_name: workerName, total_hours: 0, entries: [] }; } workerGroups[workerName].total_hours += workHours; workerGroups[workerName].entries.push(item); }); return { summary: { date: selectedDate, total_workers: Object.keys(workerGroups).length, total_hours: totalHours, total_entries: rawData.length, error_count: errorCount }, workers: Object.values(workerGroups) }; } function displaySummary(summary) { const elements = { totalWorkers: summary.total_workers, totalHours: `${summary.total_hours}시간`, totalEntries: `${summary.total_entries}개`, errorCount: `${summary.error_count}개` }; Object.entries(elements).forEach(([id, value]) => { const el = document.getElementById(id); if (el) el.textContent = value; }); document.getElementById('reportSummary').style.display = 'block'; } function createWorkEntryElement(entry) { const entryDiv = document.createElement('div'); entryDiv.className = `work-entry ${entry.work_status_id === 2 ? 'error-entry' : ''}`; entryDiv.innerHTML = `
${entry.project_name || '프로젝트 미지정'}
${entry.work_hours || 0}시간
작업 유형: ${entry.work_type_name || '-'}
${entry.work_status_id === 2 ? `
에러 유형: ${entry.error_type_name || '에러'}
` : ''}
`; return entryDiv; } function displayWorkersDetails(workers) { const workersListEl = document.getElementById('workersList'); workersListEl.innerHTML = ''; workers.forEach(worker => { const workerCard = document.createElement('div'); workerCard.className = 'worker-card'; workerCard.innerHTML = `
👤 ${worker.worker_name}
총 ${worker.total_hours}시간
`; const entriesContainer = document.createElement('div'); entriesContainer.className = 'work-entries'; worker.entries.forEach(entry => entriesContainer.appendChild(createWorkEntryElement(entry))); workerCard.appendChild(entriesContainer); workersListEl.appendChild(workerCard); }); document.getElementById('workersReport').style.display = 'block'; } const hideElement = (id) => { const el = document.getElementById(id); if (el) el.style.display = 'none'; }; /** * 가공된 데이터를 받아 화면 전체를 렌더링합니다. * @param {object|null} processedData - 가공된 데이터 또는 데이터가 없을 경우 null */ export function renderReport(processedData) { hideElement('loadingSpinner'); hideElement('errorMessage'); hideElement('noDataMessage'); hideElement('reportSummary'); hideElement('workersReport'); hideElement('exportSection'); if (!processedData) { document.getElementById('noDataMessage').style.display = 'block'; return; } displaySummary(processedData.summary); displayWorkersDetails(processedData.workers); document.getElementById('exportSection').style.display = 'block'; } export function showLoading(isLoading) { document.getElementById('loadingSpinner').style.display = isLoading ? 'flex' : 'none'; if(isLoading) { hideElement('errorMessage'); hideElement('noDataMessage'); } } export function showError(message) { const errorEl = document.getElementById('errorMessage'); errorEl.querySelector('.error-text').textContent = message; errorEl.style.display = 'block'; hideElement('loadingSpinner'); }