This commit is contained in:
Frank Schwenk
2026-06-09 21:30:41 +02:00
parent eaa019087e
commit 019428ad5c
3 changed files with 46 additions and 47 deletions
+25 -30
View File
@@ -5,45 +5,40 @@ import { enqueue, flushQueue } from "./lib/offlineQueue.js";
import { registerPwa, wirePwaInstall, subscribePush } from "./lib/pwa.js";
import { renderSlots, renderHeatmap, updateStats, showToast, showConfetti, showEasterEgg } from "./lib/ui.js";
let pinBuffer = "";
const STATUS = { upcoming: "Noch nicht", pending: "Jetzt!", overdue: "Überfällig", snoozed: "Snoozed", taken: "Genommen", missed: "Verpasst" };
function showScreen(id) {
document.querySelectorAll(".screen").forEach((s) => { s.hidden = s.id !== id; });
}
function wirePinPad() {
const pad = document.getElementById("pinPad");
const keys = ["1","2","3","4","5","6","7","8","9","⌫","0","✓"];
pad.innerHTML = keys.map((k) =>
`<button type="button" class="pinKey${k.length > 1 ? " wide" : ""}" data-key="${k}">${k}</button>`
).join("");
function wirePinForm() {
const form = document.getElementById("pinForm");
const input = document.getElementById("pinInput");
const errEl = document.getElementById("loginError");
pad.addEventListener("click", async (e) => {
const btn = e.target.closest("[data-key]");
if (!btn) return;
const key = btn.dataset.key;
const errEl = document.getElementById("loginError");
input.addEventListener("input", () => {
const digits = input.value.replace(/\D/g, "").slice(0, 6);
if (input.value !== digits) input.value = digits;
errEl.hidden = true;
});
if (key === "⌫") { pinBuffer = pinBuffer.slice(0, -1); }
else if (key === "✓") {
if (pinBuffer.length < 4) return;
try {
const { token } = await api.login(pinBuffer);
setToken(token);
pinBuffer = "";
await initApp();
} catch {
errEl.textContent = "Falscher PIN. Dein Gehirn auch.";
errEl.hidden = false;
pinBuffer = "";
}
} else if (pinBuffer.length < 6) {
pinBuffer += key;
form.addEventListener("submit", async (e) => {
e.preventDefault();
const pin = input.value.trim();
if (pin.length < 4) return;
errEl.hidden = true;
try {
const { token } = await api.login(pin);
setToken(token);
input.value = "";
await initApp();
} catch {
errEl.textContent = "Falscher PIN. Dein Gehirn auch.";
errEl.hidden = false;
input.value = "";
input.focus();
}
document.getElementById("pinDisplay").textContent = "•".repeat(pinBuffer.length) || "••••";
});
}
@@ -167,7 +162,7 @@ async function boot() {
try { await initApp(); return; } catch { clearToken(); }
}
showScreen("loginScreen");
wirePinPad();
wirePinForm();
}
boot();
+4 -2
View File
@@ -22,8 +22,10 @@
<h1>TakeYourMeds</h1>
<p class="tagline">Dein Gehirn. Deine Medis. Unser Sarkasmus.</p>
</div>
<div class="pinDisplay" id="pinDisplay">••••</div>
<div class="pinPad" id="pinPad"></div>
<form id="pinForm" class="pinForm">
<input type="number" id="pinInput" class="pinInput" inputmode="numeric" min="0" max="999999" step="1" placeholder="PIN" autocomplete="off" required>
<button type="submit" class="btn btn-primary pinSubmit">Anmelden</button>
</form>
<p class="loginError" id="loginError" hidden></p>
</section>
+17 -15
View File
@@ -43,25 +43,27 @@ body {
.loginHero h1 { font-size: 2rem; color: var(--primary); text-shadow: 0 2px 12px rgba(241,47,18,.5); }
.tagline { color: var(--text-muted); margin-top: .5rem; font-size: .95rem; }
.pinDisplay {
text-align: center; font-size: 2rem; letter-spacing: .5rem;
margin: 1rem 0; color: var(--accent-cyan); min-height: 2.5rem;
.pinForm {
display: flex; flex-direction: column; gap: .75rem;
max-width: 280px; margin: 1rem auto 0;
}
.pinPad {
display: grid; grid-template-columns: repeat(3, 1fr); gap: .75rem;
max-width: 280px; margin: 0 auto;
}
.pinKey {
aspect-ratio: 1; border: none; border-radius: var(--radius);
background: var(--bg-card); color: var(--text);
.pinInput {
width: 100%; padding: .85rem 1rem;
border: 2px solid var(--bg-card-hover); border-radius: var(--radius);
background: var(--bg-card); color: var(--accent-cyan);
font-family: inherit; font-size: 1.5rem; font-weight: 600;
cursor: pointer; transition: transform .1s, background .15s;
box-shadow: 0 4px 12px rgba(0,0,0,.3);
text-align: center; letter-spacing: .5rem;
-moz-appearance: textfield;
}
.pinKey:active { transform: scale(.93); background: var(--primary); }
.pinKey.wide { grid-column: span 1; font-size: 1rem; }
.pinInput:focus {
outline: none; border-color: var(--accent-cyan);
box-shadow: 0 0 0 3px rgba(0, 229, 255, .2);
}
.pinInput::-webkit-outer-spin-button,
.pinInput::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pinSubmit { width: 100%; }
.loginError { text-align: center; color: var(--danger); margin-top: 1rem; }