Files
watchlist/quivio/static/index.html
T
ki 9a4909f083
CI / test (push) Has been cancelled
chore(rebrand): rename WatchStack -> Quivio
Quivio (Kofferwort aus Quire + Video) ersetzt den Arbeitstitel WatchStack.
Es ist origineller, frei auf PyPI/npm, und passt perfekt zur Doppelnatur
der App: Buecher (Quire) + Serien (Video).

Geaendert:
- Python-Paket app/ -> quivio/ (+ alle Imports angepasst)
- DB-File watchstack.db -> quivio.db
- Docker-Image: quivio:0.5.1-beta, Container-Name quivio
- Compose-Services: quivio, quivio-local
- ENV-Vars: QUIVIO_VERSION, QUIVIO_PORT, Volume quivio-data
- Frontend-Logo "W" -> "Q", Titel "Quivio", Footer
- Favicon "Q" (Georgia serif fuer klassischen Look)
- Logger-Name: watchstack -> quivio
- README, NOTICE, dist/README, data/README: Quivio
- CI-Workflow: testet quivio/ Pfade
- build-and-push.sh: lokaler Tag "quivio:VERSION"
- service-Feld in /api/health: quivio
- OpenAPI title: Quivio

Bugfix (gefunden beim Renaming):
- seed.py hatte versteckten "from app.database import DB_PATH" — gefixt

Verifiziert end-to-end:
- Python-Import OK
- Backend: service=quivio, version=0.5.1-beta, 8 unique items
- Docker-Build OK, Push in Gitea-Registry OK (neuer sha256-Digest)
- Container: Quivio 0.5.1-beta ready (logger), HTML ohne WatchStack-Rest
- OpenAPI title=Quivio
- 8 unique items nach cold start (Race-Fix haelt)
2026-07-22 00:42:09 +02:00

