const noteInput = document.getElementById("note-input"); const charCount = document.getElementById("char-count"); const saveBtn = document.getElementById("save-btn"); const searchInput = document.getElementById("search-input"); const notesList = document.getElementById("notes-list"); const emptyState = document.getElementById("empty-state"); const noteTemplate = document.getElementById("note-template"); const themeToggle = document.getElementById("theme-toggle"); let notes = []; let editingNoteId = null; const THEME_KEY = "quick-notes-theme"; function formatDate(dateString) { const date = new Date(dateString.replace(" ", "T")); if (Number.isNaN(date.getTime())) { return dateString; } return date.toLocaleString(); } function updateCounter() { charCount.textContent = `${noteInput.value.length} characters`; } function applySavedTheme() { const saved = localStorage.getItem(THEME_KEY); if (saved === "dark") { document.body.classList.add("dark"); } } function toggleTheme() { document.body.classList.toggle("dark"); const active = document.body.classList.contains("dark") ? "dark" : "light"; localStorage.setItem(THEME_KEY, active); } async function fetchNotes() { const response = await fetch("/notes"); if (!response.ok) { throw new Error("Failed to fetch notes"); } notes = await response.json(); renderNotes(); } async function saveNote() { const content = noteInput.value.trim(); if (!content) { alert("Please write a note before saving."); return; } const method = editingNoteId ? "PUT" : "POST"; const endpoint = editingNoteId ? `/notes/${editingNoteId}` : "/notes"; const response = await fetch(endpoint, { method, headers: { "Content-Type": "application/json" }, body: JSON.stringify({ content }), }); if (!response.ok) { alert("Could not save note."); return; } editingNoteId = null; noteInput.value = ""; updateCounter(); saveBtn.textContent = "Save Note"; await fetchNotes(); } async function deleteNote(noteId) { const confirmed = confirm("Delete this note?"); if (!confirmed) { return; } const response = await fetch(`/notes/${noteId}`, { method: "DELETE" }); if (!response.ok) { alert("Could not delete note."); return; } if (editingNoteId === noteId) { editingNoteId = null; noteInput.value = ""; saveBtn.textContent = "Save Note"; updateCounter(); } await fetchNotes(); } async function copyNote(content) { try { await navigator.clipboard.writeText(content); alert("Note copied."); } catch (error) { alert("Clipboard copy failed."); } } function beginEdit(note) { editingNoteId = note.id; noteInput.value = note.content; saveBtn.textContent = "Update Note"; updateCounter(); noteInput.focus(); } function renderNotes() { const query = searchInput.value.trim().toLowerCase(); const filteredNotes = notes.filter((note) => note.content.toLowerCase().includes(query) ); notesList.innerHTML = ""; if (filteredNotes.length === 0) { emptyState.style.display = "block"; emptyState.textContent = query ? "No notes matched your search." : "No notes yet. Save your first one."; return; } emptyState.style.display = "none"; filteredNotes.forEach((note, index) => { const fragment = noteTemplate.content.cloneNode(true); const noteItem = fragment.querySelector(".note-item"); noteItem.style.animationDelay = `${index * 45}ms`; fragment.querySelector(".note-content").textContent = note.content; fragment.querySelector(".note-created").textContent = `Created: ${formatDate(note.created_at)}`; fragment.querySelector(".note-updated").textContent = `Updated: ${formatDate(note.updated_at)}`; fragment.querySelector(".edit-btn").addEventListener("click", () => beginEdit(note)); fragment.querySelector(".delete-btn").addEventListener("click", () => deleteNote(note.id)); fragment.querySelector(".copy-btn").addEventListener("click", () => copyNote(note.content)); notesList.appendChild(fragment); }); } noteInput.addEventListener("input", updateCounter); saveBtn.addEventListener("click", saveNote); searchInput.addEventListener("input", renderNotes); themeToggle.addEventListener("click", toggleTheme); applySavedTheme(); updateCounter(); fetchNotes().catch(() => { emptyState.style.display = "block"; emptyState.textContent = "Could not load notes. Refresh to retry."; });