/** * Todo 관리 기능 */ let todos = []; let currentPhoto = null; let currentFilter = 'all'; // 페이지 로드 시 초기화 document.addEventListener('DOMContentLoaded', () => { setupTodoForm(); setupPhotoUpload(); setupFilters(); updateItemCounts(); loadRegisteredItems(); }); // Todo 폼 설정 function setupTodoForm() { const todoForm = document.getElementById('todoForm'); if (todoForm) { todoForm.addEventListener('submit', handleTodoSubmit); } } // 사진 업로드 설정 function setupPhotoUpload() { const cameraInput = document.getElementById('cameraInput'); const galleryInput = document.getElementById('galleryInput'); if (cameraInput) { cameraInput.addEventListener('change', handlePhotoUpload); } if (galleryInput) { galleryInput.addEventListener('change', handlePhotoUpload); } } // 필터 설정 function setupFilters() { // 필터 탭 클릭 이벤트는 HTML에서 onclick으로 처리 } // Todo 제출 처리 async function handleTodoSubmit(event) { event.preventDefault(); const content = document.getElementById('todoContent').value.trim(); if (!content) { alert('할일 내용을 입력해주세요.'); return; } try { showLoading(true); const todoData = { content: content, photo: currentPhoto, status: 'draft', created_at: new Date().toISOString() }; // 임시 저장 (백엔드 구현 전까지) const newTodo = { id: Date.now(), ...todoData, user_id: currentUser?.id || 1 }; todos.unshift(newTodo); // 실제 API 호출 (백엔드 구현 후 사용) /* const newTodo = await TodoAPI.createTodo(todoData); todos.unshift(newTodo); */ // 폼 초기화 및 목록 업데이트 clearForm(); loadRegisteredItems(); updateItemCounts(); // 성공 메시지 showToast('항목이 등록되었습니다!', 'success'); } catch (error) { console.error('할일 추가 실패:', error); alert(error.message || '할일 추가에 실패했습니다.'); } finally { showLoading(false); } } // 사진 업로드 처리 async function handlePhotoUpload(event) { const files = event.target.files; if (!files || files.length === 0) return; const file = files[0]; try { showLoading(true); // 이미지 압축 const compressedImage = await ImageUtils.compressImage(file, { maxWidth: 800, maxHeight: 600, quality: 0.8 }); currentPhoto = compressedImage; // 미리보기 표시 const previewContainer = document.getElementById('photoPreview'); const previewImage = document.getElementById('previewImage'); if (previewContainer && previewImage) { previewImage.src = compressedImage; previewContainer.classList.remove('hidden'); } } catch (error) { console.error('이미지 처리 실패:', error); alert('이미지 처리에 실패했습니다.'); } finally { showLoading(false); } } // 카메라 열기 function openCamera() { const cameraInput = document.getElementById('cameraInput'); if (cameraInput) { cameraInput.click(); } } // 갤러리 열기 function openGallery() { const galleryInput = document.getElementById('galleryInput'); if (galleryInput) { galleryInput.click(); } } // 사진 제거 function removePhoto() { currentPhoto = null; const previewContainer = document.getElementById('photoPreview'); const previewImage = document.getElementById('previewImage'); if (previewContainer) { previewContainer.classList.add('hidden'); } if (previewImage) { previewImage.src = ''; } // 파일 입력 초기화 const cameraInput = document.getElementById('cameraInput'); const galleryInput = document.getElementById('galleryInput'); if (cameraInput) cameraInput.value = ''; if (galleryInput) galleryInput.value = ''; } // 폼 초기화 function clearForm() { const todoForm = document.getElementById('todoForm'); if (todoForm) { todoForm.reset(); } removePhoto(); } // Todo 목록 로드 async function loadTodos() { try { // 임시 데이터 (백엔드 구현 전까지) if (todos.length === 0) { todos = [ { id: 1, content: '프로젝트 문서 검토', status: 'active', photo: null, created_at: new Date(Date.now() - 86400000).toISOString(), user_id: 1 }, { id: 2, content: '회의 준비', status: 'completed', photo: null, created_at: new Date(Date.now() - 172800000).toISOString(), user_id: 1 } ]; } // 실제 API 호출 (백엔드 구현 후 사용) /* todos = await TodoAPI.getTodos(currentFilter); */ renderTodos(); } catch (error) { console.error('할일 목록 로드 실패:', error); showToast('할일 목록을 불러오는데 실패했습니다.', 'error'); } } // Todo 목록 렌더링 function renderTodos() { const todoList = document.getElementById('todoList'); const emptyState = document.getElementById('emptyState'); if (!todoList || !emptyState) return; // 필터링 const filteredTodos = todos.filter(todo => { if (currentFilter === 'all') return true; if (currentFilter === 'active') return ['draft', 'scheduled', 'active', 'delayed'].includes(todo.status); if (currentFilter === 'completed') return todo.status === 'completed'; return todo.status === currentFilter; }); // 빈 상태 처리 if (filteredTodos.length === 0) { todoList.innerHTML = ''; emptyState.classList.remove('hidden'); return; } emptyState.classList.add('hidden'); // Todo 항목 렌더링 todoList.innerHTML = filteredTodos.map(todo => `
${todo.photo ? `
첨부 사진
` : ''}