236 lines
9.3 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Quivio Watchlist für Bücher & Serien</title>
<link rel="icon" type="image/svg+xml" href="/static/img/favicon.svg">
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<!-- ===================== Header / Hero ===================== -->
<header class="hero">
<div class="hero-bg"></div>
<div class="hero-inner">
<div class="brand">
<div class="logo">Q</div>
<div class="brand-text">
<h1>Quivio <span class="version-badge">beta</span></h1>
<p>Deine Watchlist für <strong>Bücher</strong>, <strong>Serien</strong> & mehr.</p>
</div>
</div>
<div class="hero-search">
<input id="search-input" type="search" placeholder="Titel, Autor oder Genre suchen…" autocomplete="off">
<select id="filter-kind">
<option value="">Alle Medien</option>
<option value="book">Nur Bücher</option>
<option value="series">Nur Serien</option>
</select>
<select id="filter-status">
<option value="">Alle Status</option>
<option value="plan">Geplant</option>
<option value="reading">Laufend</option>
<option value="done">Abgeschlossen</option>
<option value="hold">Pausiert</option>
<option value="dropped">Abgebrochen</option>
</select>
<select id="filter-sort">
<option value="updated_desc">Zuletzt geändert</option>
<option value="title_asc">Titel AZ</option>
<option value="title_desc">Titel ZA</option>
<option value="rating_desc">Beste Bewertung</option>
<option value="rating_asc">Schlechteste Bewertung</option>
<option value="year_desc">Neueste zuerst</option>
<option value="year_asc">Älteste zuerst</option>
</select>
<button id="open-stats" class="btn btn-ghost" title="Statistik anzeigen">📊</button>
<button id="open-add" class="btn btn-primary">+ Neu</button>
</div>
</div>
<!-- Status-Tabs (MAL-Style) -->
<nav class="status-tabs" id="status-tabs">
<button class="tab active" data-status="">Alle</button>
<button class="tab" data-status="plan">Geplant <span class="count" id="cnt-plan">0</span></button>
<button class="tab" data-status="reading">Laufend <span class="count" id="cnt-reading">0</span></button>
<button class="tab" data-status="done">Abgeschlossen <span class="count" id="cnt-done">0</span></button>
<button class="tab" data-status="hold">Pausiert <span class="count" id="cnt-hold">0</span></button>
<button class="tab" data-status="dropped">Abgebrochen <span class="count" id="cnt-dropped">0</span></button>
</nav>
</header>
<!-- ===================== Main ===================== -->
<main class="container">
<!-- Genre/Tag-Chips (Filter) -->
<div class="chips" id="genre-chips" aria-label="Genres">
<span class="chip-label">Genres:</span>
<!-- per JS befüllt -->
</div>
<div class="chips" id="tag-chips" aria-label="Tags">
<span class="chip-label">Tags:</span>
<!-- per JS befüllt -->
</div>
<!-- Listen-Grid -->
<section id="grid" class="grid">
<div class="grid-loading">
<div class="spinner"></div>
<span>Lade Watchlist…</span>
</div>
</section>
<div id="empty-state" class="empty hidden">
<h2>Noch nichts hier.</h2>
<p>Klick auf <strong>+ Neu</strong> und leg deinen ersten Eintrag an.</p>
</div>
</main>
<!-- ===================== Modal: Add / Edit ===================== -->
<div class="modal" id="modal-add" hidden>
<div class="modal-backdrop" data-close></div>
<div class="modal-card">
<header class="modal-header">
<h2 id="modal-title">Neuer Eintrag</h2>
<button class="icon-btn" data-close aria-label="Schließen"></button>
</header>
<form id="form-add" class="form">
<input type="hidden" name="id">
<div class="row">
<label class="field grow">
<span>Art</span>
<select name="kind" required>
<option value="book">📚 Buch</option>
<option value="series">📺 Serie</option>
</select>
</label>
<label class="field">
<span>Status</span>
<select name="status">
<option value="plan">Geplant</option>
<option value="reading">Laufend</option>
<option value="done">Abgeschlossen</option>
<option value="hold">Pausiert</option>
<option value="dropped">Abgebrochen</option>
</select>
</label>
</div>
<div class="row">
<label class="field grow">
<span>Titel*</span>
<input name="title" required maxlength="200">
<button type="button" id="btn-lookup" class="btn btn-ghost small" title="Online nachschlagen">🔍 Nachschlagen</button>
</label>
<label class="field">
<span>Jahr</span>
<input name="release_year" type="number" min="1800" max="2200">
</label>
</div>
<!-- Buch-Felder -->
<div class="row" data-when="book">
<label class="field grow">
<span>Autor</span>
<input name="author" maxlength="200">
</label>
<label class="field">
<span>ISBN</span>
<input name="isbn" maxlength="20" placeholder="z.B. 9783608938284">
</label>
</div>
<div class="row" data-when="book">
<label class="field"><span>Bände</span><input name="total_volumes" type="number" min="0"></label>
<label class="field"><span>Kapitel</span><input name="total_chapters" type="number" min="0"></label>
<label class="field"><span>Seiten</span><input name="total_pages" type="number" min="0"></label>
</div>
<!-- Serien-Felder -->
<div class="row" data-when="series">
<label class="field grow">
<span>Sender / Streaming</span>
<input name="network" maxlength="120" placeholder="z.B. Netflix, ARD, …">
</label>
<label class="field"><span>Staffeln</span><input name="total_seasons" type="number" min="0"></label>
<label class="field"><span>Episoden</span><input name="total_episodes" type="number" min="0"></label>
</div>
<div class="row" data-when="series">
<label class="field"><span>Start</span><input name="start_date" type="date"></label>
<label class="field"><span>Ende</span><input name="end_date" type="date"></label>
<label class="field"><span>Staffel aktuell</span><input name="season_watching" type="number" min="0"></label>
</div>
<div class="row">
<label class="field grow">
<span>Cover-URL</span>
<input name="cover_url" placeholder="https://… (oder per Nachschlagen automatisch)">
</label>
<label class="field">
<span>Bewertung (010)</span>
<input name="rating" type="number" step="0.1" min="0" max="10">
</label>
</div>
<label class="field">
<span>Beschreibung</span>
<textarea name="description" rows="3"></textarea>
</label>
<div class="row">
<label class="field grow">
<span>Genres (Komma-getrennt)</span>
<input name="genres" placeholder="Fantasy, Sci-Fi, Roman">
</label>
<label class="field grow">
<span>Tags (Komma-getrennt)</span>
<input name="tags" placeholder="long-runner, klassiker">
</label>
</div>
<label class="field">
<span>Notizen</span>
<textarea name="notes" rows="2"></textarea>
</label>
<footer class="modal-footer">
<button type="button" class="btn btn-ghost" data-close>Abbrechen</button>
<button type="submit" class="btn btn-primary">Speichern</button>
</footer>
</form>
</div>
</div>
<!-- ===================== Drawer: Detail ===================== -->
<aside class="drawer" id="drawer" hidden>
<div class="drawer-backdrop" data-close-drawer></div>
<div class="drawer-card">
<button class="icon-btn drawer-close" data-close-drawer aria-label="Schließen"></button>
<div id="drawer-content"><!-- per JS --></div>
</div>
</aside>
<!-- ===================== Modal: Stats ===================== -->
<div class="modal" id="modal-stats" hidden>
<div class="modal-backdrop" data-close-stats></div>
<div class="modal-card stats-card">
<header class="modal-header">
<h2>Deine Statistik</h2>
<button class="icon-btn" data-close-stats aria-label="Schließen"></button>
</header>
<div id="stats-body"><!-- per JS --></div>
</div>
</div>
<footer class="footer">
<span>Quivio <span id="version"></span> · Apache 2.0</span>
<span>Quire + Video — made for readers &amp; binge-watchers</span>
</footer>
<!-- ===================== Toast ===================== -->
<div id="toast" class="toast" hidden></div>
<script src="/static/js/app.js" defer></script>
</body>
</html>