Frontend: gemeinsamer Hook useLiveData, Komponenten nach Bereichen, große Seiten aufgeteilt

- useLiveData: Laden, Nachladen (sichtbarer Tab) und Speichern mit
  Fehlerbehandlung an einer Stelle; genutzt von Vorrat, Reisen,
  Kanban-Übersicht und Kanban-Board (Monitoring/Benutzer arbeiten anders)
- components/<bereich>/: haushalt, reisen, kanban, monitoring, projekte,
  start, design (per git mv, Historie bleibt)
- Reisen.jsx 783 → 227 Zeilen (CitySearch, VisitedList, InfoCard,
  ExportDialog, laender.js), Haushalt.jsx 634 → 193 (ListPanel,
  ListSwitcher, ListDialog, ProductsDialog), KanbanBoard.jsx 452 → 277
  (board.js, TaskCard, TaskDialog)
- storage.js für Einstellungen pro Browser; Städteliste in Reisen memoisiert
- Verhalten unverändert (Browser-Durchlauf aller Seiten und Abläufe)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
guyg1474andClaude Opus 5.5 committed 2026-10-15 18:14:32 +02:00
1 parent 4aba48ce51
commit fa58708e2d
41 files changed
+1264 -1241

No files matched your search

@@ -0,0 +1,28 @@
// Hintergrund "Fabrik" (Industrie-UI im Stil von Satisfactory): Hallenwand mit Riffelblech-Boden,
// HUD-Linie oben und zwei langsam drehende Zahnräder. Nur CSS/SVG, ohne Animation steht alles still.
// Zahnrad als Umriss mit Loch (evenodd): Zähne trapezförmig zwischen Fuß- und Kopfkreis
function gearPath(teeth, outer, inner, hole) {
const step = (Math.PI * 2) / teeth;
const pts = [];
for (let i = 0; i < teeth; i += 1) {
const a = i * step;
pts.push([inner, a - step * 0.32], [outer, a - step * 0.18], [outer, a + step * 0.18], [inner, a + step * 0.32]);
}
const ring = pts.map(([r, a], i) => `${i ? 'L' : 'M'}${(r * Math.cos(a)).toFixed(2)} ${(r * Math.sin(a)).toFixed(2)}`).join('');
return `${ring}Z M${hole} 0A${hole} ${hole} 0 1 0 ${-hole} 0A${hole} ${hole} 0 1 0 ${hole} 0Z`;
}
const BIG = gearPath(14, 48, 40, 15);
const SMALL = gearPath(10, 48, 38, 18);
export default function FabrikField() {
return (
<div className="theme-bg fabrik-field" aria-hidden="true">
<div className="fabrik-floor" />
<svg className="fabrik-gear big" viewBox="-50 -50 100 100"><path d={BIG} fillRule="evenodd" /></svg>
<svg className="fabrik-gear small" viewBox="-50 -50 100 100"><path d={SMALL} fillRule="evenodd" /></svg>
<div className="fabrik-hud" />
</div>
);
}