feat: das Dashboard -- und die eine Regel steht im Code, nicht im Vorsatz

Schritt 4. React 18, TypeScript, Vite 5, Tailwind 4 (CSS-first), Lucide,
Zustand; kein Konsta. Quelle in server/ui, Build nach server/web (gitignored),
im Abbild von einer eigenen Docker-Stufe gebaut.

JEDER KNOPF GIBT RUECKMELDUNG -- und zwar erzwungen, nicht vorgenommen:

- api.ts haelt den EINZIGEN fetch und GENAU EINE Fehlerklasse. Der
  Fivemanage-Fehler war, zwei zu haben: geworfen wurde `new Error`, geprueft
  auf `instanceof ApiError`, und damit verschwand jeder Fehlschlag lautlos.
- store.ts haelt run(): Aktion rein, Erfolgstext rein, und es meldet bei
  Erfolg diesen und bei Fehlschlag den Text DES DIENSTES. Wer darueber geht,
  kann keinen stillen Knopf bauen.
- Jeder wartende Knopf ist gesperrt und zeigt einen Kreisel. Der zweite Klick
  eine Sekunde spaeter war der Weg zu neunzehn gleichnamigen Organisationen.
- Fehlermeldungen bleiben stehen, bis jemand sie wegklickt. Ein Fehler, der
  von allein verschwindet, ist einer, den niemand gelesen hat.

@vitejs/plugin-react ist auf ^4 festgenagelt: die 6 verlangt vite ^8. In den
peerDependencies nachgesehen -- Vite 5.4.21 liegt in der Schnittmenge von
plugin-react@4 und @tailwindcss/vite@4.

Am laufenden Container nachgemessen: / kommt als text/html, assets/*.js als
text/javascript, *.css als text/css (die MIME-Falle aus Schritt 1 traegt), und
/tokens, /speicher, /konto liefern dieselbe index.html -- die SPA-Rueckfall-
route tut, wofuer sie gebaut wurde.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 17:38:38 +02:00
co-authored by Claude Opus 5
parent 65828b526c
commit 6c8ead8e15
22 changed files with 4644 additions and 15 deletions
+19 -4
View File
@@ -26,6 +26,21 @@ COPY package.json package-lock.json ./
# native Binaerdatei fuer diese Node-Version.
RUN npm ci --omit=dev
# --------------------------------------------------------------- Oberflaeche
# Eigene Stufe, damit ein geaendertes Dashboard nicht den Server neu uebersetzt
# und umgekehrt. Was hier entsteht, ist reines HTML/CSS/JS -- im Betrieb laeuft
# davon nichts, es wird nur ausgeliefert.
FROM node:22-bookworm-slim AS web
WORKDIR /ui
COPY ui/package.json ui/package-lock.json ./
# Hier bewusst OHNE --omit=dev: vite und tsc sind devDependencies, und ohne sie
# gibt es nichts zu bauen.
RUN npm ci
COPY ui/ ./
# vite.config.ts schreibt nach ../web, also /web. Wer das dort aendert, aendert
# die Zeile im Betriebsabbild mit.
RUN npm run build
# -------------------------------------------------------------------- Bauen
FROM node:22-bookworm-slim AS build
WORKDIR /app
@@ -44,10 +59,10 @@ COPY --from=deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY package.json ./
# Die gebaute Oberflaeche kaeme nach ./web -- der Dienst liefert sie aus, wenn
# sie da ist, und sagt sonst, dass sie fehlt (siehe index.ts). Solange es sie
# nicht gibt, bleibt der Ordner leer statt zu fehlen.
RUN mkdir -p /app/web
# Die gebaute Oberflaeche. Der Dienst liefert sie aus, wenn sie da ist, und
# sagt sonst, dass sie fehlt (siehe index.ts) -- diese Auskunft bleibt als
# Netz, falls die Stufe oben je leer ausgeht.
COPY --from=web /web ./web
# Ein Ordner fuer Bilder UND media.db, damit eine Sicherung aus genau einem
# Kopiervorgang ueber ein Volume besteht.