feat(weather): allow fetching OpenWeatherMap weather by location name and auto-populating GPS coordinates
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)",
|
||||
|
||||
@@ -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)",
|
||||
|
||||
Reference in New Issue
Block a user