/** * 메인 애플리케이션 Alpine.js 컴포넌트 */ // 메인 문서 앱 컴포넌트 window.documentApp = () => ({ // 상태 isAuthenticated: false, user: null, loading: false, // 문서 관련 documents: [], tags: [], selectedTag: '', viewMode: 'grid', // 'grid' 또는 'list' // 검색 searchQuery: '', searchResults: [], // 모달 상태 showUploadModal: false, showProfile: false, showMyNotes: false, showBookmarks: false, showAdmin: false, // 초기화 async init() { // 인증 상태 확인 await this.checkAuth(); // 인증 상태 변경 이벤트 리스너 window.addEventListener('auth-changed', (event) => { this.isAuthenticated = event.detail.isAuthenticated; this.user = event.detail.user; if (this.isAuthenticated) { this.loadInitialData(); } else { this.resetData(); } }); // 초기 데이터 로드 if (this.isAuthenticated) { await this.loadInitialData(); } }, // 인증 상태 확인 async checkAuth() { if (!api.token) { this.isAuthenticated = false; return; } try { this.user = await api.getCurrentUser(); this.isAuthenticated = true; } catch (error) { console.error('Auth check failed:', error); this.isAuthenticated = false; api.setToken(null); } }, // 초기 데이터 로드 async loadInitialData() { this.loading = true; try { await Promise.all([ this.loadDocuments(), this.loadTags() ]); } catch (error) { console.error('Failed to load initial data:', error); } finally { this.loading = false; } }, // 데이터 리셋 resetData() { this.documents = []; this.tags = []; this.selectedTag = ''; this.searchQuery = ''; this.searchResults = []; }, // 문서 목록 로드 async loadDocuments() { try { const params = {}; if (this.selectedTag) { params.tag = this.selectedTag; } this.documents = await api.getDocuments(params); } catch (error) { console.error('Failed to load documents:', error); this.showNotification('문서 목록을 불러오는데 실패했습니다', 'error'); } }, // 태그 목록 로드 async loadTags() { try { this.tags = await api.getTags(); } catch (error) { console.error('Failed to load tags:', error); } }, // 문서 검색 async searchDocuments() { if (!this.searchQuery.trim()) { this.searchResults = []; return; } try { const results = await api.search({ q: this.searchQuery, limit: 20 }); this.searchResults = results.results; } catch (error) { console.error('Search failed:', error); } }, // 문서 열기 openDocument(document) { // 문서 뷰어 페이지로 이동 window.location.href = `/viewer.html?id=${document.id}`; }, // 로그아웃 async logout() { try { await api.logout(); this.isAuthenticated = false; this.user = null; this.resetData(); } catch (error) { console.error('Logout failed:', error); } }, // 날짜 포맷팅 formatDate(dateString) { const date = new Date(dateString); return date.toLocaleDateString('ko-KR', { year: 'numeric', month: 'short', day: 'numeric' }); }, // 알림 표시 showNotification(message, type = 'info') { // 간단한 알림 구현 (나중에 토스트 라이브러리로 교체 가능) const notification = document.createElement('div'); notification.className = `fixed top-4 right-4 p-4 rounded-lg text-white z-50 ${ type === 'error' ? 'bg-red-500' : type === 'success' ? 'bg-green-500' : 'bg-blue-500' }`; notification.textContent = message; document.body.appendChild(notification); setTimeout(() => { notification.remove(); }, 3000); } }); // 파일 업로드 컴포넌트 window.uploadModal = () => ({ show: false, uploading: false, uploadForm: { title: '', description: '', tags: '', is_public: false, document_date: '', html_file: null, pdf_file: null }, uploadError: '', // 파일 선택 onFileSelect(event, fileType) { const file = event.target.files[0]; if (file) { this.uploadForm[fileType] = file; // HTML 파일의 경우 제목 자동 설정 if (fileType === 'html_file' && !this.uploadForm.title) { this.uploadForm.title = file.name.replace(/\.[^/.]+$/, ""); } } }, // 업로드 실행 async upload() { if (!this.uploadForm.html_file) { this.uploadError = 'HTML 파일을 선택해주세요'; return; } if (!this.uploadForm.title.trim()) { this.uploadError = '제목을 입력해주세요'; return; } this.uploading = true; this.uploadError = ''; try { const formData = new FormData(); formData.append('title', this.uploadForm.title); formData.append('description', this.uploadForm.description); formData.append('tags', this.uploadForm.tags); formData.append('is_public', this.uploadForm.is_public); formData.append('html_file', this.uploadForm.html_file); if (this.uploadForm.pdf_file) { formData.append('pdf_file', this.uploadForm.pdf_file); } if (this.uploadForm.document_date) { formData.append('document_date', this.uploadForm.document_date); } await api.uploadDocument(formData); // 성공시 모달 닫기 및 목록 새로고침 this.show = false; this.resetForm(); // 문서 목록 새로고침 window.dispatchEvent(new CustomEvent('documents-changed')); // 성공 알림 document.querySelector('[x-data="documentApp"]').__x.$data.showNotification('문서가 성공적으로 업로드되었습니다', 'success'); } catch (error) { this.uploadError = error.message; } finally { this.uploading = false; } }, // 폼 리셋 resetForm() { this.uploadForm = { title: '', description: '', tags: '', is_public: false, document_date: '', html_file: null, pdf_file: null }; this.uploadError = ''; // 파일 입력 필드 리셋 const fileInputs = document.querySelectorAll('input[type="file"]'); fileInputs.forEach(input => input.value = ''); } }); // 문서 변경 이벤트 리스너 window.addEventListener('documents-changed', () => { const app = document.querySelector('[x-data="documentApp"]').__x.$data; if (app && app.isAuthenticated) { app.loadDocuments(); app.loadTags(); } });