diff --git a/apps/zitare/apps/web/src/routes/(app)/lists/+page.svelte b/apps/zitare/apps/web/src/routes/(app)/lists/+page.svelte index 05ccbd0e2..4127b8a8a 100644 --- a/apps/zitare/apps/web/src/routes/(app)/lists/+page.svelte +++ b/apps/zitare/apps/web/src/routes/(app)/lists/+page.svelte @@ -16,6 +16,8 @@ let lists = $state([]); let loading = $state(true); + let saving = $state(false); + let deletingId = $state(null); let showCreateModal = $state(false); let newListName = $state(''); let newListDescription = $state(''); @@ -58,11 +60,12 @@ } async function createList() { - if (!newListName.trim()) return; + if (!newListName.trim() || saving) return; const token = await authStore.getValidToken(); if (!token) return; + saving = true; try { const response = await fetch(`${getBackendUrl()}/api/lists`, { method: 'POST', @@ -86,15 +89,18 @@ } } catch (error) { console.error('Failed to create list:', error); + } finally { + saving = false; } } async function deleteList(listId: string) { - if (!confirm($_('lists.confirmDelete'))) return; + if (deletingId || !confirm($_('lists.confirmDelete'))) return; const token = await authStore.getValidToken(); if (!token) return; + deletingId = listId; try { const response = await fetch(`${getBackendUrl()}/api/lists/${listId}`, { method: 'DELETE', @@ -107,6 +113,8 @@ } } catch (error) { console.error('Failed to delete list:', error); + } finally { + deletingId = null; } } @@ -214,16 +222,23 @@ e.stopPropagation(); deleteList(list.id); }} - class="p-2 text-foreground-muted hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-lg transition-colors" + disabled={deletingId === list.id} + class="p-2 text-foreground-muted hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-lg transition-colors disabled:opacity-50" > - - - + {#if deletingId === list.id} +
+ {:else} + + + + {/if} @@ -285,9 +300,14 @@ diff --git a/apps/zitare/apps/web/src/routes/(app)/lists/[id]/+page.svelte b/apps/zitare/apps/web/src/routes/(app)/lists/[id]/+page.svelte index 3d172c151..edbd261de 100644 --- a/apps/zitare/apps/web/src/routes/(app)/lists/[id]/+page.svelte +++ b/apps/zitare/apps/web/src/routes/(app)/lists/[id]/+page.svelte @@ -13,6 +13,9 @@ let list = $state(null); let isLoading = $state(true); + let isSaving = $state(false); + let isAdding = $state(false); + let removingQuoteId = $state(null); let searchTerm = $state(''); let isSearchOpen = $state(false); let showEditModal = $state(false); @@ -83,7 +86,9 @@ } async function handleUpdateList() { - if (list && editName.trim()) { + if (!list || !editName.trim() || isSaving) return; + isSaving = true; + try { const updated = await listsStore.updateList(list.id, { name: editName.trim(), description: editDescription.trim() || undefined, @@ -95,6 +100,8 @@ } else { toast.error($_('lists.detail.toast.updateError')); } + } finally { + isSaving = false; } } @@ -130,32 +137,37 @@ } async function handleAddQuotes() { - if (list) { - const count = selectedQuoteIds.size; + if (!list || isAdding) return; + isAdding = true; + try { let successCount = 0; for (const quoteId of selectedQuoteIds) { const success = await listsStore.addQuoteToList(list.id, quoteId); if (success) successCount++; } if (successCount > 0) { - // Reload list to get updated quote IDs list = await listsStore.getList(list.id); toast.success($_('lists.detail.toast.quotesAdded', { values: { count: successCount } })); } closeAddQuotesModal(); + } finally { + isAdding = false; } } async function handleRemoveQuote(quoteId: string) { - if (list && confirm($_('lists.detail.removeConfirm'))) { + if (!list || removingQuoteId || !confirm($_('lists.detail.removeConfirm'))) return; + removingQuoteId = quoteId; + try { const success = await listsStore.removeQuoteFromList(list.id, quoteId); if (success) { - // Reload list to get updated quote IDs list = await listsStore.getList(list.id); toast.info($_('lists.detail.toast.quoteRemoved')); } else { toast.error($_('lists.detail.toast.removeError')); } + } finally { + removingQuoteId = null; } } @@ -339,16 +351,23 @@ @@ -422,7 +441,16 @@ @@ -480,8 +508,13 @@