feat(ui): refresh auth, entry, admin, and secondary pages
Apply the new design-system primitives across the remaining pages so the whole app shares one visual language: - Auth/entry: redesigned index, login, register (centered card layout, SVG icons, semantic tokens) - Admin: sidebar nav with icons, cohesive admin dashboard/users/library/ processing-issues/settings (tables use border-line + hover states; scan/websocket attributes preserved) - Secondary: analytics (stat cards), devices, progress, conflicts, queue, profile + form/modal all migrated to .card/.btn/.input primitives and SVG action icons - Docs + API explorer + setup wizard + collection/rules/modals + unlinked books + book-detail modals: consistent chrome, modal scrims use --surface-overlay, close buttons use icon-btn - reader.templ and error.templ intentionally left unchanged
This commit is contained in:
+92
-98
@@ -14,8 +14,8 @@ templ Setup() {
|
||||
<body class="theme-tokyo-night min-h-screen" x-data="setupWizard" x-init="initSetup()">
|
||||
<div class="container mx-auto px-4 py-8 max-w-2xl">
|
||||
<div class="text-center mb-8">
|
||||
<h1 class="text-4xl font-bold mb-2" style="color: var(--text-primary)">Welcome to Bookhoard</h1>
|
||||
<p class="text-lg" style="color: var(--text-secondary)">Let's get your library set up.</p>
|
||||
<h1 class="text-2xl font-bold tracking-tight text-content mb-2">Welcome to Bookhoard</h1>
|
||||
<p class="text-lg text-content-muted">Let's get your library set up.</p>
|
||||
</div>
|
||||
|
||||
<!-- Step indicator -->
|
||||
@@ -39,77 +39,72 @@ templ Setup() {
|
||||
</div>
|
||||
|
||||
<!-- Error display -->
|
||||
<div x-show="errorMsg" class="mb-4 p-4 rounded-lg border border-red-500/50 bg-red-500/10 text-red-400 text-sm">
|
||||
<div x-show="errorMsg" x-cloak class="mb-4 p-4 rounded-lg border border-red-500/50 bg-red-500/10 text-red-400 text-sm">
|
||||
<span x-text="errorMsg"></span>
|
||||
</div>
|
||||
|
||||
<!-- ==================== STEP 1: Create Admin ==================== -->
|
||||
<div x-show="currentStep === 1" class="card p-6 rounded-lg shadow-md border" style="background-color: var(--bg-secondary); border-color: var(--border)">
|
||||
<h2 class="text-2xl font-bold mb-2" style="color: var(--text-primary)">Create Administrator Account</h2>
|
||||
<p class="mb-6" style="color: var(--text-secondary)">This first account will have full admin privileges.</p>
|
||||
<div x-show="currentStep === 1" x-cloak class="card p-6">
|
||||
<h2 class="text-2xl font-bold tracking-tight text-content mb-2">Create Administrator Account</h2>
|
||||
<p class="mb-6 text-content-muted">This first account will have full admin privileges.</p>
|
||||
|
||||
<form @submit.prevent="submitAdmin()">
|
||||
<div class="mb-6 p-4 rounded-lg border" style="background-color: var(--bg-primary); border-color: var(--border)">
|
||||
<label class="block text-sm font-medium mb-1" style="color: var(--text-secondary)">Server URL (Base URL)</label>
|
||||
<div class="mb-6 p-4 rounded-lg border border-line bg-surface">
|
||||
<label class="block text-xs font-semibold uppercase tracking-wide text-content-muted mb-1">Server URL (Base URL)</label>
|
||||
<input
|
||||
type="url"
|
||||
x-model="admin.baseUrl"
|
||||
placeholder="https://books.example.com"
|
||||
class="w-full px-3 py-2 border rounded mt-2"
|
||||
style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border)"
|
||||
class="input w-full mt-2"
|
||||
required
|
||||
/>
|
||||
<p class="text-sm mt-2" style="color: var(--text-secondary)">The public URL of your Bookhoard instance. Used for device sync, OPDS feed, and API endpoints.</p>
|
||||
<p class="text-sm mt-2 text-content-muted">The public URL of your Bookhoard instance. Used for device sync, OPDS feed, and API endpoints.</p>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium mb-1" style="color: var(--text-secondary)">Email</label>
|
||||
<label class="block text-xs font-semibold uppercase tracking-wide text-content-muted mb-1">Email</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
x-model="admin.email"
|
||||
class="w-full px-3 py-2 border rounded"
|
||||
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border)"
|
||||
class="input w-full"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium mb-1" style="color: var(--text-secondary)">Username</label>
|
||||
<label class="block text-xs font-semibold uppercase tracking-wide text-content-muted mb-1">Username</label>
|
||||
<input
|
||||
type="text"
|
||||
x-model="admin.username"
|
||||
id="username"
|
||||
class="w-full px-3 py-2 border rounded"
|
||||
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border)"
|
||||
class="input w-full"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4 mb-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-1" style="color: var(--text-secondary)">First Name</label>
|
||||
<label class="block text-xs font-semibold uppercase tracking-wide text-content-muted mb-1">First Name</label>
|
||||
<input
|
||||
type="text"
|
||||
x-model="admin.firstName"
|
||||
placeholder="Optional"
|
||||
class="w-full px-3 py-2 border rounded"
|
||||
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border)"
|
||||
class="input w-full"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-1" style="color: var(--text-secondary)">Last Name</label>
|
||||
<label class="block text-xs font-semibold uppercase tracking-wide text-content-muted mb-1">Last Name</label>
|
||||
<input
|
||||
type="text"
|
||||
x-model="admin.lastName"
|
||||
placeholder="Optional"
|
||||
class="w-full px-3 py-2 border rounded"
|
||||
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border)"
|
||||
class="input w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="password-requirements" class="mb-4 p-4 rounded-lg border text-sm" style="background-color: var(--bg-primary); border-color: var(--border)">
|
||||
<p class="font-semibold mb-2" style="color: var(--text-primary)">Password Requirements:</p>
|
||||
<ul class="space-y-1" style="color: var(--text-secondary)">
|
||||
<div id="password-requirements" class="mb-4 p-4 rounded-lg border border-line bg-surface text-sm">
|
||||
<p class="font-semibold mb-2 text-content">Password Requirements:</p>
|
||||
<ul class="space-y-1 text-content-muted">
|
||||
<li id="req-length" class="flex items-center gap-2">
|
||||
<span class="requirement-icon">○</span> At least 8 characters
|
||||
</li>
|
||||
@@ -131,31 +126,29 @@ templ Setup() {
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium mb-1" style="color: var(--text-secondary)">Password</label>
|
||||
<label class="block text-xs font-semibold uppercase tracking-wide text-content-muted mb-1">Password</label>
|
||||
<input
|
||||
type="password"
|
||||
x-model="admin.password"
|
||||
id="password"
|
||||
class="w-full px-3 py-2 border rounded"
|
||||
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border)"
|
||||
class="input w-full"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-6">
|
||||
<label class="block text-sm font-medium mb-1" style="color: var(--text-secondary)">Confirm Password</label>
|
||||
<label class="block text-xs font-semibold uppercase tracking-wide text-content-muted mb-1">Confirm Password</label>
|
||||
<input
|
||||
type="password"
|
||||
x-model="admin.confirmPassword"
|
||||
id="confirm-password"
|
||||
class="w-full px-3 py-2 border rounded"
|
||||
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border)"
|
||||
class="input w-full"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
id="register-btn"
|
||||
class="btn-primary w-full py-2 rounded opacity-50 cursor-not-allowed"
|
||||
class="btn btn-primary w-full opacity-50 cursor-not-allowed"
|
||||
:disabled="loading"
|
||||
x-text="loading ? 'Creating...' : 'Create Admin Account'"
|
||||
></button>
|
||||
@@ -163,49 +156,47 @@ templ Setup() {
|
||||
</div>
|
||||
|
||||
<!-- ==================== STEP 2: Create Libraries ==================== -->
|
||||
<div x-show="currentStep === 2" class="card p-6 rounded-lg shadow-md border" style="background-color: var(--bg-secondary); border-color: var(--border)">
|
||||
<h2 class="text-2xl font-bold mb-2" style="color: var(--text-primary)">Create Libraries</h2>
|
||||
<p class="mb-6" style="color: var(--text-secondary)">Add one or more media libraries. You can always add more later.</p>
|
||||
<div x-show="currentStep === 2" x-cloak class="card p-6">
|
||||
<h2 class="text-2xl font-bold tracking-tight text-content mb-2">Create Libraries</h2>
|
||||
<p class="mb-6 text-content-muted">Add one or more media libraries. You can always add more later.</p>
|
||||
|
||||
<!-- Created libraries list -->
|
||||
<div x-show="libraries.length > 0" class="mb-6 space-y-2">
|
||||
<div x-show="libraries.length > 0" x-cloak class="mb-6 space-y-2">
|
||||
<template x-for="(lib, idx) in libraries" :key="lib.id">
|
||||
<div class="p-3 rounded-lg border flex items-center justify-between" style="background-color: var(--bg-primary); border-color: var(--border)">
|
||||
<div class="p-3 rounded-lg border border-line bg-surface flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-xl" x-text="lib.type === 'ebooks' ? '📚' : lib.type === 'comics' ? '📖' : '🗾'"></span>
|
||||
<div>
|
||||
<p class="font-medium" style="color: var(--text-primary)" x-text="lib.name"></p>
|
||||
<p class="text-xs capitalize" style="color: var(--text-secondary)" x-text="lib.type"></p>
|
||||
<p class="font-medium text-content" x-text="lib.name"></p>
|
||||
<p class="text-xs capitalize text-content-muted" x-text="lib.type"></p>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@click="removeLibrary(idx)"
|
||||
class="text-xs text-red-500 hover:underline"
|
||||
class="text-xs text-danger hover:underline"
|
||||
>Remove</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- Add library form -->
|
||||
<form @submit.prevent="addLibrary()" class="space-y-4 p-4 rounded-lg border" style="background-color: var(--bg-primary); border-color: var(--border)">
|
||||
<form @submit.prevent="addLibrary()" class="space-y-4 p-4 rounded-lg border border-line bg-surface">
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-1" style="color: var(--text-secondary)">Library Name</label>
|
||||
<label class="block text-xs font-semibold uppercase tracking-wide text-content-muted mb-1">Library Name</label>
|
||||
<input
|
||||
type="text"
|
||||
x-model="newLibrary.name"
|
||||
placeholder="My Ebook Library"
|
||||
class="w-full px-3 py-2 border rounded"
|
||||
style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border)"
|
||||
class="input w-full"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-1" style="color: var(--text-secondary)">Library Type</label>
|
||||
<label class="block text-xs font-semibold uppercase tracking-wide text-content-muted mb-1">Library Type</label>
|
||||
<select
|
||||
x-model="newLibrary.type"
|
||||
class="w-full px-3 py-2 border rounded"
|
||||
style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border)"
|
||||
class="input w-full"
|
||||
>
|
||||
<option value="ebooks">📚 Ebooks</option>
|
||||
<option value="comics">📖 Comics</option>
|
||||
@@ -213,54 +204,53 @@ templ Setup() {
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-1" style="color: var(--text-secondary)">Description (optional)</label>
|
||||
<label class="block text-xs font-semibold uppercase tracking-wide text-content-muted mb-1">Description (optional)</label>
|
||||
<input
|
||||
type="text"
|
||||
x-model="newLibrary.description"
|
||||
placeholder="Optional"
|
||||
class="w-full px-3 py-2 border rounded"
|
||||
style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border)"
|
||||
class="input w-full"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn-secondary w-full py-2 rounded"
|
||||
class="btn btn-secondary w-full"
|
||||
:disabled="loading || !newLibrary.name.trim()"
|
||||
x-text="loading ? 'Creating...' : '+ Add This Library'"
|
||||
></button>
|
||||
</form>
|
||||
|
||||
<div class="flex justify-between mt-6">
|
||||
<button type="button" @click="currentStep = 1" class="btn-secondary px-4 py-2 rounded">Back</button>
|
||||
<button type="button" @click="currentStep = 3" class="btn-primary px-6 py-2 rounded">
|
||||
<button type="button" @click="currentStep = 1" class="btn btn-secondary">Back</button>
|
||||
<button type="button" @click="currentStep = 3" class="btn btn-primary">
|
||||
<span x-text="libraries.length > 0 ? 'Next: Configure Folders' : 'Skip – Continue'"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== STEP 3: Configure Folders ==================== -->
|
||||
<div x-show="currentStep === 3" class="card p-6 rounded-lg shadow-md border" style="background-color: var(--bg-secondary); border-color: var(--border)">
|
||||
<h2 class="text-2xl font-bold mb-2" style="color: var(--text-primary)">Configure Library Folders</h2>
|
||||
<p class="mb-6" style="color: var(--text-secondary)">Add the filesystem folders where your media files are stored.</p>
|
||||
<div x-show="currentStep === 3" x-cloak class="card p-6">
|
||||
<h2 class="text-2xl font-bold tracking-tight text-content mb-2">Configure Library Folders</h2>
|
||||
<p class="mb-6 text-content-muted">Add the filesystem folders where your media files are stored.</p>
|
||||
|
||||
<div x-show="libraries.length === 0" class="text-center py-8" style="color: var(--text-secondary)">
|
||||
<div x-show="libraries.length === 0" x-cloak class="text-center py-8 text-content-muted">
|
||||
<p>No libraries created. You can add folders later from the admin panel.</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
<template x-for="lib in libraries" :key="lib.id">
|
||||
<div class="p-4 rounded-lg border" style="background-color: var(--bg-primary); border-color: var(--border)">
|
||||
<div class="p-4 rounded-lg border border-line bg-surface">
|
||||
<div class="flex items-center gap-2 mb-3">
|
||||
<span class="text-xl" x-text="lib.type === 'ebooks' ? '📚' : lib.type === 'comics' ? '📖' : '🗾'"></span>
|
||||
<h4 class="font-semibold" style="color: var(--text-primary)" x-text="lib.name"></h4>
|
||||
<h4 class="font-semibold text-content" x-text="lib.name"></h4>
|
||||
</div>
|
||||
|
||||
<!-- Existing folders for this library -->
|
||||
<div class="space-y-1 mb-3" x-show="lib.folders && lib.folders.length > 0">
|
||||
<template x-for="(folder, fIdx) in (lib.folders || [])" :key="folder">
|
||||
<div class="flex items-center justify-between p-2 rounded text-sm" style="background-color: var(--bg-secondary); border-color: var(--border)">
|
||||
<span style="color: var(--text-primary)" x-text="folder"></span>
|
||||
<button type="button" @click="removeFolder(lib.id, folder, fIdx)" class="text-xs text-red-500 hover:underline">Remove</button>
|
||||
<div class="flex items-center justify-between p-2 rounded text-sm border border-line bg-surface-raised">
|
||||
<span class="text-content" x-text="folder"></span>
|
||||
<button type="button" @click="removeFolder(lib.id, folder, fIdx)" class="text-xs text-danger hover:underline">Remove</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@@ -271,18 +261,17 @@ templ Setup() {
|
||||
type="text"
|
||||
:placeholder="'/path/to/' + lib.type"
|
||||
:id="'folderInput-' + lib.id"
|
||||
class="flex-1 px-3 py-2 border rounded text-sm"
|
||||
style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border)"
|
||||
class="input flex-1 text-sm"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
@click="showFolderBrowser('folderInput-' + lib.id)"
|
||||
class="btn-secondary px-3 py-2 text-xs rounded"
|
||||
class="btn btn-secondary text-xs"
|
||||
>Browse</button>
|
||||
<button
|
||||
type="button"
|
||||
@click="addFolderToLibrary(lib)"
|
||||
class="btn-primary px-3 py-2 text-xs rounded"
|
||||
class="btn btn-primary text-xs"
|
||||
>Add</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -290,37 +279,37 @@ templ Setup() {
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between mt-6">
|
||||
<button type="button" @click="currentStep = 2" class="btn-secondary px-4 py-2 rounded">Back</button>
|
||||
<button type="button" @click="currentStep = 4" class="btn-primary px-6 py-2 rounded">Next: Scan</button>
|
||||
<button type="button" @click="currentStep = 2" class="btn btn-secondary">Back</button>
|
||||
<button type="button" @click="currentStep = 4" class="btn btn-primary">Next: Scan</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== STEP 4: Scan & Finish ==================== -->
|
||||
<div x-show="currentStep === 4" class="card p-6 rounded-lg shadow-md border" style="background-color: var(--bg-secondary); border-color: var(--border)">
|
||||
<h2 class="text-2xl font-bold mb-2" style="color: var(--text-primary)">Scan & Finish</h2>
|
||||
<p class="mb-6" style="color: var(--text-secondary)">Review your configuration and start the initial scan.</p>
|
||||
<div x-show="currentStep === 4" x-cloak class="card p-6">
|
||||
<h2 class="text-2xl font-bold tracking-tight text-content mb-2">Scan & Finish</h2>
|
||||
<p class="mb-6 text-content-muted">Review your configuration and start the initial scan.</p>
|
||||
|
||||
<!-- Summary -->
|
||||
<div class="space-y-3 mb-6">
|
||||
<div class="p-4 rounded-lg border" style="background-color: var(--bg-primary); border-color: var(--border)">
|
||||
<p class="text-sm font-medium mb-1" style="color: var(--text-secondary)">Server URL</p>
|
||||
<p style="color: var(--text-primary)" x-text="admin.baseUrl"></p>
|
||||
<div class="p-4 rounded-lg border border-line bg-surface">
|
||||
<p class="text-sm font-medium mb-1 text-content-muted">Server URL</p>
|
||||
<p class="text-content" x-text="admin.baseUrl"></p>
|
||||
</div>
|
||||
<div class="p-4 rounded-lg border" style="background-color: var(--bg-primary); border-color: var(--border)">
|
||||
<p class="text-sm font-medium mb-1" style="color: var(--text-secondary)">Administrator</p>
|
||||
<p style="color: var(--text-primary)" x-text="admin.username + ' (' + admin.email + ')'"></p>
|
||||
<div class="p-4 rounded-lg border border-line bg-surface">
|
||||
<p class="text-sm font-medium mb-1 text-content-muted">Administrator</p>
|
||||
<p class="text-content" x-text="admin.username + ' (' + admin.email + ')'"></p>
|
||||
</div>
|
||||
<div class="p-4 rounded-lg border" style="background-color: var(--bg-primary); border-color: var(--border)">
|
||||
<p class="text-sm font-medium mb-2" style="color: var(--text-secondary)">
|
||||
<div class="p-4 rounded-lg border border-line bg-surface">
|
||||
<p class="text-sm font-medium mb-2 text-content-muted">
|
||||
Libraries (<span x-text="libraries.length"></span>)
|
||||
</p>
|
||||
<template x-for="lib in libraries" :key="lib.id">
|
||||
<div class="flex items-start justify-between text-sm py-1">
|
||||
<div>
|
||||
<span style="color: var(--text-primary)" x-text="lib.name"></span>
|
||||
<span class="ml-2 text-xs px-2 py-0.5 rounded" style="background-color: var(--accent); color: var(--bg-primary)" x-text="lib.type"></span>
|
||||
<span class="text-content" x-text="lib.name"></span>
|
||||
<span class="ml-2 text-xs px-2 py-0.5 rounded bg-brand text-surface" x-text="lib.type"></span>
|
||||
</div>
|
||||
<div class="text-right" style="color: var(--text-secondary)">
|
||||
<div class="text-right text-content-muted">
|
||||
<span x-text="(lib.folders || []).length + ' folder(s)'"></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -329,16 +318,16 @@ templ Setup() {
|
||||
</div>
|
||||
|
||||
<!-- Scan progress -->
|
||||
<div x-show="scanStarted" class="mb-6 space-y-3">
|
||||
<h3 class="font-semibold" style="color: var(--text-primary)">Scan Progress</h3>
|
||||
<div x-show="scanStarted" x-cloak class="mb-6 space-y-3">
|
||||
<h3 class="font-semibold text-content">Scan Progress</h3>
|
||||
<div id="library-progress-list" class="space-y-3">
|
||||
<template x-for="job in scanJobs" :key="job.jobId">
|
||||
<div class="p-3 rounded border" style="background-color: var(--bg-primary); border-color: var(--border)">
|
||||
<div class="p-3 rounded border border-line bg-surface">
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<span class="font-medium" style="color: var(--text-primary)" x-text="job.libraryName"></span>
|
||||
<span class="text-sm" style="color: var(--text-secondary)" x-text="job.statusText"></span>
|
||||
<span class="font-medium text-content" x-text="job.libraryName"></span>
|
||||
<span class="text-sm text-content-muted" x-text="job.statusText"></span>
|
||||
</div>
|
||||
<div class="w-full rounded-full h-2" style="background-color: var(--bg-secondary)">
|
||||
<div class="w-full rounded-full h-2 bg-surface-raised">
|
||||
<div
|
||||
class="h-2 rounded-full transition-all duration-500"
|
||||
:style="'width: ' + job.progress + '%; background-color: var(--accent);'"
|
||||
@@ -347,36 +336,39 @@ templ Setup() {
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div x-show="scanComplete" class="p-4 rounded-lg border border-green-500/50 bg-green-500/10 text-green-400 text-sm">
|
||||
<div x-show="scanComplete" x-cloak class="p-4 rounded-lg border border-green-500/50 bg-green-500/10 text-green-400 text-sm">
|
||||
Initial scan complete! Your libraries are ready to use.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between mt-6">
|
||||
<button type="button" @click="currentStep = 3" class="btn-secondary px-4 py-2 rounded" :disabled="loading">Back</button>
|
||||
<button type="button" @click="currentStep = 3" class="btn btn-secondary" :disabled="loading">Back</button>
|
||||
|
||||
<div class="flex gap-3">
|
||||
<button
|
||||
x-show="!scanStarted"
|
||||
x-cloak
|
||||
type="button"
|
||||
@click="startScan()"
|
||||
class="btn-primary px-6 py-2 rounded"
|
||||
class="btn btn-primary"
|
||||
:disabled="loading"
|
||||
>Start Scan</button>
|
||||
|
||||
<button
|
||||
x-show="scanStarted && !scanComplete"
|
||||
x-cloak
|
||||
type="button"
|
||||
@click="finishSetup()"
|
||||
class="btn-secondary px-6 py-2 rounded"
|
||||
class="btn btn-secondary"
|
||||
:disabled="loading"
|
||||
>Skip to Dashboard</button>
|
||||
|
||||
<button
|
||||
x-show="scanComplete"
|
||||
x-cloak
|
||||
type="button"
|
||||
@click="finishSetup()"
|
||||
class="btn-primary px-6 py-2 rounded"
|
||||
class="btn btn-primary"
|
||||
:disabled="loading"
|
||||
x-text="loading ? 'Finishing...' : 'Go to Dashboard'"
|
||||
></button>
|
||||
@@ -386,11 +378,13 @@ templ Setup() {
|
||||
</div>
|
||||
|
||||
<!-- Folder Browser Modal (reused from admin library) -->
|
||||
<div id="folder-browser-modal" class="hidden fixed inset-0 z-50 flex items-center justify-center" style="background-color: rgba(0, 0, 0, 0.7)">
|
||||
<div class="card rounded-lg p-6 w-full max-w-md mx-4" style="background-color: var(--bg-secondary); border-color: var(--border)">
|
||||
<div id="folder-browser-modal" class="hidden fixed inset-0 z-50 flex items-center justify-center" style="background-color: var(--surface-overlay);">
|
||||
<div class="card p-6 w-full max-w-md mx-4">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-xl font-bold" style="color: var(--text-primary)">Browse Folders</h2>
|
||||
<button type="button" @click="hideFolderBrowser()" class="p-2 hover:opacity-80 rounded" style="color: var(--text-primary)">✕</button>
|
||||
<h2 class="text-xl font-bold text-content">Browse Folders</h2>
|
||||
<button type="button" @click="hideFolderBrowser()" class="icon-btn">
|
||||
@Icon("close", "h-5 w-5")
|
||||
</button>
|
||||
</div>
|
||||
<div id="folder-browser-content">
|
||||
<!-- Directory listings rendered by Alpine -->
|
||||
|
||||
Reference in New Issue
Block a user