/** * 공통 헤더 로더 * 모든 페이지에서 동일한 헤더를 로드하기 위한 유틸리티 */ class HeaderLoader { constructor() { this.headerLoaded = false; } /** * 헤더 HTML을 로드하고 삽입 */ async loadHeader(targetSelector = '#header-container') { if (this.headerLoaded) { console.log('✅ 헤더가 이미 로드됨'); return; } try { console.log('🔄 헤더 로딩 중...'); const response = await fetch('components/header.html?v=2025012352'); if (!response.ok) { throw new Error(`헤더 로드 실패: ${response.status}`); } const headerHtml = await response.text(); // 헤더 컨테이너 찾기 const container = document.querySelector(targetSelector); if (!container) { throw new Error(`헤더 컨테이너를 찾을 수 없음: ${targetSelector}`); } // 헤더 HTML 삽입 container.innerHTML = headerHtml; this.headerLoaded = true; console.log('✅ 헤더 로드 완료'); // 헤더 로드 완료 이벤트 발생 document.dispatchEvent(new CustomEvent('headerLoaded')); } catch (error) { console.error('❌ 헤더 로드 오류:', error); this.showFallbackHeader(targetSelector); } } /** * 헤더 로드 실패 시 폴백 헤더 표시 */ showFallbackHeader(targetSelector) { const container = document.querySelector(targetSelector); if (container) { container.innerHTML = `
`; } } /** * 현재 페이지 정보 가져오기 */ getCurrentPageInfo() { const path = window.location.pathname; const filename = path.split('/').pop().replace('.html', '') || 'index'; const pageInfo = { filename, isDocumentPage: ['index', 'hierarchy'].includes(filename), isMemoPage: ['memo-tree', 'story-view'].includes(filename) }; return pageInfo; } /** * 페이지별 활성 상태 업데이트 */ updateActiveStates() { const pageInfo = this.getCurrentPageInfo(); // 모든 활성 클래스 제거 document.querySelectorAll('.nav-link, .nav-dropdown-item').forEach(item => { item.classList.remove('active'); }); // 현재 페이지에 따라 활성 상태 설정 console.log('현재 페이지:', pageInfo.filename); if (pageInfo.isDocumentPage) { const docLink = document.getElementById('doc-nav-link'); if (docLink) { docLink.classList.add('active'); console.log('문서 관리 메뉴 활성화'); } } if (pageInfo.isMemoPage) { const memoLink = document.getElementById('memo-nav-link'); if (memoLink) { memoLink.classList.add('active'); console.log('메모장 메뉴 활성화'); } } // 특정 페이지 드롭다운 아이템 활성화 const pageItemMap = { 'index': 'index-nav-item', 'hierarchy': 'hierarchy-nav-item', 'memo-tree': 'memo-tree-nav-item', 'story-view': 'story-view-nav-item', 'search': 'search-nav-link', 'notes': 'notes-nav-link', 'notebooks': 'notebooks-nav-item', 'note-editor': 'note-editor-nav-item' }; const itemId = pageItemMap[pageInfo.filename]; if (itemId) { const item = document.getElementById(itemId); if (item) { item.classList.add('active'); console.log(`${pageInfo.filename} 페이지 아이템 활성화`); } } } } // 전역 인스턴스 생성 window.headerLoader = new HeaderLoader(); // DOM 로드 완료 시 자동 초기화 document.addEventListener('DOMContentLoaded', () => { window.headerLoader.loadHeader(); }); // 헤더 로드 완료 후 활성 상태 업데이트 document.addEventListener('headerLoaded', () => { setTimeout(() => { window.headerLoader.updateActiveStates(); // updateUserMenu 함수 정의 (헤더 로더에서 직접 정의) if (typeof window.updateUserMenu === 'undefined') { window.updateUserMenu = (user) => { console.log('🔄 updateUserMenu 호출됨:', user); const loggedInMenu = document.getElementById('logged-in-menu'); const loginButton = document.getElementById('login-button'); const adminMenuSection = document.getElementById('admin-menu-section'); // 사용자 정보 요소들 const userName = document.getElementById('user-name'); const userRole = document.getElementById('user-role'); const dropdownUserName = document.getElementById('dropdown-user-name'); const dropdownUserEmail = document.getElementById('dropdown-user-email'); const dropdownUserRole = document.getElementById('dropdown-user-role'); if (user) { // 로그인된 상태 console.log('✅ 사용자 로그인 상태 - UI 업데이트'); if (loggedInMenu) { loggedInMenu.classList.remove('hidden'); console.log('✅ 로그인 메뉴 표시'); } if (loginButton) { loginButton.classList.add('hidden'); console.log('✅ 로그인 버튼 숨김'); } // 사용자 정보 업데이트 const displayName = user.full_name || user.email || 'User'; const roleText = user.role === 'root' ? '시스템 관리자' : user.role === 'admin' ? '관리자' : '사용자'; if (userName) userName.textContent = displayName; if (userRole) userRole.textContent = roleText; if (dropdownUserName) dropdownUserName.textContent = displayName; if (dropdownUserEmail) dropdownUserEmail.textContent = user.email || ''; if (dropdownUserRole) dropdownUserRole.textContent = roleText; // 관리자 메뉴 표시/숨김 console.log('🔍 사용자 권한 확인:', { role: user.role, is_admin: user.is_admin, can_manage_books: user.can_manage_books, can_manage_notes: user.can_manage_notes, can_manage_novels: user.can_manage_novels }); if (adminMenuSection) { if (user.role === 'root' || user.role === 'admin' || user.is_admin) { console.log('✅ 관리자 메뉴 표시'); adminMenuSection.classList.remove('hidden'); } else { console.log('❌ 관리자 메뉴 숨김'); adminMenuSection.classList.add('hidden'); } } else { console.log('❌ adminMenuSection 요소를 찾을 수 없음'); } } else { // 로그아웃된 상태 console.log('❌ 로그아웃 상태'); if (loggedInMenu) loggedInMenu.classList.add('hidden'); if (loginButton) loginButton.classList.remove('hidden'); if (adminMenuSection) adminMenuSection.classList.add('hidden'); } }; console.log('✅ updateUserMenu 함수 정의 완료'); } // 사용자 메뉴 상태 설정 (현재 로그인 상태 확인) setTimeout(() => { // 전역 사용자 정보가 있으면 사용, 없으면 토큰으로 확인 if (window.currentUser) { window.updateUserMenu(window.currentUser); } else { // 토큰이 있으면 사용자 정보 다시 가져오기 const token = localStorage.getItem('access_token'); if (token) { fetch('/api/auth/me', { headers: { 'Authorization': `Bearer ${token}` } }) .then(response => response.ok ? response.json() : null) .then(user => { if (user) { window.currentUser = user; window.updateUserMenu(user); } else { window.updateUserMenu(null); } }) .catch(() => window.updateUserMenu(null)); } else { window.updateUserMenu(null); } } }, 200); // 전역 함수들이 정의되지 않은 경우 빈 함수로 초기화 if (typeof window.handleLanguageChange === 'undefined') { window.handleLanguageChange = function(lang) { console.log('언어 변경 함수가 아직 로드되지 않았습니다:', lang); }; } }, 100); });