All checks were successful
release-tag / release-image (push) Successful in 2m6s
206 lines
14 KiB
HTML
206 lines
14 KiB
HTML
<!doctype html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
||
<meta name="color-scheme" content="dark">
|
||
<meta name="theme-color" content="#0e0f11">
|
||
<title>Pocketwatch</title>
|
||
<link rel="stylesheet" href="/static/app.css">
|
||
</head>
|
||
<body class="mobile-compact">
|
||
<div class="app-shell">
|
||
<header class="topbar">
|
||
<div class="brand"><span class="brand-dot"></span><span>pocketwatch</span></div>
|
||
<div class="topbar-actions">
|
||
<div id="week-badge" class="metric-inline"><strong id="header-week">0:00</strong><span>Diese Woche</span></div>
|
||
<button class="icon-btn" id="export-open" title="Exportieren" aria-label="Exportieren">⇩</button>
|
||
<button class="icon-btn" id="settings-open" title="Einstellungen" aria-label="Einstellungen">⚙</button>
|
||
<button class="avatar-btn" id="account-menu" title="Abmelden"><span id="avatar-text">U</span></button>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="main-grid">
|
||
<aside class="tracker-pane">
|
||
<div class="mobile-pane-head"><h1>Erfassen</h1><button class="link-btn" id="mobile-history">Verlauf →</button></div>
|
||
<section class="tracker-card">
|
||
<div class="tracker-date"><span id="today-label">Heute</span><span id="running-hint" class="status-pill" hidden>läuft</span></div>
|
||
<label class="field-label">Kunde
|
||
<input id="client-input" list="client-list" maxlength="200" placeholder="Kunde / Projekt">
|
||
<datalist id="client-list"></datalist>
|
||
</label>
|
||
<label class="field-label activity-field">Tätigkeit
|
||
<textarea id="activity-input" rows="4" maxlength="4000" placeholder="Woran arbeitest du?"></textarea>
|
||
</label>
|
||
<div class="timer-display" id="timer-display">00:00:00</div>
|
||
<button id="timer-button" class="btn primary timer-btn">▶ Start</button>
|
||
<button id="edit-running" class="link-btn centered" hidden>Laufenden Eintrag bearbeiten</button>
|
||
</section>
|
||
|
||
<div class="metric-grid">
|
||
<article class="metric-card"><span>Heute</span><strong id="today-total">0:00</strong></article>
|
||
<article class="metric-card"><span>Diese Woche</span><strong id="week-total">0:00</strong></article>
|
||
</div>
|
||
<div id="long-running-warning" class="warning-box" hidden>Der Timer läuft seit mehr als 8 Stunden. Vielleicht vergessen zu stoppen?</div>
|
||
<footer class="sidebar-footer"><span id="user-label"></span><span>SQLite · Go</span></footer>
|
||
</aside>
|
||
|
||
<section class="history-pane" id="history-pane">
|
||
<div class="history-head">
|
||
<div class="history-title"><button class="link-btn mobile-only" id="mobile-track">← Erfassen</button><p class="eyebrow">ZEITEN</p><h1>Verlauf</h1></div>
|
||
<div class="history-actions">
|
||
<button class="btn subtle" id="add-entry">+ Nachtragen</button>
|
||
<button class="btn subtle" id="history-export">Export</button>
|
||
</div>
|
||
</div>
|
||
<div class="filter-bar">
|
||
<input id="search-input" type="search" placeholder="Kunde oder Tätigkeit suchen…" aria-label="Verlauf durchsuchen">
|
||
<div class="period-tabs" role="group" aria-label="Zeitraum">
|
||
<button data-period="day">Tag</button><button data-period="week">Woche</button><button data-period="month">Monat</button><button data-period="year">Jahr</button><button data-period="all" class="active">Alle</button>
|
||
</div>
|
||
<div class="period-step"><button id="period-prev" aria-label="Vorheriger Zeitraum">‹</button><span id="period-label">Alle Zeiten</span><button id="period-next" aria-label="Nächster Zeitraum">›</button></div>
|
||
</div>
|
||
|
||
<div class="history-scroll">
|
||
<div id="empty-state" class="empty-state" hidden><div class="empty-icon">◷</div><h2>Noch keine Einträge</h2><p>Starte links einen Timer oder trage eine Zeit nach.</p></div>
|
||
<div id="entries" class="entries"></div>
|
||
<button id="load-more" class="btn subtle load-more" hidden>Weitere laden</button>
|
||
</div>
|
||
<footer class="history-footer"><span><strong id="result-count">0</strong> Einträge</span><span>Gesamt <strong id="result-total">0:00</strong></span></footer>
|
||
</section>
|
||
</main>
|
||
|
||
<nav class="mobile-view-nav" aria-label="Mobile Ansicht">
|
||
<button type="button" id="mobile-nav-track" class="mobile-nav-button active" aria-current="page"><span class="mobile-nav-icon">◷</span><span>Timer</span></button>
|
||
<button type="button" id="mobile-nav-history" class="mobile-nav-button"><span class="mobile-nav-icon">☷</span><span>Übersicht</span></button>
|
||
<button type="button" id="mobile-nav-settings" class="mobile-nav-button"><span class="mobile-nav-icon">⚙</span><span>Mehr</span></button>
|
||
</nav>
|
||
</div>
|
||
|
||
<dialog id="entry-dialog" class="modal">
|
||
<form id="entry-form" method="dialog" class="modal-card">
|
||
<div class="modal-head"><div><p class="eyebrow">ZEITEINTRAG</p><h2 id="entry-dialog-title">Eintrag bearbeiten</h2></div><button type="button" class="icon-btn" data-close="entry-dialog">×</button></div>
|
||
<input type="hidden" id="entry-id">
|
||
<label>Kunde<input id="edit-client" maxlength="200" list="client-list"></label>
|
||
<label>Tätigkeit<textarea id="edit-activity" rows="4" maxlength="4000"></textarea></label>
|
||
<div class="two-col"><label>Start<input id="edit-start" type="datetime-local" required></label><label>Ende<input id="edit-end" type="datetime-local"></label></div>
|
||
<p class="muted small">Dauer: <strong id="edit-duration">–</strong></p>
|
||
<p id="entry-error" class="error-box" hidden></p>
|
||
<div class="modal-actions split"><button type="button" id="delete-entry" class="btn danger" hidden>Löschen</button><div class="spacer"></div><button type="button" class="btn subtle" data-close="entry-dialog">Abbrechen</button><button type="submit" class="btn primary">Speichern</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="settings-dialog" class="modal modal-wide">
|
||
<form id="settings-form" method="dialog" class="modal-card">
|
||
<div class="modal-head"><div><p class="eyebrow">POCKETWATCH</p><h2>Einstellungen</h2></div><button type="button" class="icon-btn" data-close="settings-dialog">×</button></div>
|
||
<div class="settings-grid">
|
||
<section>
|
||
<h3>Anzeige & Auswertung</h3>
|
||
<label>Zeitformat<select id="setting-time-format"><option value="24">24 Stunden</option><option value="12">12 Stunden</option></select></label>
|
||
<label>Rundung in Minuten<input id="setting-rounding" type="number" min="1" max="60"></label>
|
||
<label class="check-row"><input id="setting-round-up" type="checkbox"><span>Immer aufrunden</span></label>
|
||
<label class="check-row"><input id="setting-week" type="checkbox"><span>Wochensumme anzeigen</span></label>
|
||
<label class="check-row"><input id="setting-sticky" type="checkbox"><span>Tagesüberschriften fixieren</span></label>
|
||
<label class="check-row"><input id="setting-reminder" type="checkbox"><span>Warnung bei langem Timer</span></label>
|
||
<label class="check-row"><input id="setting-mobile-compact" type="checkbox"><span>Kompaktansicht auf Mobilgeräten</span></label>
|
||
</section>
|
||
<section>
|
||
<h3>Export</h3>
|
||
<label>Name im PDF<input id="setting-export-name" maxlength="120"></label>
|
||
<label>Zeitzone für Exporte<input id="setting-timezone" maxlength="80" placeholder="Europe/Berlin"></label>
|
||
<label class="check-row"><input id="setting-export-date" type="checkbox"><span>Exportdatum im PDF</span></label>
|
||
<p class="muted small">Tipp: Die Zeitzone wird beim ersten Öffnen automatisch aus dem Browser übernommen.</p>
|
||
<button type="button" class="btn subtle" id="change-own-password">Eigenes Passwort ändern</button>
|
||
</section>
|
||
</div>
|
||
<section id="admin-section" class="admin-section" hidden>
|
||
<div class="section-title"><div><p class="eyebrow">ADMIN</p><h3>Benutzer</h3></div><button type="button" id="add-user" class="btn subtle">+ Benutzer</button></div>
|
||
<div id="user-list" class="user-list"></div>
|
||
</section>
|
||
<p id="settings-error" class="error-box" hidden></p>
|
||
<div class="modal-actions"><button type="button" id="mobile-logout" class="btn danger mobile-compact-only">Abmelden</button><div class="spacer"></div><button type="button" class="btn subtle" data-close="settings-dialog">Abbrechen</button><button type="submit" class="btn primary">Speichern</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="user-dialog" class="modal">
|
||
<form id="user-form" method="dialog" class="modal-card compact">
|
||
<div class="modal-head"><h2>Benutzer anlegen</h2><button type="button" class="icon-btn" data-close="user-dialog">×</button></div>
|
||
<label>Benutzername<input id="new-username" minlength="3" maxlength="64" required></label>
|
||
<label>Anzeigename<input id="new-display-name" maxlength="120"></label>
|
||
<label>Passwort<input id="new-password" type="password" minlength="10" required></label>
|
||
<label>Rolle<select id="new-role"><option value="user">Benutzer</option><option value="admin">Administrator</option></select></label>
|
||
<p id="user-error" class="error-box" hidden></p>
|
||
<div class="modal-actions"><button type="button" class="btn subtle" data-close="user-dialog">Abbrechen</button><button type="submit" class="btn primary">Anlegen</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="account-password-dialog" class="modal">
|
||
<form id="account-password-form" method="dialog" class="modal-card compact">
|
||
<div class="modal-head"><h2>Eigenes Passwort ändern</h2><button type="button" class="icon-btn" data-close="account-password-dialog">×</button></div>
|
||
<label>Aktuelles Passwort<input id="current-password" type="password" autocomplete="current-password" required></label>
|
||
<label>Neues Passwort<input id="own-new-password" type="password" minlength="10" autocomplete="new-password" required></label>
|
||
<p id="account-password-error" class="error-box" hidden></p>
|
||
<div class="modal-actions"><button type="button" class="btn subtle" data-close="account-password-dialog">Abbrechen</button><button type="submit" class="btn primary">Ändern</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="password-dialog" class="modal">
|
||
<form id="password-form" method="dialog" class="modal-card compact">
|
||
<div class="modal-head"><h2>Passwort zurücksetzen</h2><button type="button" class="icon-btn" data-close="password-dialog">×</button></div>
|
||
<input type="hidden" id="password-user-id">
|
||
<label>Neues Passwort<input id="reset-password" type="password" minlength="10" required></label>
|
||
<p id="password-error" class="error-box" hidden></p>
|
||
<div class="modal-actions"><button type="button" class="btn subtle" data-close="password-dialog">Abbrechen</button><button type="submit" class="btn primary">Zurücksetzen</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="export-dialog" class="modal">
|
||
<div class="modal-card compact">
|
||
<div class="modal-head"><div><p class="eyebrow">EXPORT</p><h2>Zeiten exportieren</h2></div><button type="button" class="icon-btn" data-close="export-dialog">×</button></div>
|
||
<p class="muted">Rundung und Zeitzone werden aus deinen Einstellungen übernommen.</p>
|
||
<div class="export-scope" role="radiogroup" aria-label="Exportumfang">
|
||
<label class="check-row"><input type="radio" name="export-scope" value="view" checked><span>Aktuelle Ansicht</span></label>
|
||
<label class="check-row"><input type="radio" name="export-scope" value="custom"><span>Eigener Zeitraum</span></label>
|
||
</div>
|
||
<div id="export-custom" class="two-col" hidden>
|
||
<label>Von<input id="export-from" type="date"></label>
|
||
<label>Bis<input id="export-to" type="date"></label>
|
||
</div>
|
||
<div class="two-col">
|
||
<label>Sortierung<select id="export-sort"><option value="desc">Neueste zuerst</option><option value="asc">Älteste zuerst</option></select></label>
|
||
<label class="check-row export-compact"><input id="export-compact" type="checkbox"><span>Nur Zeiten (ohne Tätigkeit)</span></label>
|
||
</div>
|
||
<p id="export-preview" class="export-preview">0 Einträge · 0:00</p>
|
||
<div class="export-buttons"><button id="export-service" class="btn subtle service-report-button">Service-Bericht für Unterschrift</button><button id="export-pdf" class="btn primary">PDF herunterladen</button><button id="export-csv" class="btn subtle">CSV herunterladen</button></div>
|
||
</div>
|
||
</dialog>
|
||
|
||
<dialog id="service-report-dialog" class="modal modal-wide">
|
||
<form id="service-report-form" class="modal-card">
|
||
<div class="modal-head"><div><p class="eyebrow">SERVICE</p><h2>Service-Bericht erstellen</h2></div><button type="button" class="icon-btn" data-close="service-report-dialog">×</button></div>
|
||
<p class="muted">Der Bericht übernimmt den Zeitraum aus dem Export und enthält nur abgeschlossene Tätigkeiten des ausgewählten Kunden.</p>
|
||
<div class="two-col">
|
||
<label>Kunde *<input id="service-client" list="client-list" maxlength="200" required placeholder="Kunde / Projekt"></label>
|
||
<label>Ansprechpartner<input id="service-contact" maxlength="200" placeholder="Name beim Kunden"></label>
|
||
</div>
|
||
<div class="two-col">
|
||
<label>Einsatzort<input id="service-location" maxlength="400" placeholder="Standort / Adresse"></label>
|
||
<label>Auftrag / Ticket<input id="service-order" maxlength="120" placeholder="z. B. SR-2026-0042"></label>
|
||
</div>
|
||
<label>Betreff<input id="service-subject" maxlength="200" value="Service-Bericht"></label>
|
||
<label>Zusammenfassung / Bemerkungen<textarea id="service-notes" rows="4" maxlength="6000" placeholder="Optional: Ergebnis, Hinweise, offene Punkte …"></textarea></label>
|
||
<div class="two-col">
|
||
<label>Ort<input id="service-place" maxlength="120" placeholder="Ort der Unterschrift"></label>
|
||
<label>Berichtsdatum<input id="service-date" type="date" required></label>
|
||
</div>
|
||
<p id="service-preview" class="export-preview">Kunde und Zeitraum wählen.</p>
|
||
<p id="service-error" class="error-box" hidden></p>
|
||
<div class="modal-actions"><button type="button" class="btn subtle" data-close="service-report-dialog">Abbrechen</button><button type="submit" class="btn primary">Service-Bericht PDF</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<div id="toast" class="toast" role="status" aria-live="polite" hidden></div>
|
||
<script src="/static/app.js" defer></script>
|
||
</body>
|
||
</html>
|