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