228 lines
9.2 KiB
HTML
Executable File
228 lines
9.2 KiB
HTML
Executable File
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||
<meta name="theme-color" content="#1e222d">
|
||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||
<title>What To Cook? – Essens-Zufallsgenerator</title>
|
||
<link rel="manifest" href="/static/manifest.json">
|
||
<link rel="apple-touch-icon" href="/static/icon-192.png">
|
||
<link rel="stylesheet" href="/static/style.css">
|
||
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🍽️</text></svg>">
|
||
</head>
|
||
<body>
|
||
<div class="app-container">
|
||
|
||
<!-- Top Header -->
|
||
<header class="app-header">
|
||
<div class="brand">
|
||
<span class="brand-icon">🍽️</span>
|
||
<div>
|
||
<h1 class="brand-title">What To Cook?</h1>
|
||
<p class="brand-subtitle">Zufallsgenerator für Essen</p>
|
||
</div>
|
||
</div>
|
||
<!-- Tab Navigation -->
|
||
<nav class="nav-tabs" role="tablist">
|
||
<button id="tab-btn-generator" class="nav-tab active" data-tab="generator" role="tab" aria-selected="true">
|
||
<span class="icon">🎲</span> Generator
|
||
</button>
|
||
<a href="/cookbook" class="nav-tab" style="text-decoration: none;">
|
||
<span class="icon">📖</span> Kochbuch
|
||
</a>
|
||
<a href="/cookbook/new" class="nav-tab" style="text-decoration: none;">
|
||
<span class="icon">➕</span> Rezept
|
||
</a>
|
||
<button id="tab-btn-admin" class="nav-tab" data-tab="admin" role="tab" aria-selected="false">
|
||
<span class="icon">⚙️</span> Gerichte
|
||
</button>
|
||
</nav>
|
||
</header>
|
||
|
||
<!-- Main Content Area -->
|
||
<main class="app-main">
|
||
|
||
<!-- ========================================== -->
|
||
<!-- TAB 1: GENERATOR -->
|
||
<!-- ========================================== -->
|
||
<section id="tab-generator" class="tab-panel active" role="tabpanel">
|
||
|
||
<!-- Banner / Hint -->
|
||
<div class="info-card">
|
||
<div class="info-content">
|
||
<span class="info-icon">💡</span>
|
||
<div>
|
||
<strong>Bis zu 5 Gerichte konfigurieren:</strong>
|
||
Wähle Kategorie & Aufwand pro Gericht. Nicht benötigte Gerichte einfach frei lassen.
|
||
</div>
|
||
</div>
|
||
<div class="active-counter-badge" id="active-slots-counter">
|
||
<span id="active-slots-count">2</span> von 5 aktiv
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 5 Dish Configuration Slots -->
|
||
<div class="slots-container" id="slots-container">
|
||
<!-- Rendered dynamically by app.js (1 to 5) -->
|
||
</div>
|
||
|
||
<!-- Floating / Sticky Action Bar -->
|
||
<div class="action-bar-wrapper">
|
||
<button id="btn-roll-all" class="btn btn-primary btn-hero">
|
||
<span class="btn-icon">🎲</span>
|
||
<span class="btn-text">Zufallsgenerator starten</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Results Section (Anchor / Modal or Inline display) -->
|
||
<section id="results-section" class="results-section hidden">
|
||
<div class="results-header">
|
||
<div class="results-title-group">
|
||
<h2 class="results-title">Ausgeloste Gerichte</h2>
|
||
<span class="results-badge" id="results-count-badge">0 Gerichte</span>
|
||
</div>
|
||
<button id="btn-reroll-all" class="btn btn-outline btn-sm">
|
||
<span class="icon">🔄</span> Alle neu würfeln
|
||
</button>
|
||
</div>
|
||
|
||
<div id="results-list" class="results-grid">
|
||
<!-- Dynamic Result Cards -->
|
||
</div>
|
||
|
||
<div class="results-footer">
|
||
<button id="btn-back-to-config" class="btn btn-secondary">
|
||
✏️ Filter anpassen
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
</section>
|
||
|
||
<!-- ========================================== -->
|
||
<!-- TAB 2: ADMIN / DATABASE -->
|
||
<!-- ========================================== -->
|
||
<section id="tab-admin" class="tab-panel" role="tabpanel" hidden>
|
||
|
||
<div class="admin-topbar">
|
||
<div>
|
||
<h2 class="section-title">Gerichte verwalten</h2>
|
||
<p class="section-desc" id="admin-stats-summary">Lade Datenbank...</p>
|
||
</div>
|
||
<button id="btn-open-add-dish" class="btn btn-primary">
|
||
<span>➕</span> Neues Gericht
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Admin Filters -->
|
||
<div class="admin-filters-card">
|
||
<div class="search-input-wrap">
|
||
<span class="search-icon">🔍</span>
|
||
<input type="text" id="admin-search-input" placeholder="Gericht nach Namen suchen..." autocomplete="off">
|
||
<button id="admin-search-clear" class="btn-clear hidden" title="Suche leeren">✕</button>
|
||
</div>
|
||
<div class="filter-row">
|
||
<div class="form-group flex-1">
|
||
<label for="admin-filter-category" class="filter-label">Kategorie:</label>
|
||
<select id="admin-filter-category" class="custom-select">
|
||
<option value="alle">Alle Kategorien</option>
|
||
<!-- Filled via JS -->
|
||
</select>
|
||
</div>
|
||
<div class="form-group flex-1">
|
||
<label for="admin-filter-effort" class="filter-label">Aufwand:</label>
|
||
<select id="admin-filter-effort" class="custom-select">
|
||
<option value="alle">Jeder Aufwand</option>
|
||
<option value="gering">Gering 🟢</option>
|
||
<option value="mittel">Mittel 🟡</option>
|
||
<option value="hoch">Hoch 🔴</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Dishes Table / Cards for Mobile -->
|
||
<div class="dishes-list-wrap">
|
||
<div class="dishes-list-header">
|
||
<span id="dishes-count-label">Gerichte</span>
|
||
</div>
|
||
<div id="admin-dishes-list" class="admin-dishes-list">
|
||
<div class="loading-spinner">Lade Gerichte...</div>
|
||
</div>
|
||
</div>
|
||
|
||
</section>
|
||
|
||
</main>
|
||
|
||
<!-- Dialog: Add / Edit Dish -->
|
||
<dialog id="dish-modal" class="modal">
|
||
<div class="modal-box">
|
||
<div class="modal-header">
|
||
<h3 id="modal-title" class="modal-title">Neues Gericht anlegen</h3>
|
||
<button id="btn-close-modal" class="btn-icon-close" aria-label="Schließen">✕</button>
|
||
</div>
|
||
<form id="dish-form" method="dialog">
|
||
<input type="hidden" id="dish-form-id" value="">
|
||
|
||
<div class="form-group">
|
||
<label for="dish-name-input" class="form-label">Name des Gerichts *</label>
|
||
<input type="text" id="dish-name-input" class="text-input" placeholder="z. B. Spaghetti Carbonara" required autocomplete="off">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">Kategorien * <span class="form-label-hint">(Mehrfachauswahl möglich)</span></label>
|
||
<div class="category-checkbox-group" id="modal-category-group">
|
||
<!-- Filled via JS as checkbox pills -->
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">Arbeitsaufwand *</label>
|
||
<div class="effort-radio-group">
|
||
<label class="effort-radio-label">
|
||
<input type="radio" name="modal-effort" value="gering" required>
|
||
<span class="effort-pill effort-gering">Gering 🟢 (≤ 20 Min)</span>
|
||
</label>
|
||
<label class="effort-radio-label">
|
||
<input type="radio" name="modal-effort" value="mittel" checked required>
|
||
<span class="effort-pill effort-mittel">Mittel 🟡 (~ 45 Min)</span>
|
||
</label>
|
||
<label class="effort-radio-label">
|
||
<input type="radio" name="modal-effort" value="hoch" required>
|
||
<span class="effort-pill effort-hoch">Hoch 🔴 (> 60 Min)</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-actions">
|
||
<button type="button" id="btn-cancel-modal" class="btn btn-secondary">Abbrechen</button>
|
||
<button type="submit" id="btn-save-modal" class="btn btn-primary">Speichern</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</dialog>
|
||
|
||
<!-- Dialog: Delete Confirm -->
|
||
<dialog id="delete-modal" class="modal">
|
||
<div class="modal-box modal-box-sm">
|
||
<h3 class="modal-title">Gericht löschen?</h3>
|
||
<p id="delete-modal-text" class="modal-text">Möchtest du dieses Gericht wirklich aus der Datenbank entfernen?</p>
|
||
<div class="modal-actions">
|
||
<button id="btn-cancel-delete" class="btn btn-secondary">Abbrechen</button>
|
||
<button id="btn-confirm-delete" class="btn btn-danger">Unwiderruflich löschen</button>
|
||
</div>
|
||
</div>
|
||
</dialog>
|
||
|
||
<!-- Toast Notifications -->
|
||
<div id="toast-container" class="toast-container" aria-live="polite"></div>
|
||
|
||
</div>
|
||
|
||
<script src="/static/app.js"></script>
|
||
</body>
|
||
</html>
|