Online Task-Oriented Note-Taking Tool

Task-Oriented Note-Taking Tool

Organize your projects, notes, and tasks all in one place.

Projects / Notes

Select a note or create a new one

Your notes and tasks will be displayed here.

No notes yet.

`; } notes.forEach(note => { const button = document.createElement('button'); button.type = 'button'; button.dataset.id = note.id; button.textContent = note.title || 'Untitled Note'; button.className = `w-full text-left p-2 rounded-md transition-colors ${note.id === activeNoteId ? 'bg-blue-500 text-white' : 'bg-slate-100 hover:bg-slate-200'}`; button.onclick = () => selectNote(note.id); notesListEl.appendChild(button); }); }; const renderEditor = () => { const activeNote = notes.find(n => n.id === activeNoteId); if (activeNote) { welcomePanel.classList.add('hidden'); editorPanel.classList.remove('hidden'); downloadPdfBtn.style.display = 'inline-block'; noteTitleInput.value = activeNote.title; noteContentInput.value = activeNote.content; // Render tasks taskListEl.innerHTML = ''; activeNote.tasks.forEach(task => { const taskDiv = document.createElement('div'); taskDiv.className = 'flex items-center gap-2 p-2 bg-slate-50 rounded'; const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.checked = task.completed; checkbox.className = 'h-5 w-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500'; checkbox.onchange = () => toggleTask(task.id); const label = document.createElement('label'); label.textContent = task.text; label.className = `flex-grow task-item ${task.completed ? 'completed' : ''}`; const deleteBtn = document.createElement('button'); deleteBtn.type = 'button'; deleteBtn.innerHTML = `×`; deleteBtn.className = 'font-bold text-red-500 hover:text-red-700 px-2'; deleteBtn.onclick = () => deleteTask(task.id); taskDiv.appendChild(checkbox); taskDiv.appendChild(label); taskDiv.appendChild(deleteBtn); taskListEl.appendChild(taskDiv); }); } else { welcomePanel.classList.remove('hidden'); editorPanel.classList.add('hidden'); downloadPdfBtn.style.display = 'none'; } }; const selectNote = (id) => { activeNoteId = id; renderNotesList(); renderEditor(); }; const createNewNote = () => { const newNote = { id: Date.now(), title: 'Untitled Note', content: '', tasks: [] }; notes.unshift(newNote); saveNotes(); selectNote(newNote.id); }; const updateNote = () => { const activeNote = notes.find(n => n.id === activeNoteId); if (activeNote) { activeNote.title = noteTitleInput.value; activeNote.content = noteContentInput.value; saveNotes(); renderNotesList(); // Update title in list } }; const deleteActiveNote = () => { if (!activeNoteId) return; notes = notes.filter(n => n.id !== activeNoteId); activeNoteId = null; saveNotes(); renderNotesList(); renderEditor(); }; const addTask = (text) => { const activeNote = notes.find(n => n.id === activeNoteId); if (activeNote) { const newTask = { id: Date.now(), text: text, completed: false }; activeNote.tasks.push(newTask); saveNotes(); renderEditor(); } }; const toggleTask = (taskId) => { const activeNote = notes.find(n => n.id === activeNoteId); const task = activeNote?.tasks.find(t => t.id === taskId); if (task) { task.completed = !task.completed; saveNotes(); renderEditor(); } }; const deleteTask = (taskId) => { const activeNote = notes.find(n => n.id === activeNoteId); if (activeNote) { activeNote.tasks = activeNote.tasks.filter(t => t.id !== taskId); saveNotes(); renderEditor(); } }; const generatePDF = async () => { const activeNote = notes.find(n => n.id === activeNoteId); if (!activeNote) { alert("Please select a note to download."); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF(); const pdfContent = document.getElementById('pdf-content'); pdfContent.innerHTML = ''; pdfContent.classList.remove('hidden'); const pdfContainer = document.createElement('div'); pdfContainer.style.padding = '25px'; pdfContainer.style.width = '600px'; const title = document.createElement('h1'); title.innerText = activeNote.title; title.style.textAlign = 'center'; title.style.fontSize = '24px'; title.style.marginBottom = '20px'; pdfContainer.appendChild(title); // Notes Section const notesTitle = document.createElement('h2'); notesTitle.innerText = 'Notes'; notesTitle.style.fontSize = '18px'; notesTitle.style.borderBottom = '1px solid #ccc'; notesTitle.style.paddingBottom = '5px'; notesTitle.style.marginBottom = '10px'; pdfContainer.appendChild(notesTitle); const noteP = document.createElement('p'); noteP.style.whiteSpace = 'pre-wrap'; noteP.innerText = activeNote.content || '(No notes written)'; noteP.style.marginBottom = '20px'; pdfContainer.appendChild(noteP); // Tasks Section if (activeNote.tasks.length > 0) { const tasksTitle = document.createElement('h2'); tasksTitle.innerText = 'Tasks'; tasksTitle.style.fontSize = '18px'; tasksTitle.style.borderBottom = '1px solid #ccc'; tasksTitle.style.paddingBottom = '5px'; tasksTitle.style.marginBottom = '10px'; pdfContainer.appendChild(tasksTitle); activeNote.tasks.forEach(task => { const taskP = document.createElement('p'); taskP.innerText = `${task.completed ? '[x]' : '[ ]'} ${task.text}`; pdfContainer.appendChild(taskP); }); } pdfContent.appendChild(pdfContainer); try { const canvas = await html2canvas(pdfContainer, { scale: 2 }); const imgData = canvas.toDataURL('image/png'); const pdfWidth = doc.internal.pageSize.getWidth(); const pdfHeight = (canvas.height * pdfWidth) / canvas.width; doc.addImage(imgData, 'PNG', 10, 10, pdfWidth - 20, pdfHeight > 277 ? 277 : pdfHeight - 20); doc.save(`${activeNote.title.replace(/ /g, '_')}.pdf`); } catch (error) { console.error("PDF generation failed:", error); } finally { pdfContent.classList.add('hidden'); pdfContent.innerHTML = ''; } }; // Event Listeners addNoteBtn.addEventListener('click', createNewNote); noteTitleInput.addEventListener('input', updateNote); noteContentInput.addEventListener('input', updateNote); deleteNoteBtn.addEventListener('click', deleteActiveNote); downloadPdfBtn.addEventListener('click', generatePDF); addTaskForm.addEventListener('submit', (e) => { e.preventDefault(); const taskText = taskInput.value.trim(); if (taskText) { addTask(taskText); taskInput.value = ''; } }); // Initial Render renderNotesList(); renderEditor(); });
Scroll to Top