Online Smart Notes Organizer
Select a note to view or edit
Or create a new one to get started!
Your notes are saved automatically in your browser's local storage. They are not sent to any server.
Confirm Deletion
Are you sure you want to delete this note? This action cannot be undone.
${note.content || 'No content'}
${new Date(note.updatedAt).toLocaleDateString()}
${note.priority}
`;
item.addEventListener('click', () => handleNoteSelect(note.id));
notesListEl.appendChild(item);
});
};
/**
* Displays the selected note in the editor panel.
* @param {number} id - The ID of the note to display.
*/
const displayNoteInEditor = (id) => {
const note = notes.find(n => n.id === id);
if (!note) {
showWelcomeScreen();
return;
}
noteTitleEl.value = note.title;
noteContentEl.value = note.content;
notePriorityEl.value = note.priority;
noteTagsEl.value = note.tags.join(', ');
showEditor();
};
// --- UI Visibility Toggles ---
const showEditor = () => {
welcomeScreen.classList.add('hidden');
editorView.classList.remove('hidden');
editorView.classList.add('flex');
};
const showWelcomeScreen = () => {
welcomeScreen.classList.remove('hidden');
editorView.classList.add('hidden');
editorView.classList.remove('flex');
activeNoteId = null;
renderNotesList(searchInput.value);
};
const showDeleteModal = () => deleteModal.classList.add('flex');
const hideDeleteModal = () => deleteModal.classList.remove('flex');
// --- Event Handlers ---
/**
* Handles creating a new note.
*/
const handleNewNote = () => {
const newNote = {
id: Date.now(),
title: 'Untitled Note',
content: '',
tags: [],
priority: 'medium',
createdAt: new Date(),
updatedAt: new Date()
};
notes.push(newNote);
saveNotes();
activeNoteId = newNote.id;
renderNotesList();
displayNoteInEditor(newNote.id);
noteTitleEl.focus();
noteTitleEl.select();
};
/**
* Handles selecting a note from the list.
* @param {number} id - The ID of the selected note.
*/
const handleNoteSelect = (id) => {
activeNoteId = id;
renderNotesList(searchInput.value);
displayNoteInEditor(id);
};
/**
* Handles updating the active note's content.
*/
const handleNoteUpdate = () => {
if (!activeNoteId) return;
const note = notes.find(n => n.id === activeNoteId);
if (note) {
note.title = noteTitleEl.value;
note.content = noteContentEl.value;
note.priority = notePriorityEl.value;
note.tags = noteTagsEl.value.split(',').map(tag => tag.trim()).filter(Boolean);
note.updatedAt = new Date();
saveNotes();
renderNotesList(searchInput.value);
}
};
/**
* Handles initiating the note deletion process.
*/
const handleDeleteNote = () => {
if (!activeNoteId) return;
noteToDeleteId = activeNoteId;
showDeleteModal();
};
/**
* Handles the final confirmation of note deletion.
*/
const handleConfirmDelete = () => {
if (!noteToDeleteId) return;
notes = notes.filter(note => note.id !== noteToDeleteId);
saveNotes();
hideDeleteModal();
noteToDeleteId = null;
activeNoteId = null;
showWelcomeScreen();
renderNotesList();
};
/**
* Generates a PDF of the currently filtered notes.
*/
const generatePDF = () => {
const { jsPDF } = window.jspdf;
const pdf = new jsPDF({
orientation: 'p',
unit: 'mm',
format: 'a4'
});
const query = searchInput.value;
const filteredNotes = notes
.filter(note =>
note.title.toLowerCase().includes(query.toLowerCase()) ||
note.content.toLowerCase().includes(query.toLowerCase())
)
.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt));
pdf.setFontSize(18);
pdf.text('My Smart Notes', 105, 20, { align: 'center' });
if(query) {
pdf.setFontSize(10);
pdf.text(`Filtered by: "${query}"`, 105, 27, { align: 'center' });
}
let yPosition = 40;
const pageHeight = pdf.internal.pageSize.height;
const margin = 15;
filteredNotes.forEach((note, index) => {
if (yPosition > pageHeight - margin) {
pdf.addPage();
yPosition = 20;
}
pdf.setFontSize(14);
pdf.setFont(undefined, 'bold');
pdf.text(note.title, margin, yPosition);
yPosition += 7;
pdf.setFontSize(10);
pdf.setFont(undefined, 'normal');
pdf.text(`Priority: ${note.priority} | Last Updated: ${new Date(note.updatedAt).toLocaleString()}`, margin, yPosition);
yPosition += 5;
if (note.tags.length > 0) {
pdf.setFont(undefined, 'italic');
pdf.text(`Tags: ${note.tags.join(', ')}`, margin, yPosition);
yPosition += 5;
}
pdf.setFont(undefined, 'normal');
const contentLines = pdf.splitTextToSize(note.content, pdf.internal.pageSize.width - (margin * 2));
pdf.text(contentLines, margin, yPosition);
yPosition += (contentLines.length * 5) + 10; // Add extra space after each note
if(index < filteredNotes.length - 1) {
pdf.setDrawColor(200); // Light gray line
pdf.line(margin, yPosition - 5, pdf.internal.pageSize.width - margin, yPosition - 5);
}
});
pdf.save('Smart_Notes_Export.pdf');
};
// --- Event Listeners Setup ---
newNoteBtn.addEventListener('click', handleNewNote);
searchInput.addEventListener('input', (e) => renderNotesList(e.target.value));
pdfDownloadBtn.addEventListener('click', generatePDF);
// Auto-save on editor changes
[noteTitleEl, noteContentEl, notePriorityEl, noteTagsEl].forEach(el => {
el.addEventListener('input', handleNoteUpdate);
});
// Delete modal listeners
deleteNoteBtn.addEventListener('click', handleDeleteNote);
cancelDeleteBtn.addEventListener('click', hideDeleteModal);
confirmDeleteBtn.addEventListener('click', handleConfirmDelete);
// --- Initial Load ---
loadNotes();
renderNotesList();
});
