fix(ui): custom confirm dialog, picker visibility, remove wiring

Three fixes for the collection detail page:

1. Picker modal never showed because the outer overlay div had
   style="display:none" with no x-show binding — add x-show bound
   to $store.bookPicker.isOpen plus a backdrop and click-to-close.

2. Replace native confirm() with an in-page Alpine modal for UI
   continuity. Add confirm dialog state (showConfirm, confirmMessage,
   pendingAction) and methods (requestRemoveBook, requestBulkRemove,
   executeConfirmed, closeConfirm) to the collections component.
   The actual API calls (doRemoveBook/doBulkRemove) are triggered only
   when the user confirms.

3. Rename removeBook → requestRemoveBook and bulkRemove →
   requestBulkRemove in template + JS renderer so the dialog opens
   instead of navigating or failing silently.
This commit is contained in:
2026-08-06 10:55:37 -04:00
parent 816ee0ec80
commit ef3c05714a
3 changed files with 98 additions and 51 deletions
+28 -4
View File
@@ -150,7 +150,7 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
/>
</div>
<button
@click="bulkRemove()"
@click="requestBulkRemove()"
:disabled="selectedBooks.length === 0"
:class="selectedBooks.length === 0 ? 'opacity-50 cursor-not-allowed' : ''"
class="btn btn-danger"
@@ -217,7 +217,7 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
</div>
<div class="mt-3 pt-3 border-t" style="border-color: var(--border);">
<button
@click="removeBook('{ book.MediaItemID }')"
@click="requestRemoveBook('{ book.MediaItemID }')"
class="btn btn-secondary w-full"
>
@Icon("trash", "h-4 w-4")
@@ -230,9 +230,11 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
</div>
<div
x-data="bookPicker"
x-show="$store.bookPicker.isOpen"
@keyup.escape.window="$store.bookPicker.close()"
class="fixed inset-0 z-50 flex items-center justify-center"
style="display: none;"
@click.self="$store.bookPicker.close()"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none; background-color: var(--surface-overlay);"
>
<div
@click.stop
@@ -345,6 +347,28 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
</div>
</div>
</div>
<div
x-show="showConfirm"
@click.self="closeConfirm()"
class="fixed inset-0 z-[60] flex items-center justify-center p-4"
style="display: none; background-color: var(--surface-overlay);"
>
<div
@click.stop
class="card p-6 w-full max-w-md mx-4"
style="box-shadow: var(--shadow-pop);"
>
<h3 class="text-lg font-bold mb-2" style="color: var(--text-primary)">Remove from Collection</h3>
<p x-text="confirmMessage" class="text-sm mb-6" style="color: var(--text-secondary)"></p>
<div class="flex justify-end gap-3">
<button @click="closeConfirm()" class="btn btn-secondary">Cancel</button>
<button @click="executeConfirmed()" class="btn btn-danger">
@Icon("trash", "h-4 w-4")
<span x-text="confirmLabel"></span>
</button>
</div>
</div>
</div>
</body>
<div
id="collection-data"