Erste Produktivversion

This commit is contained in:
2026-08-08 20:31:58 +02:00
parent d8ded2816d
commit 7b21e2d1b4
110 changed files with 18170 additions and 644 deletions

View File

@@ -0,0 +1,81 @@
// Willkommensstrecke: Passwort setzen über den Link aus der
// Einladungsnachricht. Läuft ohne Anmeldung.
"use strict";
import { get, post } from "../api.js";
import { el, mount } from "../dom.js";
export async function welcomeView(root, { token, toLogin }) {
let preview;
try {
preview = await get(`/api/auth/welcome/${encodeURIComponent(token)}`);
} catch (err) {
mount(root,
el("section.card", {},
el("h1", {}, "Einladung"),
el("p.error", {}, err.message),
el("button.primary", { type: "button", onclick: toLogin }, "Zur Anmeldung")));
return;
}
const nameField = el("input", {
type: "text",
maxLength: 80,
value: preview.display_name || "",
placeholder: "wird anderen Mitgliedern angezeigt",
});
const passField = el("input", {
type: "password",
autocomplete: "new-password",
onkeydown: (ev) => { if (ev.key === "Enter") submit(); },
});
const repeatField = el("input", {
type: "password",
autocomplete: "new-password",
onkeydown: (ev) => { if (ev.key === "Enter") submit(); },
});
const error = el("p.error", { hidden: true });
const notice = el("p.notice", { hidden: true });
const button = el("button.primary", { type: "button" }, "Zugang einrichten");
async function submit() {
error.hidden = true;
if (passField.value !== repeatField.value) {
error.textContent = "Die beiden Eingaben stimmen nicht überein.";
error.hidden = false;
return;
}
button.disabled = true;
try {
const result = await post("/api/auth/welcome/complete", {
token,
password: passField.value,
display_name: nameField.value.trim() || null,
});
notice.textContent = result.detail;
notice.hidden = false;
setTimeout(toLogin, 1500);
} catch (err) {
error.textContent = err.message;
error.hidden = false;
button.disabled = false;
}
}
button.addEventListener("click", submit);
mount(root,
el("section.card", {},
el("h1", {}, "Willkommen"),
el("p.lead", {},
`Für ${preview.email} wurde ein Zugang eingerichtet. `,
"Leg jetzt dein Passwort fest danach kannst du dich anmelden."),
el("label", {}, "Anzeigename ", el("span.hint", {}, "(freiwillig)")), nameField,
el("label", {}, "Passwort ", el("span.hint", {}, "(mindestens 12 Zeichen)")), passField,
el("label", {}, "Wiederholen"), repeatField,
error,
notice,
button));
passField.focus();
}