/** * TBM - Module Loader * TBM 모듈을 초기화하고 연결하는 메인 진입점 * * 로드 순서: * 1. state.js - 전역 상태 관리 * 2. utils.js - 유틸리티 함수 * 3. api.js - API 클라이언트 * 4. index.js - 이 파일 (메인 컨트롤러) */ class TbmController { constructor() { this.state = window.TbmState; this.api = window.TbmAPI; this.utils = window.TbmUtils; this.initialized = false; console.log('[TbmController] 생성'); } /** * 초기화 */ async init() { if (this.initialized) { console.log('[TbmController] 이미 초기화됨'); return; } console.log('🛠️ TBM 관리 페이지 초기화'); // API 함수가 로드될 때까지 대기 let retryCount = 0; while (!window.apiCall && retryCount < 50) { await new Promise(resolve => setTimeout(resolve, 100)); retryCount++; } if (!window.apiCall) { window.showToast?.('시스템을 초기화할 수 없습니다. 페이지를 새로고침해주세요.', 'error'); return; } // 오늘 날짜 설정 (서울 시간대 기준) const today = this.utils.getTodayKST(); const tbmDateEl = document.getElementById('tbmDate'); const sessionDateEl = document.getElementById('sessionDate'); if (tbmDateEl) tbmDateEl.value = today; if (sessionDateEl) sessionDateEl.value = today; // 이벤트 리스너 설정 this.setupEventListeners(); // 초기 데이터 로드 await this.api.loadInitialData(); await this.api.loadTodayOnlyTbm(); // 렌더링 this.displayTodayTbmSessions(); this.initialized = true; console.log('[TbmController] 초기화 완료'); } /** * 이벤트 리스너 설정 */ setupEventListeners() { // 탭 버튼들 document.querySelectorAll('.tbm-tab-btn').forEach(btn => { btn.addEventListener('click', () => { const tabName = btn.dataset.tab; if (tabName) this.switchTbmTab(tabName); }); }); } /** * 탭 전환 */ async switchTbmTab(tabName) { this.state.setCurrentTab(tabName); // 탭 버튼 활성화 상태 변경 document.querySelectorAll('.tbm-tab-btn').forEach(btn => { if (btn.dataset.tab === tabName) { btn.classList.add('active'); } else { btn.classList.remove('active'); } }); // 탭 컨텐츠 표시 변경 document.querySelectorAll('.tbm-tab-content').forEach(content => { content.classList.remove('active'); }); const tabContent = document.getElementById(`${tabName}-tab`); if (tabContent) tabContent.classList.add('active'); // 탭에 따라 데이터 로드 if (tabName === 'tbm-input') { await this.api.loadTodayOnlyTbm(); this.displayTodayTbmSessions(); } else if (tabName === 'tbm-manage') { await this.api.loadRecentTbmGroupedByDate(); this.displayTbmGroupedByDate(); this.updateViewModeIndicator(); } } /** * 오늘의 TBM 세션 표시 */ displayTodayTbmSessions() { const grid = document.getElementById('todayTbmGrid'); const emptyState = document.getElementById('todayEmptyState'); const todayTotalEl = document.getElementById('todayTotalSessions'); const todayCompletedEl = document.getElementById('todayCompletedSessions'); const todayActiveEl = document.getElementById('todayActiveSessions'); const sessions = this.state.todaySessions; if (sessions.length === 0) { if (grid) grid.innerHTML = ''; if (emptyState) emptyState.style.display = 'flex'; if (todayTotalEl) todayTotalEl.textContent = '0'; if (todayCompletedEl) todayCompletedEl.textContent = '0'; if (todayActiveEl) todayActiveEl.textContent = '0'; return; } if (emptyState) emptyState.style.display = 'none'; const completedCount = sessions.filter(s => s.status === 'completed').length; const activeCount = sessions.filter(s => s.status === 'draft').length; if (todayTotalEl) todayTotalEl.textContent = sessions.length; if (todayCompletedEl) todayCompletedEl.textContent = completedCount; if (todayActiveEl) todayActiveEl.textContent = activeCount; if (grid) { grid.innerHTML = sessions.map(session => this.createSessionCard(session)).join(''); } } /** * 날짜별 그룹으로 TBM 표시 */ displayTbmGroupedByDate() { const container = document.getElementById('tbmDateGroupsContainer'); const emptyState = document.getElementById('emptyState'); const totalSessionsEl = document.getElementById('totalSessions'); const completedSessionsEl = document.getElementById('completedSessions'); if (!container) return; const sortedDates = Object.keys(this.state.dateGroupedSessions).sort((a, b) => new Date(b) - new Date(a) ); if (sortedDates.length === 0 || this.state.allLoadedSessions.length === 0) { container.innerHTML = ''; if (emptyState) emptyState.style.display = 'flex'; if (totalSessionsEl) totalSessionsEl.textContent = '0'; if (completedSessionsEl) completedSessionsEl.textContent = '0'; return; } if (emptyState) emptyState.style.display = 'none'; // 통계 업데이트 const completedCount = this.state.allLoadedSessions.filter(s => s.status === 'completed').length; if (totalSessionsEl) totalSessionsEl.textContent = this.state.allLoadedSessions.length; if (completedSessionsEl) completedSessionsEl.textContent = completedCount; // 날짜별 그룹 HTML 생성 const today = this.utils.getTodayKST(); const dayNames = ['일', '월', '화', '수', '목', '금', '토']; container.innerHTML = sortedDates.map(date => { const sessions = this.state.dateGroupedSessions[date]; const dateObj = new Date(date + 'T00:00:00'); const dayName = dayNames[dateObj.getDay()]; const isToday = date === today; const [year, month, day] = date.split('-'); const displayDate = `${parseInt(month)}월 ${parseInt(day)}일`; return `
${displayDate} ${dayName}요일 ${isToday ? '오늘' : ''} ${sessions.length}건
${sessions.map(session => this.createSessionCard(session)).join('')}
`; }).join(''); } /** * 뷰 모드 표시 업데이트 */ updateViewModeIndicator() { const indicator = document.getElementById('viewModeIndicator'); const text = document.getElementById('viewModeText'); if (indicator && text) { if (this.state.isAdminUser()) { indicator.style.display = 'none'; } else { indicator.style.display = 'inline-flex'; text.textContent = '내 TBM'; } } } /** * TBM 세션 카드 생성 */ createSessionCard(session) { const statusBadge = this.utils.getStatusBadge(session.status); const leaderName = session.leader_name || session.created_by_name || '작업 책임자'; const leaderRole = session.leader_name ? (session.leader_job_type || '작업자') : '관리자'; return `

${leaderName} ${leaderRole}

${statusBadge}
📅 ${this.utils.formatDate(session.session_date)} ${session.start_time ? '| ' + session.start_time : ''}
프로젝트 ${session.project_name || '-'}
공정 ${session.work_type_name || '-'}
작업장 ${session.work_location || '-'}
팀원 ${session.team_member_count || 0}명
${session.status === 'draft' ? ` ` : ''}
`; } /** * 디버그 */ debug() { console.log('[TbmController] 상태 디버그:'); this.state.debug(); } } // 전역 인스턴스 생성 window.TbmController = new TbmController(); // 하위 호환성: 기존 전역 함수들 window.switchTbmTab = (tabName) => window.TbmController.switchTbmTab(tabName); window.displayTodayTbmSessions = () => window.TbmController.displayTodayTbmSessions(); window.displayTbmGroupedByDate = () => window.TbmController.displayTbmGroupedByDate(); window.displayTbmSessions = () => window.TbmController.displayTbmGroupedByDate(); window.createSessionCard = (session) => window.TbmController.createSessionCard(session); window.updateViewModeIndicator = () => window.TbmController.updateViewModeIndicator(); // 날짜 그룹 토글 window.toggleDateGroup = function(date) { const group = document.querySelector(`.tbm-date-group[data-date="${date}"]`); if (group) { group.classList.toggle('collapsed'); } }; // DOMContentLoaded 이벤트에서 초기화 document.addEventListener('DOMContentLoaded', () => { setTimeout(() => { window.TbmController.init(); }, 100); }); console.log('[Module] tbm/index.js 로드 완료');