feat(weather): allow fetching OpenWeatherMap weather by location name and auto-populating GPS coordinates

This commit is contained in:
2026-05-28 16:21:34 +02:00
parent cc183edc6d
commit bbf8163a50
3 changed files with 41 additions and 9 deletions
+35 -7
View File
@@ -92,6 +92,7 @@ export default function LogEntryEditor({ entryId, logbookId, onBack }: LogEntryE
const [evGpsLat, setEvGpsLat] = useState('')
const [evGpsLng, setEvGpsLng] = useState('')
const [evRemarks, setEvRemarks] = useState('')
const [evLocationName, setEvLocationName] = useState('')
const [loading, setLoading] = useState(false)
const [saving, setSaving] = useState(false)
@@ -382,7 +383,10 @@ export default function LogEntryEditor({ entryId, logbookId, onBack }: LogEntryE
}
const handleFetchWeather = async () => {
if (!evGpsLat || !evGpsLng) {
const hasGps = evGpsLat && evGpsLng
const hasLocation = evLocationName.trim()
if (!hasGps && !hasLocation) {
showAlert(t('settings.gps_error'))
return
}
@@ -395,14 +399,25 @@ export default function LogEntryEditor({ entryId, logbookId, onBack }: LogEntryE
setWeatherLoading(true)
try {
const res = await fetch(
`https://api.openweathermap.org/data/2.5/weather?lat=${evGpsLat}&lon=${evGpsLng}&appid=${apiKey}&units=metric`
)
let url = ''
if (hasLocation) {
url = `https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(evLocationName.trim())}&appid=${apiKey}&units=metric`
} else {
url = `https://api.openweathermap.org/data/2.5/weather?lat=${evGpsLat}&lon=${evGpsLng}&appid=${apiKey}&units=metric`
}
const res = await fetch(url)
if (!res.ok) throw new Error('Weather API rejected the request')
const data = await res.json()
// If fetched by location, automatically pre-fill GPS coordinates
if (hasLocation && data.coord) {
setEvGpsLat(Number(data.coord.lat).toFixed(6))
setEvGpsLng(Number(data.coord.lon).toFixed(6))
}
// Convert wind speed m/s to Beaufort scale
const mps = data.wind.speed || 0
let bft = 0
@@ -513,6 +528,7 @@ export default function LogEntryEditor({ entryId, logbookId, onBack }: LogEntryE
setEvGpsLat('')
setEvGpsLng('')
setEvRemarks('')
setEvLocationName('')
}
const handleDeleteEvent = (index: number) => {
@@ -943,6 +959,18 @@ export default function LogEntryEditor({ entryId, logbookId, onBack }: LogEntryE
</div>
<div className="form-grid mb-4">
<div className="input-group">
<label>{t('logs.event_location')}</label>
<input
type="text"
placeholder={t('logs.event_location_placeholder')}
className="input-text"
value={evLocationName}
onChange={(e) => setEvLocationName(e.target.value)}
disabled={saving}
/>
</div>
<div className="input-group">
<label>{t('logs.event_gps')} (Lat, Lng)</label>
<div className="gps-input-row">
@@ -978,13 +1006,15 @@ export default function LogEntryEditor({ entryId, logbookId, onBack }: LogEntryE
onClick={handleFetchWeather}
title={t('logs.weather_btn')}
style={{ width: 'auto', padding: '12px' }}
disabled={saving || weatherLoading || !evGpsLat || !evGpsLng}
disabled={saving || weatherLoading || (!evLocationName.trim() && (!evGpsLat || !evGpsLng))}
>
<CloudSun size={16} />
</button>
</div>
</div>
</div>
<div className="form-grid mb-4">
<div className="input-group">
<label>{t('logs.event_wind_direction')}</label>
<input
@@ -996,9 +1026,7 @@ export default function LogEntryEditor({ entryId, logbookId, onBack }: LogEntryE
disabled={saving || weatherLoading}
/>
</div>
</div>
<div className="form-grid mb-4">
<div className="input-group">
<label>{t('logs.event_wind_strength')}</label>
<input
+3 -1
View File
@@ -87,6 +87,8 @@
"event_weather": "Wetter",
"event_log": "Logge (sm)",
"event_gps": "GPS-Position",
"event_location": "Ort / Hafen",
"event_location_placeholder": "z. B. Kiel",
"event_remarks": "Bemerkungen / Vorkommnisse",
"gps_btn": "GPS-Koordinaten abrufen",
"weather_btn": "OpenWeatherMap Wetter abrufen",
@@ -176,7 +178,7 @@
"no_key": "Bitte hinterlegen Sie Ihren OpenWeatherMap API-Schlüssel in den Einstellungen, um Wetterdaten abzurufen.",
"weather_success": "Wetterdaten erfolgreich abgerufen!",
"weather_error": "Wetterdatenabruf fehlgeschlagen. Überprüfen Sie den API-Schlüssel und die Verbindung.",
"gps_error": "Bitte ermitteln Sie zuerst die GPS-Koordinaten.",
"gps_error": "Bitte geben Sie einen Ort an oder ermitteln Sie die GPS-Koordinaten.",
"theme_title": "Design-Anpassung",
"theme_label": "Design-Stil der App",
"theme_auto": "Automatisch (OS-Erkennung)",
+3 -1
View File
@@ -87,6 +87,8 @@
"event_weather": "Weather",
"event_log": "Log (nm)",
"event_gps": "GPS Position",
"event_location": "Location / Port",
"event_location_placeholder": "e.g. Kiel",
"event_remarks": "Remarks / Events",
"gps_btn": "Get GPS Location",
"weather_btn": "Fetch OpenWeatherMap Weather",
@@ -176,7 +178,7 @@
"no_key": "Please set your OpenWeatherMap API Key in settings to enable weather auto-fill.",
"weather_success": "Weather details fetched successfully!",
"weather_error": "Failed to fetch weather. Check your API key and connection.",
"gps_error": "Please fetch GPS coordinates first.",
"gps_error": "Please enter a location or fetch GPS coordinates first.",
"theme_title": "UI Customization",
"theme_label": "Application Style / Theme",
"theme_auto": "Auto (OS Detect)",