Spaces:
Paused
Paused
File size: 4,475 Bytes
d044ca3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | 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.";
});
|