diff --git a/frontend/src/components/InvitePage.jsx b/frontend/src/components/InvitePage.jsx
new file mode 100644
index 0000000..518b0ff
--- /dev/null
+++ b/frontend/src/components/InvitePage.jsx
@@ -0,0 +1,40 @@
+import React, { useEffect, useState } from "react";
+import { api } from "../api/client";
+import { styles } from "../styles/styles";
+import { stylesTokens } from "../styles/theme";
+
+export default function InvitePage({ token }) {
+ const [info, setInfo] = useState(null);
+ const [password, setPassword] = useState("");
+ const [confirm, setConfirm] = useState("");
+ const [message, setMessage] = useState("");
+ const [saving, setSaving] = useState(false);
+
+ useEffect(() => { api(`/auth/invite/${encodeURIComponent(token)}`).then(setInfo).catch((e) => setMessage("❌ " + (e?.message || "Diese Einladung ist nicht mehr gültig."))); }, [token]);
+ const submit = async (event) => {
+ event.preventDefault(); setMessage("");
+ if (password.length < 8) return setMessage("❌ Das Passwort muss mindestens 8 Zeichen haben.");
+ if (password !== confirm) return setMessage("❌ Die Passwörter stimmen nicht überein.");
+ setSaving(true);
+ try { await api(`/auth/invite/${encodeURIComponent(token)}`, { method: "POST", body: JSON.stringify({ password }) }); setMessage("✅ Passwort gesetzt. Du wirst weitergeleitet …"); setTimeout(() => { window.location.href = "/"; }, 700); }
+ catch (e) { setMessage("❌ " + (e?.message || "Einladung konnte nicht aktiviert werden.")); setSaving(false); }
+ };
+
+ return
+
+
+ ✦
+ Notizbogen
+ Deine Einladung
+ {info ? <>
+ {info.display_name}
{info.email} · {info.role}
+
+ > : {message || "Einladung wird geprüft …"}
}
+
+
;
+}
diff --git a/frontend/src/components/TopBar.jsx b/frontend/src/components/TopBar.jsx
index 032d624..fafaf79 100644
--- a/frontend/src/components/TopBar.jsx
+++ b/frontend/src/components/TopBar.jsx
@@ -10,6 +10,7 @@ export default function TopBar({
openDesignModal,
openStatsModal,
openAdminPanel,
+ openAdminSettings,
doLogout,
onOpenNewGame,
}) {
@@ -75,6 +76,15 @@ export default function TopBar({
>
Admin Dashboard
+
>
)}
diff --git a/frontend/src/styles/hooks/useHpGlobalStyles.js b/frontend/src/styles/hooks/useHpGlobalStyles.js
index aff555e..adb0622 100644
--- a/frontend/src/styles/hooks/useHpGlobalStyles.js
+++ b/frontend/src/styles/hooks/useHpGlobalStyles.js
@@ -113,10 +113,17 @@ export function useHpGlobalStyles() {
.hp-admin-check { display: flex; align-items: center; gap: 8px; color: var(--hp-textDim); font-size: 13px; }
.hp-admin-check input { width: 18px; height: 18px; accent-color: var(--hp-textGold); }
.hp-admin-editor-card { overflow: hidden; }
+ .hp-settings-grid { display: grid; grid-template-columns: minmax(0, 1fr) 140px; gap: 10px; }
+ .hp-settings-test { display: flex; align-items: end; gap: 10px; }
+ .hp-invite-card { animation: popIn 480ms cubic-bezier(.2,.8,.2,1); box-shadow: 0 24px 80px rgba(0,0,0,.6), 0 0 40px rgba(233,216,166,.08); }
+ .hp-invite-seal { width: 52px; height: 52px; margin: 0 auto 14px; display: grid; place-items: center; border: 1px solid rgba(233,216,166,.42); border-radius: 50%; color: var(--hp-textGold); font-size: 24px; box-shadow: 0 0 24px rgba(233,216,166,.12); }
.hp-admin-role { padding: 4px 8px; border-radius: 999px; background: rgba(233,216,166,0.10); border: 1px solid rgba(233,216,166,0.16); font-size: 12px; }
.hp-admin-status { color: #baf3c9 !important; font-size: 13px; }
.hp-admin-status--disabled { color: #ffb3b3 !important; }
@media (max-width: 600px) {
+ .hp-settings-grid { grid-template-columns: 1fr; }
+ .hp-settings-test { align-items: stretch; flex-direction: column; }
+ .hp-settings-test button { width: 100%; }
.hp-shell { padding: calc(12px + env(safe-area-inset-top)) 10px calc(28px + env(safe-area-inset-bottom)) !important; }
.hp-topbar { align-items: center !important; padding: 10px !important; gap: 6px !important; flex-wrap: nowrap !important; }
.hp-topbar > div:first-child { min-width: 0; flex: 1; }
@@ -136,6 +143,7 @@ export function useHpGlobalStyles() {
.hp-admin-actions .hp-admin-action { width: 36px; min-width: 36px; min-height: 36px; padding: 0 !important; }
.hp-admin-editor-card { padding: 14px !important; max-height: calc(100dvh - 20px) !important; }
.hp-admin-editor-card input, .hp-admin-editor-card select { min-height: 40px; padding: 8px 10px !important; }
+ .hp-admin-settings-card { padding: 14px !important; max-height: calc(100dvh - 20px) !important; overflow: auto; }
.hp-admin-editor-card button { min-height: 40px; }
.hp-row { grid-template-columns: minmax(0, 1fr) 42px 62px !important; gap: 7px !important; padding: 12px 11px !important; }
.hp-row button { min-height: 40px; }