${todo.content}

${getStatusText(todo.status)} ${formatDate(todo.created_at)}
${todo.status !== 'completed' ? ` ` : ''}
`).join(''); } // Todo 상태 토글 async function toggleTodo(id) { try { const todo = todos.find(t => t.id === id); if (!todo) return; const newStatus = todo.status === 'completed' ? 'active' : 'completed'; // 임시 업데이트 todo.status = newStatus; // 실제 API 호출 (백엔드 구현 후 사용) /* await TodoAPI.updateTodo(id, { status: newStatus }); */ renderTodos(); showToast(newStatus === 'completed' ? '할일을 완료했습니다!' : '할일을 다시 활성화했습니다!', 'success'); } catch (error) { console.error('할일 상태 변경 실패:', error); showToast('상태 변경에 실패했습니다.', 'error'); } } // Todo 삭제 async function deleteTodo(id) { if (!confirm('정말로 이 할일을 삭제하시겠습니까?')) return; try { // 임시 삭제 todos = todos.filter(t => t.id !== id); // 실제 API 호출 (백엔드 구현 후 사용) /* await TodoAPI.deleteTodo(id); */ renderTodos(); showToast('할일이 삭제되었습니다.', 'success'); } catch (error) { console.error('할일 삭제 실패:', error); showToast('삭제에 실패했습니다.', 'error'); } } // Todo 편집 (향후 구현) function editTodo(id) { // TODO: 편집 모달 또는 인라인 편집 구현 console.log('편집 기능 구현 예정:', id); } // 필터 변경 function filterTodos(filter) { currentFilter = filter; // 탭 활성화 상태 변경 document.querySelectorAll('.filter-tab').forEach(tab => { tab.classList.remove('active', 'bg-white', 'text-blue-600'); tab.classList.add('text-gray-600'); }); event.target.classList.add('active', 'bg-white', 'text-blue-600'); event.target.classList.remove('text-gray-600'); renderTodos(); } // 상태 아이콘 반환 function getStatusIcon(status) { const icons = { draft: 'fa-edit', scheduled: 'fa-calendar', active: 'fa-play', completed: 'fa-check', delayed: 'fa-clock' }; return icons[status] || 'fa-circle'; } // 상태 텍스트 반환 function getStatusText(status) { const texts = { draft: '검토 필요', scheduled: '예정됨', active: '진행중', completed: '완료됨', delayed: '지연됨' }; return texts[status] || '알 수 없음'; } // 날짜 포맷팅 function formatDate(dateString) { const date = new Date(dateString); const now = new Date(); const diffTime = now - date; const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24)); if (diffDays === 0) return '오늘'; if (diffDays === 1) return '어제'; if (diffDays < 7) return `${diffDays}일 전`; return date.toLocaleDateString('ko-KR'); } // 토스트 메시지 표시 function showToast(message, type = 'info') { // 간단한 alert으로 대체 (향후 토스트 UI 구현) console.log(`[${type.toUpperCase()}] ${message}`); if (type === 'error') { alert(message); } } // 페이지 이동 함수 function goToPage(pageType) { const pages = { 'todo': 'todo.html', 'calendar': 'calendar.html', 'checklist': 'checklist.html' }; if (pages[pageType]) { window.location.href = pages[pageType]; } else { console.error('Unknown page type:', pageType); } } // 대시보드로 이동 function goToDashboard() { window.location.href = 'dashboard.html'; } // 분류 센터로 이동 function goToClassify() { window.location.href = 'classify.html'; } // 항목 등록 후 인덱스 업데이트 function updateItemCounts() { // TODO: API에서 각 분류별 항목 수를 가져와서 업데이트 // 임시로 하드코딩된 값 사용 const todoCount = document.getElementById('todoCount'); const calendarCount = document.getElementById('calendarCount'); const checklistCount = document.getElementById('checklistCount'); if (todoCount) todoCount.textContent = '2개'; if (calendarCount) calendarCount.textContent = '3개'; if (checklistCount) checklistCount.textContent = '5개'; } // 등록된 항목들 로드 function loadRegisteredItems() { // 임시 데이터 (실제로는 API에서 가져옴) const sampleItems = [ { id: 1, content: '프로젝트 문서 정리', photo_url: null, category: null, created_at: '2024-01-15' }, { id: 2, content: '회의 자료 준비', photo_url: null, category: 'todo', created_at: '2024-01-16' }, { id: 3, content: '월말 보고서 작성', photo_url: null, category: 'calendar', created_at: '2024-01-17' } ]; renderRegisteredItems(sampleItems); } // 등록된 항목들 렌더링 function renderRegisteredItems(items) { const itemsList = document.getElementById('itemsList'); const emptyState = document.getElementById('emptyState'); if (!itemsList || !emptyState) return; if (!items || items.length === 0) { itemsList.innerHTML = ''; emptyState.classList.remove('hidden'); return; } emptyState.classList.add('hidden'); itemsList.innerHTML = items.map(item => `
${item.photo_url ? `
첨부 사진
` : ''}

