// 노트북 관리 애플리케이션 컴포넌트 window.notebooksApp = () => ({ // 상태 관리 notebooks: [], stats: null, loading: false, saving: false, error: '', // 알림 시스템 notification: { show: false, message: '', type: 'info' // 'success', 'error', 'info' }, // 필터링 searchQuery: '', activeOnly: true, sortBy: 'updated_at', // 검색 디바운스 searchTimeout: null, // 모달 상태 showCreateModal: false, showEditModal: false, showDeleteModal: false, editingNotebook: null, deletingNotebook: null, deleting: false, // 노트북 폼 notebookForm: { title: '', description: '', color: '#3B82F6', icon: 'book', is_active: true, sort_order: 0 }, // 인증 상태 isAuthenticated: false, currentUser: null, // API 클라이언트 api: null, // 색상 옵션 availableColors: [ '#3B82F6', // blue '#10B981', // emerald '#F59E0B', // amber '#EF4444', // red '#8B5CF6', // violet '#06B6D4', // cyan '#84CC16', // lime '#F97316', // orange '#EC4899', // pink '#6B7280' // gray ], // 아이콘 옵션 availableIcons: [ { value: 'book', label: '📖 책' }, { value: 'sticky-note', label: '📝 노트' }, { value: 'lightbulb', label: '💡 아이디어' }, { value: 'graduation-cap', label: '🎓 학습' }, { value: 'briefcase', label: '💼 업무' }, { value: 'heart', label: '❤️ 개인' }, { value: 'code', label: '💻 개발' }, { value: 'palette', label: '🎨 창작' }, { value: 'flask', label: '🧪 연구' }, { value: 'star', label: '⭐ 즐겨찾기' } ], // 초기화 async init() { console.log('📚 Notebooks App 초기화 시작'); // API 클라이언트 초기화 this.api = new DocumentServerAPI(); // 인증 상태 확인 await this.checkAuthStatus(); if (this.isAuthenticated) { await this.loadStats(); await this.loadNotebooks(); } // 헤더 로드 await this.loadHeader(); }, // 인증 상태 확인 async checkAuthStatus() { try { const user = await this.api.getCurrentUser(); this.isAuthenticated = true; this.currentUser = user; console.log('✅ 인증됨:', user.username || user.email); } catch (error) { console.log('❌ 인증되지 않음'); this.isAuthenticated = false; this.currentUser = null; window.location.href = '/'; } }, // 헤더 로드 async loadHeader() { try { if (typeof loadHeaderComponent === 'function') { await loadHeaderComponent(); } else if (typeof window.loadHeaderComponent === 'function') { await window.loadHeaderComponent(); } else { console.warn('헤더 로더 함수를 찾을 수 없습니다.'); } } catch (error) { console.error('헤더 로드 실패:', error); } }, // 통계 정보 로드 async loadStats() { try { this.stats = await this.api.getNotebookStats(); console.log('📊 노트북 통계 로드됨:', this.stats); } catch (error) { console.error('통계 로드 실패:', error); } }, // 노트북 목록 로드 async loadNotebooks() { this.loading = true; this.error = ''; try { const queryParams = { active_only: this.activeOnly, sort_by: this.sortBy, order: 'desc' }; if (this.searchQuery) { queryParams.search = this.searchQuery; } this.notebooks = await this.api.getNotebooks(queryParams); console.log('📚 노트북 로드됨:', this.notebooks.length, '개'); } catch (error) { console.error('노트북 로드 실패:', error); this.error = '노트북을 불러오는 중 오류가 발생했습니다.'; } finally { this.loading = false; } }, // 검색 디바운스 debounceSearch() { clearTimeout(this.searchTimeout); this.searchTimeout = setTimeout(() => { this.loadNotebooks(); }, 300); }, // 새로고침 async refreshNotebooks() { await Promise.all([ this.loadStats(), this.loadNotebooks() ]); }, // 노트북 열기 (노트 목록으로 이동) openNotebook(notebook) { window.location.href = `/notes.html?notebook_id=${notebook.id}¬ebook_name=${encodeURIComponent(notebook.title)}`; }, // 노트북에 노트 생성 createNoteInNotebook(notebook) { window.location.href = `/note-editor.html?notebook_id=${notebook.id}¬ebook_name=${encodeURIComponent(notebook.title)}`; }, // 노트북 편집 editNotebook(notebook) { this.editingNotebook = notebook; this.notebookForm = { title: notebook.title, description: notebook.description || '', color: notebook.color, icon: notebook.icon, is_active: notebook.is_active, sort_order: notebook.sort_order }; this.showEditModal = true; }, // 노트북 삭제 (모달 표시) deleteNotebook(notebook) { this.deletingNotebook = notebook; this.showDeleteModal = true; }, // 삭제 확인 async confirmDeleteNotebook() { if (!this.deletingNotebook) return; this.deleting = true; try { await this.api.deleteNotebook(this.deletingNotebook.id, true); // force=true this.showNotification('노트북이 삭제되었습니다.', 'success'); this.closeDeleteModal(); await this.refreshNotebooks(); } catch (error) { console.error('노트북 삭제 실패:', error); this.showNotification('노트북 삭제에 실패했습니다.', 'error'); } finally { this.deleting = false; } }, // 삭제 모달 닫기 closeDeleteModal() { this.showDeleteModal = false; this.deletingNotebook = null; this.deleting = false; }, // 노트북 저장 async saveNotebook() { if (!this.notebookForm.title.trim()) { this.showNotification('제목을 입력해주세요.', 'error'); return; } this.saving = true; try { if (this.showEditModal && this.editingNotebook) { // 편집 await this.api.updateNotebook(this.editingNotebook.id, this.notebookForm); this.showNotification('노트북이 수정되었습니다.', 'success'); } else { // 생성 await this.api.createNotebook(this.notebookForm); this.showNotification('노트북이 생성되었습니다.', 'success'); } this.closeModal(); await this.refreshNotebooks(); } catch (error) { console.error('노트북 저장 실패:', error); this.showNotification('노트북 저장에 실패했습니다.', 'error'); } finally { this.saving = false; } }, // 모달 닫기 closeModal() { this.showCreateModal = false; this.showEditModal = false; this.editingNotebook = null; this.notebookForm = { title: '', description: '', color: '#3B82F6', icon: 'book', is_active: true, sort_order: 0 }; }, // 날짜 포맷팅 formatDate(dateString) { const date = new Date(dateString); const now = new Date(); const diffTime = Math.abs(now - date); const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); if (diffDays === 1) { return '오늘'; } else if (diffDays === 2) { return '어제'; } else if (diffDays <= 7) { return `${diffDays - 1}일 전`; } else { return date.toLocaleDateString('ko-KR'); } }, // 알림 표시 showNotification(message, type = 'info') { this.notification = { show: true, message: message, type: type }; // 3초 후 자동으로 숨김 setTimeout(() => { this.notification.show = false; }, 3000); } });