React-Frontend: Grundgerüst (Vite, TypeScript, Router, TanStack Query)

- frontend/ mit Vite 8, React 19, React Router 8, TanStack Query 5, TS 7
- api.ts: Fehler allein über HTTP-Status (ApiError), errMsg wie bisher
- types.ts: API-Antworten laut notes/api.md
- Layout mit unverändertem Header-Markup, app.css als Kopie
- Dev-Proxy für /api und /static aufs Go-Backend
- Containerfile: HEALTHCHECK auf /api/stats

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TiXsPUqw7oeomZ8wZrQW5q
This commit is contained in:
irrlicht
2026-09-26 23:18:56 +02:00
co-authored by Claude Opus 5.5
parent 030a5bd943
commit 37279ac90d
18 changed files with 2091 additions and 1 deletions
+45
View File
@@ -0,0 +1,45 @@
import { Link, Outlet, useLocation } from "react-router";
// 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>
<div id="headerbar"></div>
</>
) : (
<div id="headerbar"><Link className="button" to="/">zurück zum Feed</Link></div>
)}
</header>
<main>
<Outlet />
</main>
</>
);
}