Files
crushdb/backend/static/index.html
T
jhkaktus 516cb13dcf feat: Anlass + Endgrund fields for records
Adds two optional free-text fields to describe why a transaction
started ("Anlass") and why it ended ("Endgrund") - chosen names instead
of the technical "Startursache"/"Endesuhrsache". Displayed as own table
columns and editable in the form; legacy records without those fields
render as "-". Payload is encrypted client-side like every other field
(no server change needed, opaque ciphertext).

Verified: node --check, crypto roundtrip incl. new fields, legacy-safe
access (?? ''), pytest 3/3.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-10-11 01:04:46 +02:00

126 lines
4.5 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>crushdb</title>
<link rel="stylesheet" href="/static/style.css" />
</head>
<body>
<h1>crushdb</h1>
<p class="tagline">Verschlüsselte Datensätze zwischen zwei Personen</p>
<section id="flash" class="flash" aria-live="polite"></section>
<!-- First visit: NO records exist yet → user chooses a new passphrase -->
<section id="setup" hidden>
<form id="setup-form" autocomplete="off">
<h2>Willkommen bei crushdb!</h2>
<p class="intro">
Du benutzt crushdb zum ersten Mal. Wähle jetzt eine Passphrase –
sie ist das Master-Passwort für alle deine Daten. Es gibt keine
Zurücksetzung, speichere sie sicher!
</p>
<label>Neue Passphrase
<input type="password" id="setup-pass1" autocomplete="new-password"
required minlength="8" placeholder="mindestens 8 Zeichen" />
</label>
<label>Passphrase wiederholen
<input type="password" id="setup-pass2" autocomplete="new-password"
required placeholder="gleiche Passphrase nochmal" />
</label>
<button type="submit" id="setup-btn">Konto einrichten →</button>
<p id="setup-progress" class="hint" hidden>Schlüssel wird abgeleitet …</p>
<p class="hint">
Wichtig: Die Passphrase wird <strong>nicht am Server gespeichert</strong>.
Sie bleibt nur in deinem Browser-Arbeitsspeicher. Wer sie vergisst,
verliert Zugriff auf alle Daten (absichtlich so).
</p>
</form>
</section>
<!-- Returning user: records exist but are undecryptable → enter passphrase -->
<section id="unlock">
<form id="unlock-form" autocomplete="off">
<h2>Entsperren</h2>
<p class="intro">
Du hast bereits verschlüsselte Datensätze hinterlegt.
Gib deine Passphrase ein, um sie zu lesen.
</p>
<label>Passphrase
<input type="password" id="passphrase" autocomplete="current-password"
required placeholder="deine Passphrase …" />
</label>
<button type="submit" id="unlock-btn">Entsperren</button>
<p id="unlock-progress" class="hint" hidden>Schlüssel wird abgeleitet …</p>
<p class="hint">
Die Passphrase verlässt niemals deinen Browser. Sie wird per
Argon2id lokal abgeleitet und nur im Arbeitsspeicher gehalten.
</p>
</form>
</section>
<!-- main app, hidden until unlocked -->
<section id="app" hidden>
<div class="toolbar">
<button id="new-btn" type="button">+ Neuer Datensatz</button>
<button id="lock-btn" type="button">Sperren</button>
</div>
<table id="records">
<thead>
<tr>
<th>Person A</th>
<th>Person B</th>
<th>Start</th>
<th>Ende</th>
<th>Anlass</th>
<th>Endgrund</th>
<th>Aktion</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
</section>
<!-- create/edit modal -->
<div id="editor-backdrop" hidden>
<form id="editor" autocomplete="off">
<h2 id="editor-title">Neuer Datensatz</h2>
<label>Person A
<input id="f-persona" type="text" required maxlength="120" />
</label>
<label>Person B
<input id="f-personb" type="text" required maxlength="120" />
</label>
<label>Start (optional, beliebiger Text)
<input id="f-tsstart" type="text" maxlength="120"
placeholder="z. B. 12.03.2026, Sommer 2025, unbekannt …" />
</label>
<label>Ende (optional, beliebiger Text)
<input id="f-tsend" type="text" maxlength="120"
placeholder="z. B. laufend, unbekannt, März 2026 …" />
</label>
<label>Anlass (optional)
<input id="f-startcause" type="text" maxlength="300"
placeholder="womit/warum es begann, z. B. gemeinsam geplante Reise …" />
</label>
<label>Endgrund (optional)
<input id="f-endcause" type="text" maxlength="300"
placeholder="warum es endete, z. B. zurückgezahlt, abgelaufen …" />
</label>
<label>Aktion
<input id="f-action" type="text" required maxlength="500" />
</label>
<div class="actions">
<button type="submit">Speichern</button>
<button type="button" id="editor-cancel">Abbrechen</button>
</div>
</form>
</div>
<script type="module" src="/static/ui.js"></script>
</body>
</html>