refactor(web): Modal component; admin + discover modals migrated (W2)

This commit is contained in:
2026-05-08 05:37:58 -04:00
parent 92813ba1bb
commit 970752a153
7 changed files with 543 additions and 512 deletions
+76 -103
View File
@@ -11,6 +11,7 @@
import { qk } from '$lib/api/queries';
import { errMessage } from '$lib/api/errors';
import { playRadio } from '$lib/player/store.svelte';
import Modal from '$lib/components/Modal.svelte';
import type { AdminQuarantineRow, LidarrQuarantineReason } from '$lib/api/types';
// Aggregated triage queue. One row per track, with per-row resolution
@@ -328,113 +329,85 @@
{/if}
</div>
{#if deleteFileRow}
<!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
class="fixed inset-0 z-50 flex items-center justify-center"
style="background: rgba(0,0,0,0.5);"
onclick={cancelDeleteFile}
>
<div
role="dialog"
aria-modal="true"
aria-labelledby="delete-file-title"
class="w-full max-w-md rounded-xl border border-border bg-surface p-5 shadow-lg"
onclick={(e) => e.stopPropagation()}
tabindex="-1"
>
<h3 id="delete-file-title" class="font-display text-lg font-medium text-text-primary">
Delete file?
</h3>
<p class="mt-2 text-sm text-text-secondary">
Remove <em class="font-medium text-text-primary">{deleteFileRow.track_title}</em>
from disk and clear {deleteFileRow.report_count} reports? Lidarr may auto-redownload depending on its monitor settings.
</p>
<div class="mt-5 flex justify-end gap-2">
<button
type="button"
class="rounded-md border border-border px-3 py-1.5 text-sm text-text-secondary hover:text-text-primary"
onclick={cancelDeleteFile}
>
Cancel
</button>
<button
type="button"
aria-label="Confirm delete file"
class="inline-flex items-center gap-1 rounded-md bg-action-secondary px-3 py-1.5 text-sm text-action-fg"
onclick={() => confirmDeleteFile(deleteFileRow!)}
>
<Trash2 size={14} strokeWidth={2} />
Delete file
</button>
</div>
<Modal
title="Delete file?"
open={deleteFileRow !== null}
onClose={cancelDeleteFile}
>
{#if deleteFileRow}
<p class="-mt-2 text-sm text-text-secondary">
Remove <em class="font-medium text-text-primary">{deleteFileRow.track_title}</em>
from disk and clear {deleteFileRow.report_count} reports? Lidarr may auto-redownload depending on its monitor settings.
</p>
<div class="mt-5 flex justify-end gap-2">
<button
type="button"
class="rounded-md border border-border px-3 py-1.5 text-sm text-text-secondary hover:text-text-primary"
onclick={cancelDeleteFile}
>
Cancel
</button>
<button
type="button"
aria-label="Confirm delete file"
class="inline-flex items-center gap-1 rounded-md bg-action-secondary px-3 py-1.5 text-sm text-action-fg"
onclick={() => confirmDeleteFile(deleteFileRow!)}
>
<Trash2 size={14} strokeWidth={2} />
Delete file
</button>
</div>
</div>
{/if}
{/if}
</Modal>
{#if deleteLidarrRow}
<!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
class="fixed inset-0 z-50 flex items-center justify-center"
style="background: rgba(0,0,0,0.5);"
onclick={cancelDeleteLidarr}
>
<div
role="dialog"
aria-modal="true"
aria-labelledby="delete-lidarr-title"
class="w-full max-w-md rounded-xl border border-border bg-surface p-5 shadow-lg"
onclick={(e) => e.stopPropagation()}
tabindex="-1"
>
<h3 id="delete-lidarr-title" class="font-display text-lg font-medium text-text-primary">
Delete via Lidarr?
</h3>
<p class="mt-2 text-sm text-text-secondary">
This will tell Lidarr to remove <em class="font-medium text-text-primary">{deleteLidarrRow.album_title}</em>
(artist <em class="font-medium text-text-primary">{deleteLidarrRow.artist_name}</em>)
and add it to the import-list exclusion. Affects all tracks on the album. Type <strong>DELETE</strong> to confirm.
<Modal
title="Delete via Lidarr?"
open={deleteLidarrRow !== null}
onClose={cancelDeleteLidarr}
>
{#if deleteLidarrRow}
<p class="-mt-2 text-sm text-text-secondary">
This will tell Lidarr to remove <em class="font-medium text-text-primary">{deleteLidarrRow.album_title}</em>
(artist <em class="font-medium text-text-primary">{deleteLidarrRow.artist_name}</em>)
and add it to the import-list exclusion. Affects all tracks on the album. Type <strong>DELETE</strong> to confirm.
</p>
<label class="mt-3 block">
<span class="block text-sm text-text-secondary">Type DELETE to confirm</span>
<input
type="text"
bind:value={deleteLidarrInput}
placeholder="DELETE"
class="mt-1 w-full rounded-md border border-border bg-background px-3 py-2 font-mono text-sm text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-2 focus:ring-accent"
aria-label="Type DELETE to confirm"
/>
</label>
{#if deleteLidarrError}
<p class="mt-3 text-sm text-error" data-testid="delete-lidarr-error">
{deleteLidarrError}
</p>
<label class="mt-3 block">
<span class="block text-sm text-text-secondary">Type DELETE to confirm</span>
<input
type="text"
bind:value={deleteLidarrInput}
placeholder="DELETE"
class="mt-1 w-full rounded-md border border-border bg-background px-3 py-2 font-mono text-sm text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-2 focus:ring-accent"
aria-label="Type DELETE to confirm"
/>
</label>
{#if deleteLidarrError}
<p class="mt-3 text-sm text-error" data-testid="delete-lidarr-error">
{deleteLidarrError}
</p>
{/if}
<div class="mt-5 flex justify-end gap-2">
<button
type="button"
class="rounded-md border border-border px-3 py-1.5 text-sm text-text-secondary hover:text-text-primary"
onclick={cancelDeleteLidarr}
>
Cancel
</button>
<button
type="button"
aria-label="Confirm delete via Lidarr"
disabled={deleteLidarrInput.trim() !== 'DELETE'}
class="inline-flex items-center gap-1 rounded-md bg-action-destructive px-3 py-1.5 text-sm text-action-fg disabled:cursor-not-allowed disabled:opacity-50"
onclick={() => confirmDeleteLidarr(deleteLidarrRow!)}
>
<Trash2 size={14} strokeWidth={2} />
<Cloud size={14} strokeWidth={2} />
Delete via Lidarr
</button>
</div>
{/if}
<div class="mt-5 flex justify-end gap-2">
<button
type="button"
class="rounded-md border border-border px-3 py-1.5 text-sm text-text-secondary hover:text-text-primary"
onclick={cancelDeleteLidarr}
>
Cancel
</button>
<button
type="button"
aria-label="Confirm delete via Lidarr"
disabled={deleteLidarrInput.trim() !== 'DELETE'}
class="inline-flex items-center gap-1 rounded-md bg-action-destructive px-3 py-1.5 text-sm text-action-fg disabled:cursor-not-allowed disabled:opacity-50"
onclick={() => confirmDeleteLidarr(deleteLidarrRow!)}
>
<Trash2 size={14} strokeWidth={2} />
<Cloud size={14} strokeWidth={2} />
Delete via Lidarr
</button>
</div>
</div>
{/if}
{/if}
</Modal>
{#if toast}
<div