From 405639db7da451ffb24f99c14eef719afc3c4c2c Mon Sep 17 00:00:00 2001 From: Pepe Ziberi Date: Thu, 23 Jul 2026 22:27:48 +0200 Subject: [PATCH] refactor(wind): Wind nur noch in der Kopfzeile (Karte = nur Nordpfeil) (v1.8.9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Wind-Anzeige von der Karte entfernt (war doppelt und nicht als "Wind" erkennbar); MapCompass zeigt jetzt nur den Nordpfeil - Kopfzeile: Wind-Badge ist klickbar → Einsteller (Live vom Standort / Richtung wählen / entfernen), klar mit "Wind" beschriftet - Topbar erhält onWindChange/onFetchLiveWind (nur bei Bearbeitungsrecht) Co-Authored-By: Claude Opus 4.8 (1M context) --- package.json | 2 +- src/app/app/page.tsx | 2 + src/components/layout/topbar.tsx | 94 +++++++++++++++++++---- src/components/map/map-compass.tsx | 116 +++++------------------------ 4 files changed, 100 insertions(+), 114 deletions(-) diff --git a/package.json b/package.json index 6bf0779..3f304db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lageplan", - "version": "1.8.8", + "version": "1.8.9", "description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation", "private": true, "scripts": { diff --git a/src/app/app/page.tsx b/src/app/app/page.tsx index ad76f84..a9cad62 100644 --- a/src/app/app/page.tsx +++ b/src/app/app/page.tsx @@ -1031,6 +1031,8 @@ export default function AppPage() { } }} windLive={windLive} + onWindChange={canEditMap ? (d) => handleWindChange(d) : undefined} + onFetchLiveWind={canEditMap ? handleFetchLiveWind : undefined} isEditingByMe={isEditingByMe} onStopEditing={handleStopEditing} editingLoading={editingLoading} diff --git a/src/components/layout/topbar.tsx b/src/components/layout/topbar.tsx index f2e875e..48fd68e 100644 --- a/src/components/layout/topbar.tsx +++ b/src/components/layout/topbar.tsx @@ -48,6 +48,8 @@ import { ChevronDown, Loader2, Share2, + Wind, + Satellite, } from 'lucide-react' import { HoseSettingsDialog } from '@/components/dialogs/hose-settings-dialog' import { ShareDialog } from '@/components/dialogs/share-dialog' @@ -56,6 +58,12 @@ import type { Project, DrawFeature, ProjectMode } from '@/types' import { formatDateTime } from '@/lib/utils' import { Logo } from '@/components/ui/logo' +// 8-Richtungs-Auswahl (Grad, meteorologisch „Wind aus") +const WIND_OPTIONS: { label: string; deg: number }[] = [ + { label: 'N', deg: 0 }, { label: 'NO', deg: 45 }, { label: 'O', deg: 90 }, { label: 'SO', deg: 135 }, + { label: 'S', deg: 180 }, { label: 'SW', deg: 225 }, { label: 'W', deg: 270 }, { label: 'NW', deg: 315 }, +] + interface TopbarProps { project: Project | null onNewProject: (mode?: ProjectMode) => void @@ -82,6 +90,10 @@ interface TopbarProps { onTogglePresentationLock?: () => void /** Windrichtung wird live aktualisiert (für die Live-Anzeige oben) */ windLive?: boolean + /** Windrichtung setzen/entfernen (Grad, meteorologisch „Wind aus"; null = entfernen) */ + onWindChange?: (dir: number | null) => void + /** Live-Wind (Open-Meteo) vom Standort holen */ + onFetchLiveWind?: () => Promise | void /** true, wenn der aktuelle Nutzer den Bearbeitungs-Lock hält */ isEditingByMe?: boolean /** Karte speichern & für andere freigeben (Lock lösen) */ @@ -115,6 +127,8 @@ export function Topbar({ presentationLocked, onTogglePresentationLock, windLive, + onWindChange, + onFetchLiveWind, isEditingByMe, onStopEditing, editingLoading, @@ -138,6 +152,8 @@ export function Topbar({ const [deleteConfirmId, setDeleteConfirmId] = useState(null) const [isDeleting, setIsDeleting] = useState(false) + const [windLoading, setWindLoading] = useState(false) + // Live clock const [now, setNow] = useState(new Date()) useEffect(() => { @@ -214,20 +230,70 @@ export function Topbar({ {/* Zone 3 — Uhr + Aktionen */}
- {/* Wind — taktische Live-Anzeige (Pfeil zeigt Ausbreitungsrichtung, N oben) */} - {typeof project?.windDirection === 'number' && ( -
- - - - - Wind aus {degToCompass(project.windDirection)} - - {windLive && } -
+ {/* Wind — klare, einzige Wind-Anzeige. Klick öffnet den Einsteller (Live vom Standort + oder Richtung wählen). Der Pfeil zeigt die Ausbreitungsrichtung, N oben. */} + {project && onWindChange && ( + + + {typeof project.windDirection === 'number' ? ( + + ) : ( + + )} + + +
+ Windrichtung (Wind aus) +
+ {onFetchLiveWind && ( + + )} +
oder Richtung wählen:
+
+ {WIND_OPTIONS.map((w) => ( + + ))} +
+ {typeof project.windDirection === 'number' && ( + + )} +
+
)} {/* Uhr — Ops-Rooms leben nach der Uhr */} diff --git a/src/components/map/map-compass.tsx b/src/components/map/map-compass.tsx index 0e24519..0d6f413 100644 --- a/src/components/map/map-compass.tsx +++ b/src/components/map/map-compass.tsx @@ -1,124 +1,42 @@ 'use client' -import { useState } from 'react' -import { Wind, X, Loader2, Satellite } from 'lucide-react' - interface MapCompassProps { /** Karten-Bearing in Grad (0 = Norden oben) */ bearing: number - /** Windrichtung meteorologisch „Wind aus" in Grad, oder null */ - windDirection: number | null | undefined - canEdit: boolean - onWindChange: (dir: number | null) => void - /** Live-Wind (Open-Meteo) für den aktuellen Standort holen */ + // Die folgenden Props werden nicht mehr verwendet (Wind lebt jetzt oben in der Kopfzeile), + // bleiben aber optional erhalten, damit bestehende Aufrufe nicht brechen. + windDirection?: number | null + canEdit?: boolean + onWindChange?: (dir: number | null) => void onFetchLiveWind?: () => Promise | void } const DIRS = ['N', 'NO', 'O', 'SO', 'S', 'SW', 'W', 'NW'] +/** Grad → Kompass-Kürzel (N, NO, …). Wird auch von der Kopfzeile für die Wind-Anzeige genutzt. */ export function degToCompass(deg: number): string { return DIRS[Math.round(((deg % 360) + 360) % 360 / 45) % 8] } -// 8-Richtungs-Auswahl (Grad, meteorologisch „aus") -const WIND_OPTIONS: { label: string; deg: number }[] = [ - { label: 'N', deg: 0 }, { label: 'NO', deg: 45 }, { label: 'O', deg: 90 }, { label: 'SO', deg: 135 }, - { label: 'S', deg: 180 }, { label: 'SW', deg: 225 }, { label: 'W', deg: 270 }, { label: 'NW', deg: 315 }, -] - -export function MapCompass({ bearing, windDirection, canEdit, onWindChange, onFetchLiveWind }: MapCompassProps) { - const [open, setOpen] = useState(false) - const [loadingLive, setLoadingLive] = useState(false) - const hasWind = typeof windDirection === 'number' - - const handleLive = async () => { - if (!onFetchLiveWind) return - setLoadingLive(true) - try { await onFetchLiveWind() } finally { setLoadingLive(false) } - } - +/** + * Reiner Nordpfeil/Kompass auf der Karte (dreht mit dem Karten-Bearing). + * Die Windrichtung wird NICHT mehr hier angezeigt — sie lebt eindeutig in der Kopfzeile. + */ +export function MapCompass({ bearing }: MapCompassProps) { return ( -
- {/* Kompass mit Nordpfeil (dreht mit dem Karten-Bearing) */} - - - {/* Wind-Anzeige */} - {hasWind && ( -
- - {/* Pfeil zeigt in die Drift-/Ausbreitungsrichtung (wohin es weht) */} - - - aus {degToCompass(windDirection as number)} -
- )} - {!hasWind && canEdit && ( - - )} - - {/* Wind-Auswahl */} - {open && canEdit && ( -
-
- Wind aus - -
- {onFetchLiveWind && ( - - )} -
oder Richtung wählen:
-
- {WIND_OPTIONS.map((w) => ( - - ))} -
- {hasWind && ( - - )} -
- )} +
) }