From 386e8140019ccddb6a955e5ebe4a3c4a140eda8c Mon Sep 17 00:00:00 2001 From: terraputix Date: Sun, 15 Feb 2026 15:42:20 +0100 Subject: [PATCH] fix: type errors --- src/lib/stores/url-hash-store.ts | 41 +- src/routes/weather/+layout.svelte | 13 +- src/routes/weather/+page.ts | 2 +- src/routes/weather/14-day/+page.svelte | 384 +++++++++-------- src/routes/weather/compare/+page.svelte | 404 +++++++++--------- src/routes/weather/utils/weather-codes.ts | 4 +- src/routes/weather/week/+page.ts | 2 +- .../weather/week/[location]/+page.svelte | 156 ++++--- src/routes/weather/week/[location]/+page.ts | 28 +- 9 files changed, 569 insertions(+), 465 deletions(-) diff --git a/src/lib/stores/url-hash-store.ts b/src/lib/stores/url-hash-store.ts index 676ab4c..e890a4c 100644 --- a/src/lib/stores/url-hash-store.ts +++ b/src/lib/stores/url-hash-store.ts @@ -1,10 +1,45 @@ -import { writable } from 'svelte/store'; +import { type Writable, writable } from 'svelte/store'; + +export interface UrlHashParams { + latitude?: number[]; + longitude?: number[]; + daily?: string[]; + hourly?: string[]; + models?: string[]; + current?: string[]; + minutely_15?: string[]; + timezone?: string; + location_mode?: string; + csv_coordinates?: string; + time_mode?: string; + past_days?: string; + forecast_days?: string; + end_date?: string; + start_date?: string; + past_hours?: string; + cell_selection?: string; + forecast_hours?: string; + past_minutely_15?: string; + temporal_resolution?: string; + forecast_minutely_15?: string; + tilt?: string; + azimuth?: string; + timeformat?: string; + wind_speed_unit?: string; + temperature_unit?: string; + precipitation_unit?: string; + [key: string]: unknown; +} + +export interface UrlHashStore extends Writable { + updateParam: (key: string, value: unknown) => void; +} // Placeholder function for urlHashStore // In a real application, this would handle URL hash parameters // and return a Svelte store that reflects those parameters. -export function urlHashStore(initialValue: Record) { - const { subscribe, set, update } = writable(initialValue); +export function urlHashStore(initialValue: UrlHashParams): UrlHashStore { + const { subscribe, set, update } = writable(initialValue); // In a full implementation, you would add logic here to: // 1. Read the URL hash on initialization diff --git a/src/routes/weather/+layout.svelte b/src/routes/weather/+layout.svelte index 7cc664c..c6723cb 100644 --- a/src/routes/weather/+layout.svelte +++ b/src/routes/weather/+layout.svelte @@ -16,9 +16,16 @@ let { children }: Props = $props(); + interface CurrentWeather { + current: { + temperature_2m: number; + weather_code: number; + }; + } + let location = $state(get(storedLocation)); let mounted = $state(false); - let currentWeather = $state(null); + let currentWeather = $state(null); // Subscribe to location changes storedLocation.subscribe((value) => { @@ -47,8 +54,8 @@ } }; - const getWeatherIcon = (code) => { - const iconMap = { + const getWeatherIcon = (code: number): string => { + const iconMap: Record = { 0: '☀️', 1: '🌤️', 2: '⛅', diff --git a/src/routes/weather/+page.ts b/src/routes/weather/+page.ts index e65096f..9c6e182 100644 --- a/src/routes/weather/+page.ts +++ b/src/routes/weather/+page.ts @@ -1,6 +1,6 @@ import { redirect } from '@sveltejs/kit'; -import type { PageLoad } from '$types'; +import type { PageLoad } from './$types'; export const prerender = true; diff --git a/src/routes/weather/14-day/+page.svelte b/src/routes/weather/14-day/+page.svelte index 2c91724..e248a53 100644 --- a/src/routes/weather/14-day/+page.svelte +++ b/src/routes/weather/14-day/+page.svelte @@ -16,7 +16,7 @@ let node: HTMLElement; let chart: any; - let Highcharts = $state(null); + let Highcharts = $state(null); let showLegend = $state(false); let averageOnly = $state(false); @@ -41,221 +41,230 @@ if (dev) { // const HighchartsDebugger = await import('highcharts/modules/debugger'); // HighchartsDebugger.default(Highcharts); - const Debugger = (await import('highcharts/es-modules/Extensions/Debugger/Debugger.js')) - .default; - const ErrorMessages = ( - await import('highcharts/es-modules/Extensions/Debugger/ErrorMessages.js') + const Debugger = ( + await import('highcharts/es-modules/Extensions/Debugger/Debugger.js' as any) ).default; - Highcharts.errorMessages = ErrorMessages; - Debugger.compose(Highcharts.Chart); + const ErrorMessages = ( + await import('highcharts/es-modules/Extensions/Debugger/ErrorMessages.js' as any) + ).default; + if (Highcharts) { + (Highcharts as any).errorMessages = ErrorMessages; + Debugger.compose(Highcharts.Chart); + } } }); - $effect(async () => { - count = 0; - if (Highcharts) { - node.replaceChildren([]); + $effect(() => { + const loadData = async () => { + count = 0; + if (Highcharts) { + node.replaceChildren(); - const dataDaily = await fetch( - `https://api.open-meteo.com/v1/forecast?latitude=${location.latitude}&longitude=${location.longitude}&timeformat=unixtime&daily=sunset,sunrise&forecast_days=14` - ); - const wd = await dataDaily.json(); + const dataDaily = await fetch( + `https://api.open-meteo.com/v1/forecast?latitude=${location.latitude}&longitude=${location.longitude}&timeformat=unixtime&daily=sunset,sunrise&forecast_days=14` + ); + const wd = await dataDaily.json(); - const dataReq = await fetch( - `https://ensemble-api.open-meteo.com/v1/ensemble?latitude=${location.latitude}&longitude=${location.longitude}&hourly=${$params.hourly.join(',')}&models=${$params.models.join(',')}&timeformat=unixtime&forecast_days=14` - ); - const data = await dataReq.json(); + const dataReq = await fetch( + `https://ensemble-api.open-meteo.com/v1/ensemble?latitude=${location.latitude}&longitude=${location.longitude}&hourly=${$params.hourly?.join(',') || ''}&models=${$params.models?.join(',') || ''}&timeformat=unixtime&forecast_days=14` + ); + const data = await dataReq.json(); - let plotBands: any = []; - if ('daily' in wd && 'sunrise' in wd.daily && 'sunset' in wd.daily) { - let rise = wd.daily.sunrise; - let set = wd.daily.sunset; - plotBands = rise.map(function (r, i) { - return { - color: 'rgba(255, 255, 194, 0.5)', - from: (r + data.utc_offset_seconds) * 1000, - to: (set[i] + data.utc_offset_seconds) * 1000 - }; - }); - } + let plotBands: any = []; + if ('daily' in wd && 'sunrise' in wd.daily && 'sunset' in wd.daily) { + let rise = wd.daily.sunrise; + let set = wd.daily.sunset; + plotBands = rise.map(function (r: any, i: number) { + return { + color: 'rgba(255, 255, 194, 0.5)', + from: (r + data.utc_offset_seconds) * 1000, + to: (set[i] + data.utc_offset_seconds) * 1000 + }; + }); + } - let minValues = new Array(data.hourly.time.length).fill(undefined); - let maxValues = new Array(data.hourly.time.length).fill(undefined); + let minValues = new Array(data.hourly.time.length).fill(undefined); + let maxValues = new Array(data.hourly.time.length).fill(undefined); - for (let variable of $params.hourly) { - const chartDiv = document.createElement('div'); + for (let variable of $params.hourly || []) { + const chartDiv = document.createElement('div'); - let unit; + let unit; - let hourly_starttime = (data.hourly.time[0] + data.utc_offset_seconds) * 1000; - let pointInterval = (data.hourly.time[1] - data.hourly.time[0]) * 1000; + let hourly_starttime = (data.hourly.time[0] + data.utc_offset_seconds) * 1000; + let pointInterval = (data.hourly.time[1] - data.hourly.time[0]) * 1000; - const series = []; - let average = new Array(data.hourly.time.length).fill(0); - let averageCount = new Array(data.hourly.time.length).fill(0); + const series = []; + let average = new Array(data.hourly.time.length).fill(0); + let averageCount = new Array(data.hourly.time.length).fill(0); - for (let [model, values] of Object.entries(data.hourly)) { - if (model === 'time') { - continue; - } - if (model.startsWith(variable)) { - for (let [index, val] of values.entries()) { - if (val) { - let avVal = average[index]; - average[index] = avVal + val; - averageCount[index]++; + for (let [model, values] of Object.entries(data.hourly)) { + if (model === 'time') { + continue; + } + if (model.startsWith(variable)) { + for (let [index, val] of (values as any[]).entries()) { + if (val) { + let avVal = average[index]; + average[index] = avVal + val; + averageCount[index]++; - if (minValues[index] > val || minValues[index] === undefined) { - minValues[index] = val; - } - if (maxValues[index] < val || maxValues[index] === undefined) { - maxValues[index] = val; + if (minValues[index] > val || minValues[index] === undefined) { + minValues[index] = val; + } + if (maxValues[index] < val || maxValues[index] === undefined) { + maxValues[index] = val; + } } } - } - unit = data.hourly_units[model]; + unit = data.hourly_units[model]; + } } - } - for (let [index, val] of average.entries()) { - average[index] = Math.round((val / averageCount[index]) * 10) / 10; - } + for (let [index, val] of average.entries()) { + average[index] = Math.round((val / averageCount[index]) * 10) / 10; + } - const minMax = []; - for (let [index, min] of minValues.entries()) { - minMax.push([min, maxValues[index]]); - } + const minMax = []; + for (let [index, min] of minValues.entries()) { + minMax.push([min, maxValues[index]]); + } - series.push({ - name: 'temperature_2m_spread', - data: minMax, - type: 'arearange', - tooltip: { - valueSuffix: ' ' + unit - }, - pointStart: hourly_starttime, - pointInterval: pointInterval, - className: 'highcharts-spread-series' - }); + series.push({ + name: 'temperature_2m_spread', + data: minMax, + type: 'arearange', + tooltip: { + valueSuffix: ' ' + unit + }, + pointStart: hourly_starttime, + pointInterval: pointInterval, + className: 'highcharts-spread-series' + }); - series.push({ - name: variable + '_average', - data: average, - dashStyle: 'ShortDashDot', - color: '#5e5e5e', - type: - unit == 'mm' || unit == 'cm' || unit == 'inch' || unit == 'MJ/m²' ? 'column' : 'spline', - tooltip: { - valueSuffix: ' ' + unit - }, - lineWidth: 4, - states: { - hover: { - lineWidth: 6 - } - }, - pointStart: hourly_starttime, - pointInterval: pointInterval, - className: 'highcharts-average-series' - }); - - new Highcharts.Chart(chartDiv, { - credits: { - text: count === $params.hourly.length - 1 ? 'Open-Meteo.com' : '', - href: 'http://open-meteo.com' - }, - - chart: { - height: showLegend ? '400px' : '300px', - styledMode: true, - marginLeft: '50', - marginRight: 0 - }, - - lang: { - locale: 'en-GB' - }, - - title: { - text: count === 0 ? 'Model Spread' : '', - align: 'left' - }, - - subtitle: { - text: - count === 0 - ? `Compare ${$params.hourly.join(', ')} in models: ` + - $params.models.join(', ') + - '' - : '', - align: 'left' - }, - - yAxis: { - title: { - text: unit - } - }, - - xAxis: { - type: 'datetime', - plotLines: [ - { - value: Date.now() + data.utc_offset_seconds * 1000, - color: 'red', - width: 2 - } - ], - plotBands: plotBands - }, - - plotOptions: { - spline: { - lineWidth: 2, - states: { - hover: { - lineWidth: 3 - } - }, - marker: { - enabled: false + series.push({ + name: variable + '_average', + data: average, + dashStyle: 'ShortDashDot', + color: '#5e5e5e', + type: + unit == 'mm' || unit == 'cm' || unit == 'inch' || unit == 'MJ/m²' + ? 'column' + : 'spline', + tooltip: { + valueSuffix: ' ' + unit + }, + lineWidth: 4, + states: { + hover: { + lineWidth: 6 } }, - column: { - pointWidth: 5 - } - }, + pointStart: hourly_starttime, + pointInterval: pointInterval, + className: 'highcharts-average-series' + }); - legend: { - enabled: showLegend, - layout: 'horizontal', - align: 'center', - verticalAlign: 'bottom' - }, + new Highcharts!.Chart({ + chart: { + renderTo: chartDiv, + height: showLegend ? '400px' : '300px', + styledMode: true, + marginLeft: 50, + marginRight: 0 + }, - series: series, + credits: { + text: count === ($params.hourly?.length || 0) - 1 ? 'Open-Meteo.com' : '', + href: 'http://open-meteo.com' + }, - responsive: { - rules: [ - { - condition: { - maxWidth: 800 - } + lang: { + locale: 'en-GB' + }, + + title: { + text: count === 0 ? 'Model Spread' : '', + align: 'left' + }, + + subtitle: { + text: + count === 0 + ? `Compare ${$params.hourly?.join(', ') || ''} in models: ` + + ($params.models?.join(', ') || '') + + '' + : '', + align: 'left' + }, + + yAxis: { + title: { + text: unit } - ] - }, + }, - tooltip: { - shared: true, - animation: false - } - }); + xAxis: { + type: 'datetime', + plotLines: [ + { + value: Date.now() + data.utc_offset_seconds * 1000, + color: 'red', + width: 2 + } + ], + plotBands: plotBands + }, - count++; - node.appendChild(chartDiv); + plotOptions: { + spline: { + lineWidth: 2, + states: { + hover: { + lineWidth: 3 + } + }, + marker: { + enabled: false + } + }, + column: { + pointWidth: 5 + } + }, + + legend: { + enabled: showLegend, + layout: 'horizontal', + align: 'center', + verticalAlign: 'bottom' + }, + + series: series as any, + + responsive: { + rules: [ + { + condition: { + maxWidth: 800 + } + } + ] + }, + + tooltip: { + shared: true, + animation: false + } + }); + + count++; + node.appendChild(chartDiv); + } } - } + }; + loadData(); }); onDestroy(() => { @@ -266,7 +275,10 @@ -
+