${item.content}

등록: ${formatDate(item.created_at)} ${item.category ? ` ${getCategoryText(item.category)} ` : ` 미분류 `}
`).join(''); } // 분류 모달 표시 function showClassificationModal(itemId) { // TODO: 분류 선택 모달 구현 console.log('분류 모달 표시:', itemId); // 임시로 confirm으로 분류 선택 const choice = prompt('분류를 선택하세요:\n1. Todo (시작 날짜)\n2. 캘린더 (마감 기한)\n3. 체크리스트 (기한 없음)\n\n번호를 입력하세요:'); if (choice) { const categories = { '1': 'todo', '2': 'calendar', '3': 'checklist' }; const category = categories[choice]; if (category) { classifyItem(itemId, category); } } } // 항목 분류 function classifyItem(itemId, category) { // TODO: API 호출하여 항목 분류 업데이트 console.log('항목 분류:', itemId, category); // 분류 후 해당 페이지로 이동 goToPage(category); } // 분류별 색상 function getCategoryColor(category) { const colors = { 'todo': 'bg-blue-100 text-blue-800', 'calendar': 'bg-orange-100 text-orange-800', 'checklist': 'bg-green-100 text-green-800' }; return colors[category] || 'bg-gray-100 text-gray-800'; } // 분류별 텍스트 function getCategoryText(category) { const texts = { 'todo': 'Todo', 'calendar': '캘린더', 'checklist': '체크리스트' }; return texts[category] || '미분류'; } // 전역으로 사용 가능하도록 export window.loadTodos = loadTodos; window.openCamera = openCamera; window.openGallery = openGallery; window.removePhoto = removePhoto; window.clearForm = clearForm; window.toggleTodo = toggleTodo; window.deleteTodo = deleteTodo; window.editTodo = editTodo; window.filterTodos = filterTodos; window.goToPage = goToPage; window.goToDashboard = goToDashboard; window.goToClassify = goToClassify; window.showClassificationModal = showClassificationModal; window.updateItemCounts = updateItemCounts;