/** * 생산팀 대시보드 — Sprint 003 */ const PAGE_ICONS = { 'dashboard': 'fa-home', 'work.tbm': 'fa-clipboard-list', 'work.report_create': 'fa-file-alt', 'work.analysis': 'fa-chart-bar', 'work.nonconformity': 'fa-exclamation-triangle', 'work.schedule': 'fa-calendar-alt', 'work.meetings': 'fa-users', 'work.daily_status': 'fa-chart-bar', 'work.proxy_input': 'fa-user-edit', 'factory.repair_management': 'fa-tools', 'inspection.daily_patrol': 'fa-route', 'inspection.checkin': 'fa-user-check', 'inspection.work_status': 'fa-briefcase', 'purchase.request': 'fa-shopping-cart', 'purchase.analysis': 'fa-chart-line', 'attendance.my_vacation_info': 'fa-info-circle', 'attendance.monthly': 'fa-calendar', 'attendance.vacation_request': 'fa-paper-plane', 'attendance.vacation_management': 'fa-cog', 'attendance.vacation_allocation': 'fa-plus-circle', 'attendance.annual_overview': 'fa-chart-pie', 'admin.user_management': 'fa-users-cog', 'admin.projects': 'fa-project-diagram', 'admin.tasks': 'fa-tasks', 'admin.workplaces': 'fa-building', 'admin.equipments': 'fa-cogs', 'admin.departments': 'fa-sitemap', 'admin.notifications': 'fa-bell', 'admin.attendance_report': 'fa-clipboard-check', }; const CATEGORY_COLORS = { '작업 관리': '#3b82f6', '공장 관리': '#f59e0b', '소모품 관리': '#10b981', '근태 관리': '#8b5cf6', '시스템 관리': '#6b7280', }; const DEFAULT_COLOR = '#06b6d4'; function escHtml(s) { const d = document.createElement('div'); d.textContent = s; return d.innerHTML; } async function initDashboard() { showSkeleton(); try { const token = typeof getToken === 'function' ? getToken() : (localStorage.getItem('sso_token') || getCookie('sso_token')); if (!token) { showError('로그인이 필요합니다.'); return; } const resp = await fetch('/api/dashboard/my-summary', { headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' } }); if (!resp.ok) throw new Error('API 오류: ' + resp.status); const result = await resp.json(); if (!result.success) throw new Error(result.message || '데이터 로드 실패'); renderDashboard(result.data); } catch (err) { showError(err.message); } } function getCookie(name) { const v = document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)'); return v ? v.pop() : ''; } function renderDashboard(data) { const { user, vacation, overtime, quick_access } = data; // 프로필 카드 const card = document.getElementById('profileCard'); const initial = (user.worker_name || user.name || '?').charAt(0); const vacRemaining = vacation.remaining_days; const vacTotal = vacation.total_days; const vacUsed = vacation.used_days; const vacPct = vacTotal > 0 ? Math.round((vacUsed / vacTotal) * 100) : 0; const vacColor = vacRemaining >= 5 ? 'green' : vacRemaining >= 3 ? 'yellow' : 'red'; const otHours = overtime.total_overtime_hours; const otDays = overtime.overtime_days; card.innerHTML = `
${escHtml(initial)}
${escHtml(user.worker_name || user.name)}
${escHtml(user.job_type || '')}${user.job_type ? ' · ' : ''}${escHtml(user.department_name)}
연차
${vacTotal > 0 ? `
잔여 ${vacRemaining}일
${vacTotal}일 중 ${vacUsed}일 사용
` : `
연차 정보 미등록
`}
연장근로
${otHours.toFixed(1)}h
이번달 ${otDays}일
`; // 아이콘 그리드 renderGrid('deptPagesGrid', 'deptPagesSection', quick_access.department_pages); renderGrid('personalPagesGrid', 'personalPagesSection', quick_access.personal_pages); renderGrid('adminPagesGrid', 'adminPagesSection', quick_access.admin_pages); } function renderGrid(gridId, sectionId, pages) { const grid = document.getElementById(gridId); const section = document.getElementById(sectionId); if (!pages || pages.length === 0) { section.classList.add('hidden'); return; } section.classList.remove('hidden'); // dashboard 자체 제외 const filtered = pages.filter(p => p.page_key !== 'dashboard'); if (filtered.length === 0) { section.classList.add('hidden'); return; } grid.innerHTML = filtered.map(p => { const icon = PAGE_ICONS[p.page_key] || p.icon || 'fa-circle'; const color = CATEGORY_COLORS[p.category] || DEFAULT_COLOR; return `
${escHtml(p.page_name)}
`; }).join(''); } function showSkeleton() { const card = document.getElementById('profileCard'); card.innerHTML = `
`; // 그리드 스켈레톤 ['deptPagesGrid'].forEach(id => { const g = document.getElementById(id); if (g) g.innerHTML = Array(8).fill('
').join(''); }); } function showError(msg) { document.getElementById('profileCard').innerHTML = `

${escHtml(msg || '정보를 불러올 수 없습니다.')}

`; } // tkfb-core.js 인증 완료 후 실행 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => setTimeout(initDashboard, 300)); } else { setTimeout(initDashboard, 300); }