This commit is contained in:
Vincent van der Wal
2026-07-19 14:57:26 +02:00
parent 9e1944396e
commit 6d81af8df5
26 changed files with 408 additions and 466 deletions
+58 -38
View File
@@ -12,23 +12,28 @@
import MeteogramCharts from './MeteogramCharts.svelte';
import ModelSelector from './ModelSelector.svelte';
import type { GeoLocation } from '$lib/stores/settings';
import type { PageData } from './$types';
import type { FetchedDaily, FetchedHourly } from './types';
let { data }: { data: PageData } = $props();
let params = $state({
latitude: [$storedLocation.latitude],
longitude: [$storedLocation.longitude],
models: ['best_match'],
...defaultParameters
});
let location = $state<GeoLocation>($storedLocation);
storedLocation.subscribe((value) => {
location = value;
// the URL is the source of truth: location comes from the load function,
// which is also correct on hydrated prerendered pages. The persisted store
// only mirrors it so the header and bare /weather/* redirects follow along.
let location = $derived(data.location);
$effect(() => {
storedLocation.set(data.location);
});
let mounted = $state(false);
let loading = $state(true);
let loadError = $state<string | null>(null);
let requestVersion = 0;
const selectedDay = new SvelteDate();
@@ -52,40 +57,47 @@
if (!mounted || !loc || !modelList?.length) return;
const loadData = async () => {
loading = true;
// versioned so a slow stale response can never overwrite a newer one
const version = ++requestVersion;
loading = true;
loadError = null;
const result: WeekForecastResult = await fetchWeekForecast({
latitude: loc.latitude!,
longitude: loc.longitude!,
model: modelList[0],
temperature_unit: params.temperature_unit as 'celsius' | 'fahrenheit',
wind_speed_unit: params.wind_speed_unit as 'kmh' | 'ms' | 'mph' | 'kn',
precipitation_unit: params.precipitation_unit as 'mm' | 'inch',
forecast_days: 7,
past_days: 0,
timezone: loc.timezone
fetchWeekForecast({
latitude: loc.latitude!,
longitude: loc.longitude!,
model: modelList[0],
temperature_unit: params.temperature_unit as 'celsius' | 'fahrenheit',
wind_speed_unit: params.wind_speed_unit as 'kmh' | 'ms' | 'mph' | 'kn',
precipitation_unit: params.precipitation_unit as 'mm' | 'inch',
forecast_days: 7,
past_days: 0,
timezone: loc.timezone
})
.then((result: WeekForecastResult) => {
if (version !== requestVersion) return;
fetchedHourly = {
hourly: result.hourly,
utc_offset_seconds: result.utcOffsetSeconds,
timezone: result.timezone,
timestamps: result.hourlyTimestamps,
hourlyDates: result.hourlyDates,
markAreas: result.markAreas
};
fetchedDaily = {
daily: result.daily,
timezone: result.timezone,
dailyDates: result.dailyDates
};
loading = false;
})
.catch((err: unknown) => {
if (version !== requestVersion) return;
loadError = err instanceof Error ? err.message : String(err);
loading = false;
});
fetchedHourly = {
hourly: result.hourly,
utc_offset_seconds: result.utcOffsetSeconds,
timezone: result.timezone,
timestamps: result.hourlyTimestamps,
hourlyDates: result.hourlyDates,
markAreas: result.markAreas
};
fetchedDaily = {
daily: result.daily,
timezone: result.timezone,
dailyDates: result.dailyDates
};
loading = false;
};
loadData();
});
</script>
@@ -97,6 +109,14 @@
<div class="week-page">
<div class="weather-content" style="min-height: 50vh">
{#if loadError}
<div
class="mb-4 rounded-md border border-destructive/50 bg-destructive/10 px-4 py-3 text-sm text-destructive"
>
Failed to load weather data: {loadError}
</div>
{/if}
<DailyCards daily={fetchedDaily} {selectedDay} units={params} onSelectDay={switchDay} />
{#if fetchedHourly && fetchedDaily}