Files
Kontrollverlust/frontend/src/Layout.tsx
T
irrlichtandClaude Opus 5.5 ca65ddcacc React-Frontend: Login, Registrierung, Header, neuer Beitrag
- AuthBox mit Login/Registrierung (Auto-Login nach Registrierung)
- Compose mit Zwischenablage-Bild, Feed springt danach an den Anfang
- Headerbar mit Profil-Link und Logout
- useAuthChanged: me und Votes nach Login/Logout neu laden
- kein Aufblitzen der Login-Box, solange der Anmeldestatus lädt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TiXsPUqw7oeomZ8wZrQW5q
2026-09-26 23:38:03 +02:00

67 lines
2.1 KiB
TypeScript

import { Link, Outlet, useLocation } from "react-router";
import { api } from "./api";
import { useAuthChanged, useMe } from "./auth";
// Tage ohne Datenverlust (fester Startpunkt, Kontinuität seit der alten
// Version).
const dataLossStart = new Date("2025-12-13T12:44:00").getTime();
function plural(n: number, one: string, many: string) {
return `${n} ${n === 1 ? one : many}`;
}
// Layout ist der gemeinsame Seitenrahmen. Markup und IDs entsprechen dem alten
// Frontend (web/*.html), damit app.css unverändert greift: die Startseite hat
// Tagline und Headerbar, alle anderen Seiten den "zurück zum Feed"-Knopf.
export function Layout() {
const isHome = useLocation().pathname === "/";
const days = Math.floor((Date.now() - dataLossStart) / 86400000);
return (
<>
<header>
<nav id="legal">
<a href="/static/docs/impressum.html">Impressum</a> -{" "}
<a href="/static/docs/datenschutz.html">Datenschutz</a> -{" "}
<a href="/static/docs/beitragsordnung.html">Beitragsordnung</a> -{" "}
<Link to="/stats">Statistik</Link>
</nav>
<Link to="/"><h1>Kontrollverlust</h1></Link>
{isHome ? (
<>
<p id="stats" className="tagline">
Ohne Datenverlust seit {plural(days, "Tag", "Tagen")}
</p>
<Headerbar />
</>
) : (
<div id="headerbar"><Link className="button" to="/">zurück zum Feed</Link></div>
)}
</header>
<main>
<Outlet />
</main>
</>
);
}
// Headerbar der Startseite: angemeldet Profil-Link und Logout, sonst leer.
function Headerbar() {
const me = useMe().data;
const authChanged = useAuthChanged();
if (!me) return <div id="headerbar"></div>;
// POST statt GET: als GET wäre Logout per fremdem Link auslösbar (CSRF).
const logout = async () => {
await api.post("/auth/logout").catch(() => undefined);
await authChanged();
};
return (
<div id="headerbar">
<Link className="button" to={`/u/${encodeURIComponent(me.username)}`}>mein Profil</Link>{" "}
<button id="logout-btn" onClick={logout}>Logout</button>
</div>
);
}