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 [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
|
||||||
|
|||||||
@@ -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)",
|
||||||
|
|||||||
@@ -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)",
|
||||||
|
|||||||
Reference in New Issue
Block a user