Service Worker (public/sw.js) cached die App-Shell für Seiten-GETs
(network-first, cache-fallback). Durchsichten, die offline gespeichert
werden, landen in einer IndexedDB-Warteschlange (idb) statt zu
scheitern und werden automatisch synchronisiert, sobald wieder
Netzwerk verfügbar ist (Mount + online-Event), mit manuellem Retry
über ein Badge im App-Header. Ein modulweiter In-Flight-Lock in
sync.ts verhindert doppelte Synchronisierung bei gleichzeitigen
Aufrufen (gefunden über React-StrictMode-Doppel-Mount, das ohne den
Lock dieselbe Durchsicht zweimal anlegte).
Neue Seite /apiaries/map zeigt alle Bienenstände mit hinterlegten
Koordinaten auf einer Leaflet-Karte (OpenStreetMap-Kacheln), mit
Marker-Popup, das zum jeweiligen Bienenstand verlinkt. Karte wird
per next/dynamic mit ssr:false geladen, da Leaflet auf window/document
zugreift.
Breiten-/Längengrad waren zwar seit dem MVP im Backend-DTO vorhanden,
aber über kein Formular erreichbar – ohne diese Lücke wäre die Karte
dauerhaft leer geblieben. Daher Breitengrad-/Längengrad-Felder auf der
Bienenstand-Anlegen- und Bearbeiten-Seite ergänzt.
Marker-Icons werden aus public/leaflet/ bedient statt aus
node_modules-Bild-Imports, da Turbopack Bilder aus node_modules nicht
als StaticImageData auflöst (führte zu "iconUrl not set"-Laufzeitfehler,
live im Browser gefunden und behoben) – der von Leaflet empfohlene
Workaround für Bundler-Icon-Probleme.
Live verifiziert: Koordinaten speichern, Karte zeigt Marker an
korrekter Position, Popup verlinkt korrekt, Empty State bei fehlenden
Koordinaten, mobile Breite ohne Overflow. Zero Konsolenfehler.
Backend war bereits fertig, das Frontend fehlte bislang. Neue
gemeinsame DocumentUploadCard-Komponente (Liste hochgeladener Dateien,
Upload per Dateiauswahl, Download, Löschen mit Bestätigungsdialog da
unumkehrbar) plus dazugehöriges src/lib/documents/ API-Modul.
apiFetch erzwingt bislang immer Content-Type: application/json, was
multipart-Uploads verhindert hätte – daher neue apiFetchFormData-
Hilfsfunktion in api-client.ts ergänzt (kein manuell gesetzter
Content-Type, damit der Browser die multipart-Boundary selbst setzt).
Eingebunden auf allen Detailseiten, die laut TASKS.md Modul 29 vorsehen
und tatsächlich eine eigene Route haben: Bienenstand, Volk, Königin,
Honigcharge. Durchsicht hat keine eigene Detailseite (nur Einträge in
der Volk-Unterliste) und wird daher vorerst ausgelassen.
Live verifiziert: Upload, Download und Löschen (inkl. Bestätigungsdialog)
funktionieren End-to-End gegen das Backend, zero Konsolenfehler auf
allen vier Detailseiten.
Neue gemeinsame EmptyState-Komponente (Icon in Kreis, Titel, Beschreibung,
gestrichelter Rahmen) und Einbindung auf allen 9 Listenseiten mit Tabellen
(Völker, Bienenstände, Königinnen, Aufgaben, Honigchargen, Benutzer,
Inventar, Produkte, Lager mit Behältern und Artikeln).
Bug behoben: Bei leerem Datensatz wurde bisher nur eine Tabelle mit
Kopfzeile und keinerlei Inhalt oder Erklärung angezeigt – wirkte wie ein
Ladefehler statt eines normalen "noch keine Daten"-Zustands. Besonders
für neurodivergente Nutzer wichtig, da Unklarheit über den Systemzustand
("ist das kaputt oder einfach leer?") unnötige kognitive Last erzeugt.
Aktiver Tab war kaum vom Tab-Leisten-Hintergrund zu unterscheiden
(fast gleicher Ton). Jetzt weisser Karten-Hintergrund mit Schatten
und Primaerfarben-Text fuer den aktiven Tab, groesserer Radius/Padding
passend zum Rest der Oberflaeche.
Neue PageHeader-Komponente (Gradient-Icon-Badge + Titel + Beschreibung
+ Aktionen) ersetzt die nackten <h1>-Zeilen auf den meistgenutzten
Seiten (Voelker, Bienenstaende, Koeniginnen, Aufgaben, Honigchargen,
Statistik, Webhooks, Benutzerverwaltung). Gradient variiert pro
Bereich (Honig/Salbei/Himmel), passend zum jeweiligen Sidebar-Icon.
Primaerer Button-Stil nutzt jetzt den Honig-Gradient statt Volltonfarbe,
mit Schatten und Hover-Lift. Buttons/Inputs/Select/Textarea/Dialog auf
rounded-xl bzw. rounded-2xl vereinheitlicht, Formularfelder mit Karten-
hintergrund, dezentem Schatten und Hover-Rahmen statt nacktem Rand.
Dialog-Footer-Radius/Aussenabstand an das groessere Popup-Padding
angepasst, sonst waere die Ecke am Fusszeilen-Rand versetzt gewesen.
Die geteilte Table-Komponente (11 Listenseiten: Voelker, Bienenstaende,
Koeniginnen, Aufgaben, Honigchargen, Inventar, Produkte, Lager, Benutzer,
Audit-Log, Webhooks) bekommt jetzt denselben Karten-Rahmen/Schatten wie
der Rest der Oberflaeche statt nackt auf dem Hintergrund zu schweben,
plus getoente Kopfzeile, ruhigere Uppercase-Spaltentitel und mehr
Zeilenabstand.
Kartenhintergrund und Seitenhintergrund waren fast farbgleich, wodurch
alles flach wirkte trotz vorhandenem Schatten. Staerkerer Kontrast
(--background/--card/--muted/--border), neue Gradient- und
Schatten-Tokens (--gradient-honey/-sage/-sky, --shadow-soft/-elevated).
Card-Komponente: rounded-2xl, echter sichtbarer Schatten, optionaler
Hover-Lift (interactive-Prop). Sidebar: solide Gradient-Badge, kraeftiger
Active-Pill-Zustand statt blassem Tint. Header: sticky mit Blur-Schatten
statt hartem Rand. Dashboard: Gradient-Hero mit Begruessung und
Honeycomb-Muster, farbige Gradient-Icon-Badges pro KPI-Kachel,
Hinweise-Zeilen mit Icon statt rohem Enum-Badge (dabei toten
CONSPICUOUS_COLONY-Style-Key gefunden und auf COLONY_ATTENTION
korrigiert). Honeycomb-Hintergrund aus der Login-Seite in eine
gemeinsame Komponente extrahiert und dort mit dem gleichen
Gradient-Badge-Header konsistent gemacht.
Volk aufloesen, Bienenstand deaktivieren, Benutzer deaktivieren und
Webhook loeschen liefen bisher ohne jede Rueckfrage direkt auf Klick.
Neue wiederverwendbare ConfirmDialog-Komponente erzwingt jetzt eine
bewusste Bestaetigung. Zusaetzlich zeigen Volk/Bienenstand/Benutzer
nach dem Aufloesen/Deaktivieren einen Reaktivieren-Button (nutzt die
neuen Backend-Endpunkte), da diese Aktionen nie ein echtes Loeschen
sind und ein versehentlicher Klick bisher nicht rueckgaengig zu
machen war.
Tab-basierte /statistics-Seite (Voelker, Koeniginnen, Bienenstaende,
Varroa, Honig, Futter) mit animierten Balkendiagrammen, Sidebar-Eintrag
und Live-Verifikation ueber alle Tabs sowie Mobile-Breakpoint.
NotificationBell in der Kopfzeile: ungelesene Anzahl als Badge,
Dropdown mit Prioritaets-Badges (INFO/HINWEIS/WARNUNG/KRITISCH),
Klick markiert als gelesen und fuehrt zum verknuepften Objekt.
Ausserdem IDOR im Backend gefunden und behoben (siehe vorheriger
Commit) - live mit einem echten Datensatz verifiziert.
Wiederverwendbarer QrCodeDialog (authentifizierter Blob-Fetch)
auf Volk-, Bienenstand-, Koenigin-, Honigcharge-Detailseiten und
je Lagerbehaelter-Zeile eingebunden.