Heatmap Tool (Standalone)
Eine Webanwendung zur Visualisierung von Excel-Daten (XLSX) auf einer Deutschlandkarte. Das Tool aggregiert Daten basierend auf Postleitzahlen (PLZ) und stellt sie entweder als Punkte-Cluster oder als Heatmap dar.
Features
- Excel Upload: Lädt beliebige
.xlsxDateien. Erkennt automatisch die PLZ-Spalte (oder fragt nach, wenn unklar). - Personal-Standorte: Fest hinterlegte Standorte von Vertrieblern (Blau) und Technikern (Orange) können unabhängig von Excel-Daten eingeblendet werden.
- Einzugsgebiete (Isochronen):
- Visualisierung der Erreichbarkeit basierend auf echter Fahrtzeit über das Straßennetz (via OpenRouteService).
- Berücksichtigt Autobahnen und Straßentypen (verzerrte Polygone statt perfekter Kreise).
- Fallback: Automatisches Umschalten auf ein mathematisches Kreis-Modell (Radius = Zeit * Geschwindigkeit), falls kein API-Key vorhanden ist.
- Interaktive Planung: Schieberegler für Fahrtzeit (bis 60 Min.) und Durchschnittsgeschwindigkeit zur Simulation von Reichweiten.
- Visualisierung:
- Punkte-Karte: Kreise pro PLZ, Radius = Anzahl der Einträge. Mit Marker-Clustering beim Herauszoomen.
- Heatmap: Klassische Dichte-Darstellung.
- Interaktive Filter: Alle anderen Spalten der Excel-Datei werden automatisch zu Filtern (Checkboxen).
- Dynamische Tooltips: Benutzer können per Drag-and-Drop konfigurieren, welche Daten im Tooltip eines Punktes angezeigt werden.
Installation & Start
Das Projekt ist vollständig in den GTM-Engine Stack integriert.
-
API Key konfigurieren: Für echte Fahrtzeiten (Isochronen) einen kostenlosen Key auf openrouteservice.org erstellen und in der
.envhinterlegen:ORS_API_KEY=dein_key_hier -
Container starten (im Root-Verzeichnis):
docker-compose up -d --build heatmap-frontend heatmap-backend
Architektur
- Frontend: React 19, Vite, Leaflet (
react-leaflet,react-leaflet-cluster,react-leaflet-heatmap-layer-v3).- Interner Port: 80 (Nginx)
- Routing:
/heatmap/(via Gateway)
- Backend: Python FastAPI, Pandas, Requests (für ORS API).
- Interner Port: 8000
- Kommunikation: Nginx (Frontend) leitet
/api/Anfragen an das Backend weiter.
Lessons Learned & Known Issues (WICHTIG!)
1. OpenRouteService (ORS) API Limits
- Limit: Der kostenlose "Free Tier" erlaubt Isochronen bis maximal 60 Minuten.
- Fehler: Anfragen über 60 Min. resultieren in einem
400 Bad Request. Das Frontend ist daher auf diesen Wert begrenzt. - Debouncing: Da API-Calls kontingentiert sind (500/Tag), werden Isochronen erst nach einer kurzen Pause (800ms) beim Schieben des Reglers angefordert.
2. Docker Networking & Nginx Proxy
- Integration: Das Tool läuft nun hinter einem zentralen Nginx-Gateway.
- Pfad-Anpassung:
vite.config.tsnutztbase: '/heatmap/', damit Assets korrekt geladen werden. - API-Routing: Das Frontend-Nginx (
nginx.conf) proxied/api/anhttp://heatmap-backend:8000. Dies verhindert405 Method Not AllowedFehler bei POST-Requests, die sonst vom statischen Server abgefangen würden.
2. React 19 vs. Leaflet Libraries
- Problem: Viele Leaflet-Plugins (wie
react-leaflet-heatmap-layer-v3) haben veraltete Peer-Dependencies (z.B. React 17), was beinpm installzu Fehlern führt. - Lösung:
- Lokal: Installation mit
--legacy-peer-deps. - Docker Build: Im
Dockerfiledes Frontends muss zwingendRUN npm install --legacy-peer-depsstehen, sonst schlägt der Build fehl.
- Lokal: Installation mit
3. Import/Export Syntax (TypeScript)
- Problem:
Uncaught SyntaxError: The requested module ... does not provide an export named ... - Ursache: Beim Importieren von TypeScript-Interfaces (z.B.
TooltipColumn) in einer.tsxDatei wurde das Schlüsselworttypevergessen. - Korrekt:
import type { TooltipColumn } from '../App'; - Falsch:
import { TooltipColumn } from '../App';(Führt zu Runtime-Fehlern im Browser, da Vite versucht, es als JS-Code zu kompilieren).
4. Endlosschleifen bei Karten-Events (Vorsicht!)
- Problem: Versuch, eine "zoom-adaptive Legende" zu bauen, die den
maxCountbasierend auf dem sichtbaren Ausschnitt neu berechnet. - Fehler: Ein
useEffectoder Event-Handler (useMapEvents), der den State (visibleData) aktualisiert, löst ein Re-Render der Karte aus. Das Re-Render löst erneut das Event aus -> Endlosschleife / Stack Overflow. - Status: Feature wurde reverted. Wenn wir das wieder einbauen, muss der Handler vom Rendering entkoppelt sein (z.B. via
useCallbackoder komplett außerhalb der Render-Logik der Map-Komponente).
5. Daten-Normalisierung
- Problem:
KeyError: 'plz'. Die Excel-Datei hatte "PLZ" (groß), das Backend erwartete "plz" (klein) oder umgekehrt. - Lösung: Das Backend normalisiert jetzt die Spaltennamen intern, bevor die Daten an das Frontend gesendet werden. Das Frontend verlässt sich strikt auf klein geschrieben
plz,lat,lon.