feat: frontend note deletion support

This commit is contained in:
ae 2025-04-21 15:13:34 +03:00
parent 30bacd11fc
commit 2b1ce51d31
Signed by: ae
GPG Key ID: 995EFD5C1B532B3E
4 changed files with 95 additions and 5 deletions

View File

@ -226,6 +226,14 @@
@apply bg-[var(--dark-background)];
}
.sidebar-item-content {
@apply flex flex-col;
}
.sidebar-item-bottom-row {
@apply mt-1 flex items-center justify-between;
}
.sidebar-item-text {
@apply text-xs text-[var(--light-text)]/60;
}
@ -234,6 +242,30 @@
@apply text-[var(--dark-text)]/60;
}
.sidebar-item-delete {
@apply flex h-6.5 w-6.5 items-center justify-center rounded-lg border-1 border-[var(--light-accent)]/20 bg-transparent p-1;
}
.dark .sidebar-item-delete {
@apply border-[var(--dark-accent)]/20;
}
.sidebar-item-delete > svg {
@apply text-[var(--light-accent)]/50;
}
.dark .sidebar-item-delete > svg {
@apply text-[var(--dark-accent)]/50;
}
.sidebar-item-delete:hover > svg {
@apply text-[var(--light-accent)] transition-colors delay-100;
}
.dark .sidebar-item-delete:hover > svg {
@apply text-[var(--dark-accent)];
}
.sidebar-divider {
@apply divide-y divide-[var(--light-text)]/20;
}

View File

@ -164,6 +164,22 @@
}
}
const deleteNote = async (noteID: string) => {
try {
await apiClient.deleteNote(noteID)
// If we're deleting the currently active note, clear the current note
if ($currentFullNote && $currentFullNote.id === noteID) {
currentFullNote.set(null)
}
// Refresh the notes list due to updates being pushed to server
await loadNotes()
} catch (err) {
cError.set(`Failed to delete note: ${err instanceof Error ? err.message : "Unknown error"}`)
}
}
const logout = async () => {
await apiClient.logout()
}
@ -190,6 +206,7 @@
{logout}
{createNewNote}
{selectNote}
{deleteNote}
on:close={closeSidebar}
/>

View File

@ -2,6 +2,7 @@
import type { NoteMetadata, FullNote } from "$lib/client"
import Close from "$lib/icons/Close.svelte"
import CreateNew from "$lib/icons/CreateNew.svelte"
import Delete from "$lib/icons/Delete.svelte"
import Logout from "$lib/icons/Logout.svelte"
import Search from "$lib/icons/Search.svelte"
import Settings from "$lib/icons/Settings.svelte"
@ -13,7 +14,8 @@
export let toggleSettings: () => void
export let logout: () => Promise<void>
export let createNewNote: () => Promise<void>
export let selectNote: (noteId: string, fetchRemote: boolean) => Promise<void>
export let selectNote: (noteID: string, fetchRemote: boolean) => Promise<void>
export let deleteNote: (noteID: string) => Promise<void>
const formatDate = (dateString: string | Date): string => {
if (!dateString) {
@ -35,6 +37,14 @@
sidebarOpen = false
}
const handleDeleteNote = (event: MouseEvent, noteID: string) => {
event.stopPropagation()
if (confirm("Are you sure you want to delete this note?")) {
deleteNote(noteID)
}
}
const handleNoteKeydown = (event: KeyboardEvent, noteID: string) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault() // Prevent page scroll on space
@ -103,10 +113,24 @@
role="option"
aria-selected={currentNote && note.id === currentNote.id}
>
<h3 class="truncate font-bold">{note.title || "Untitled Note"}</h3>
<p class="sidebar-item-text mt-1 italic">
{formatDate(note.updatedAt)}
</p>
<div class="sidebar-item-content">
<!-- Note metadata description -->
<h3 class="truncate font-bold">{note.title || "Untitled Note"}</h3>
<div class="sidebar-item-bottom-row">
<p class="sidebar-item-text mt-1 italic">
{formatDate(note.updatedAt)}
</p>
<!-- Note delete button -->
<button
on:click={(e) => handleDeleteNote(e, note.id)}
class="sidebar-item-delete"
aria-label="Delete note"
>
<Delete />
</button>
</div>
</div>
</li>
{/each}
</ul>

View File

@ -0,0 +1,17 @@
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="currentColor">
<path d="M10 12V17" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path d="M14 12V17" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path d="M4 7H20" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M6 10V18C6 19.6569 7.34315 21 9 21H15C16.6569 21 18 19.6569 18 18V10"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M9 5C9 3.89543 9.89543 3 11 3H13C14.1046 3 15 3.89543 15 5V7H9V5Z"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>

After

Width:  |  Height:  |  Size: 673 B