fix: type errors

This commit is contained in:
terraputix
2026-02-15 15:42:20 +01:00
parent be0f7f822d
commit 386e814001
9 changed files with 569 additions and 465 deletions
+87 -69
View File
@@ -25,7 +25,7 @@
const params = urlHashStore({
latitude: [$storedLocation.latitude],
longitude: [$storedLocation.longitude],
models: 'best_match',
models: ['best_match'],
...defaultParameters
});
@@ -96,7 +96,7 @@
const maxX = 10000;
const maxY = 500;
const deltaX = 10000 / hourly.variables(0)?.valuesArray()?.length;
const deltaX = 10000 / (hourly.variables(0)?.valuesArray()?.length || 1);
const ctx = canvasElement?.getContext('2d');
if (ctx) {
@@ -119,10 +119,10 @@
// create canvas
daylight(ctx, config, hourlyTime);
raster(ctx, config, hourlyTime, today, canvasElement);
raster(ctx, config, hourlyTime, today, canvasElement!);
tempGradient(ctx, config, hourlyTemps, $params.temperature_unit);
cloudCover(ctx, config, hourlyCloudCover, canvasElement);
precip(ctx, config, hourlyPrecip, canvasElement);
cloudCover(ctx, config, hourlyCloudCover, canvasElement!);
precip(ctx, config, hourlyPrecip, canvasElement!);
}
return {
@@ -134,7 +134,7 @@
values: hourly
.variables(2)
?.valuesArray()
?.map((t) => t.toFixed(1))
?.map((t) => Number(t.toFixed(1)))
},
{
id: 1,
@@ -143,7 +143,7 @@
values: hourly
.variables(0)
?.valuesArray()
?.map((p) => p.toFixed(1))
?.map((p) => Number(p.toFixed(1)))
},
{
id: 2,
@@ -152,7 +152,7 @@
values: hourly
.variables(1)
?.valuesArray()
?.map((p) => p.toFixed(0))
?.map((p) => Number(p.toFixed(0)))
},
{
id: 3,
@@ -161,7 +161,7 @@
values: hourly
.variables(4)
?.valuesArray()
?.map((p) => p.toFixed(0))
?.map((p) => Number(p.toFixed(0)))
},
{
id: 4,
@@ -170,7 +170,7 @@
values: hourly
.variables(7)
?.valuesArray()
?.map((p) => p.toFixed(0))
?.map((p) => Number(p.toFixed(0)))
}
],
entriesLength: hourly.variables(0)?.valuesArray()?.length,
@@ -237,17 +237,18 @@
let winddir = true;
entries = 6;
let scrollDiv: HTMLElement = $state();
let scrollDiv: HTMLElement | undefined = $state();
let tableCells;
const switchDay = (date: SvelteDate, index: number) => {
const switchDay = (date: Date, index: number) => {
selectedDay = date;
tableCells = document.querySelectorAll('td.time');
for (let tableCell of tableCells) {
if (Number(tableCell.dataset['date']) === selectedDay.getDate()) {
scrollDiv.scrollTo({ left: tableCell.offsetLeft - 110, behavior: 'smooth' });
const htmlCell = tableCell as HTMLElement;
if (Number(htmlCell.dataset['date']) === selectedDay.getDate()) {
scrollDiv?.scrollTo({ left: htmlCell.offsetLeft - 110, behavior: 'smooth' });
break;
}
}
@@ -259,34 +260,35 @@
setTimeout(() => {
tableCells = document.querySelectorAll('td.time');
for (let tableCell of tableCells) {
if (Number(tableCell.dataset['date']) === selectedDay.getDate()) {
scrollDiv.scrollTo({ left: tableCell.offsetLeft - 110 });
const htmlCell = tableCell as HTMLElement;
if (Number(htmlCell.dataset['date']) === selectedDay.getDate()) {
scrollDiv?.scrollTo({ left: htmlCell.offsetLeft - 110 });
break;
}
}
}, 150);
document.onkeydown = (e) => {
if (!scrollDiv === document.activeElement || !scrollDiv.contains(document.activeElement)) {
if (scrollDiv !== document.activeElement && !scrollDiv?.contains(document.activeElement)) {
if (e.key === 'ArrowLeft') {
if (selectedDay.getDate() >= today.getDate()) {
let newDate = new SvelteDate();
let newDate = new Date();
newDate.setDate(selectedDay.getDate() - 1);
switchDay(newDate);
switchDay(newDate, selectedDayIndex - 1);
}
}
if (e.key === 'ArrowRight') {
if (selectedDay.getDate() <= today.getDate() + 4) {
let newDate = new SvelteDate();
let newDate = new Date();
newDate.setDate(selectedDay.getDate() + 1);
switchDay(newDate);
switchDay(newDate, selectedDayIndex + 1);
}
}
}
};
});
let modelSelected = $derived(models.find((mo) => String(mo.value) === $params.models));
let modelSelected = $derived(models.find((mo) => String(mo.value) === $params.models?.[0]));
// let modelSelectedValue = $derived($params.models[0]);
//
</script>
@@ -308,7 +310,9 @@
{#await weatherDaily then wd}
{#each wd.daily.time as time, index (index)}
{@const selected = time.getDate() === selectedDay.getDate()}
{#if !isNaN(wd.daily.temperature_2m_max.values(index).toFixed(1))}
{#if wd.daily.temperature_2m_max.values(index) != null && !isNaN(Number(wd.daily.temperature_2m_max
.values(index)!
.toFixed(1)))}
<button
style="transition: 300ms; min-width: 13%; {selected ? 'transform: scale(1.025)' : ''}"
class="cursor-pointer"
@@ -338,23 +342,23 @@
<svg class="fill-foreground" width="60px" height="60px">
<use
xlink:href="/images/weather-icons/wi-day-{weatherCodes[
wd.daily.weather_code.values(index)
(wd.daily.weather_code.values(index) ?? 0) as number
]}.svg#Layer_1"
></use>
</svg>
</div>
<div
class="weather-temp-max flex min-w-[65px] justify-center rounded-t p-1 text-sm"
style={`background-color: ${getColor(wd.daily.temperature_2m_max.values(index).toFixed(0), $params.temperature_unit)}; color: ${wd.daily.temperature_2m_min.values(index) < ($params.temperature_unit === 'celsius' ? 4 : 7) || wd.daily.temperature_2m_min.values(index) >= ($params.temperature_unit === 'celsius' ? 30 : 104) ? 'white' : 'black'}`}
style={`background-color: ${getColor((wd.daily.temperature_2m_max.values(index) ?? 0).toFixed(0), $params.temperature_unit)}; color: ${(wd.daily.temperature_2m_min.values(index) ?? 0) < ($params.temperature_unit === 'celsius' ? 4 : 7) || (wd.daily.temperature_2m_min.values(index) ?? 0) >= ($params.temperature_unit === 'celsius' ? 30 : 104) ? 'white' : 'black'}`}
>
{wd.daily.temperature_2m_max.values(index).toFixed(1)}
{wd.daily.temperature_2m_max.values(index)?.toFixed(1)}
{$params.temperature_unit === 'celsius' ? '°C' : '°F'}
</div>
<div
class="weather-temp-min flex min-w-[65px] justify-center rounded-b p-1 text-sm"
style={`background: ${getColor(wd.daily.temperature_2m_min.values(index).toFixed(0), $params.temperature_unit)}; color: ${wd.daily.temperature_2m_min.values(index) < ($params.temperature_unit === 'celsius' ? 4 : 7) || wd.daily.temperature_2m_min.values(index) >= ($params.temperature_unit === 'celsius' ? 30 : 104) ? 'white' : 'black'}`}
style={`background: ${getColor((wd.daily.temperature_2m_min.values(index) ?? 0).toFixed(0), $params.temperature_unit)}; color: ${(wd.daily.temperature_2m_min.values(index) ?? 0) < ($params.temperature_unit === 'celsius' ? 4 : 7) || (wd.daily.temperature_2m_min.values(index) ?? 0) >= ($params.temperature_unit === 'celsius' ? 30 : 104) ? 'white' : 'black'}`}
>
{wd.daily.temperature_2m_min.values(index).toFixed(1)}
{wd.daily.temperature_2m_min.values(index)?.toFixed(1)}
{$params.temperature_unit === 'celsius' ? '°C' : '°F'}
</div>
<div class="mt-2 flex items-center justify-center gap-1">
@@ -369,7 +373,7 @@
</div>
</div>
{Number(wd.daily.sunshine_duration.values(index) / 3600).toFixed(0)}h
{Number((wd.daily.sunshine_duration.values(index) ?? 0) / 3600).toFixed(0)}h
</div>
<div class="mt-1 flex items-center justify-center">
<div class="relative flex h-6 w-6 items-center justify-center">
@@ -442,8 +446,9 @@
data-time={weather.hourlyTime[index].getHours() + ':00'}
style="font-size: 11px; position: absolute; bottom: {188 +
27 * entries}px; left:{111 +
(5000 / weather.entriesLength) * index}px; min-width: {5000 /
weather.entriesLength}px; max-width: {5000 / weather.entriesLength}px;"
(5000 / (weather.entriesLength || 1)) * index}px; min-width: {5000 /
(weather.entriesLength || 1)}px; max-width: {5000 /
(weather.entriesLength || 1)}px;"
>{weather.hourlyTime[index].getHours() < 10 ? '0' : ''}{weather.hourlyTime[
index
].getHours()}</td
@@ -467,16 +472,17 @@
0.8 * 200 -
0.54 *
200 *
((maxTemp - weather.entries[0].values[index]) / diffTemp)}px; left:{116 +
(5000 / weather.entriesLength) * index}px; min-width: {5000 /
weather.entriesLength}px; max-width: {5000 / weather.entriesLength}px;"
((maxTemp! - weather.entries[0].values![index]) / diffTemp!)}px; left:{116 +
(5000 / (weather.entriesLength || 1)) * index}px; min-width: {5000 /
(weather.entriesLength || 1)}px; max-width: {5000 /
(weather.entriesLength || 1)}px;"
><svg class="fill-foreground {now ? 'scale-125' : ''}" width="20px" height="20px">
<use
class="stroke-2"
xlink:href="/images/weather-icons/wi-{weather.hourlyTime[index].getHours() >
6 && weather.hourlyTime[index].getHours() < 21
? 'day'
: 'night'}-{weatherCodes[weatherCodesHourly[index]]}.svg#Layer_1"
: 'night'}-{weatherCodes[weatherCodesHourly![index] as number]}.svg#Layer_1"
></use>
</svg></td
>
@@ -491,9 +497,9 @@
>Temp graph</th
>
{#each weather.indexes as index, j (j)}
{@const temp = weather.entries[0].values[index]}
{@const temp = weather.entries?.[0]?.values?.[index]}
{#if !isNaN(temp)}
{#if temp !== undefined && !isNaN(temp)}
<td
class={weather.hourlyTime[index].getDate() === today.getDate() &&
weather.hourlyTime[index].getHours() === today.getHours()
@@ -502,10 +508,10 @@
style="position: absolute; bottom: {27.5 * entries -
49 +
0.8 * 200 -
0.55 * 200 * ((maxTemp - temp) / diffTemp)}px; left:{111 +
(5000 / weather.entriesLength) * index}px; min-width: {5000 /
weather.entriesLength}px; max-width: {5000 / weather.entriesLength}px;"
>{temp.toFixed(0)}</td
0.55 * 200 * ((maxTemp! - temp!) / diffTemp!)}px; left:{111 +
(5000 / (weather.entriesLength || 1)) * index}px; min-width: {5000 /
(weather.entriesLength || 1)}px; max-width: {5000 /
(weather.entriesLength || 1)}px;">{temp?.toFixed(0)}</td
>
{/if}
{/each}
@@ -520,49 +526,49 @@
>
{#each weather.indexes as index, j (j)}
{#if !isNaN(entry.values[index])}
{#if entry.values && !isNaN(entry.values[index])}
<td
class="border-r border-border {weather.hourlyTime[index].getDate() ===
today.getDate() && weather.hourlyTime[index].getHours() === today.getHours()
? 'now'
: ''}"
style="min-width: {5000 / weather.entriesLength}px; max-width: {5000 /
weather.entriesLength}px;
style="min-width: {5000 / (weather.entriesLength || 1)}px; max-width: {5000 /
(weather.entriesLength || 1)}px;
{entry.name === 'temperature_2m'
? 'background: ' +
getColor(
weather.entries[0].values[index].toFixed(0),
weather.entries[0].values![index].toFixed(0),
$params.temperature_unit
)
: ''};
{entry.name === 'temperature_2m'
? 'color: ' +
(weather.entries[0].values[index] <
(weather.entries[0].values![index] <
($params.temperature_unit === 'celsius' ? -13 : 7) ||
weather.entries[0].values[index] >=
weather.entries[0].values![index] >=
($params.temperature_unit === 'celsius' ? 40 : 104)
? 'white'
: 'black')
: ''};
{entry.name === 'precipitation_probability'
? 'background: rgba(0, 0, 230,' +
weather.entries[2].values[index] / 120 +
weather.entries[2].values![index] / 120 +
')'
: ''};
{entry.name === 'precipitation_probability'
? 'color: ' +
(weather.entries[2].values[index] > 50
(weather.entries[2].values![index] > 50
? 'white'
: 'hsl(var(--foreground)')
: ''};
{entry.name === 'relative_humidity_2m'
? 'background: rgba(0, 240, 240,' +
weather.entries[4].values[index] ** 3.8 / 10 ** 8.2 +
weather.entries[4].values![index] ** 3.8 / 10 ** 8.2 +
')'
: ''};"
>{entry.name === 'precipitation' || entry.name === 'temperature_2m'
? entry.values[index].toFixed(1)
: entry.values[index]}</td
? entry.values![index].toFixed(1)
: entry.values![index]}</td
>
{/if}
{/each}
@@ -578,16 +584,16 @@
>Wind Dir.</th
>
{#each weather.indexes as index, j (j)}
{#if !isNaN(weather.windDirections[index])}
{#if weather.windDirections && !isNaN(weather.windDirections[index])}
<td
class="border-r border-border {weather.hourlyTime[index].getDate() ===
today.getDate() && weather.hourlyTime[index].getHours() === today.getHours()
? 'now'
: ''}"
style="transform: rotate({weather.windDirections[
style="transform: rotate({weather.windDirections![
index
]}deg);min-width: {5000 / weather.entriesLength}px; max-width: {5000 /
weather.entriesLength}px;"
]}deg);min-width: {5000 / (weather.entriesLength || 1)}px; max-width: {5000 /
(weather.entriesLength || 1)}px;"
><svg class="fill-foreground" width="25px" height="25px">
<use xlink:href="/images/weather-icons/wi-direction-down.svg#Layer_1"></use>
</svg></td
@@ -621,20 +627,32 @@
<div>
<div class="mt-6 flex gap-6 md:mt-12">
<div class="relative w-1/2">
<Select.Root name="model_selection" type="single" bind:value={$params.models}>
<Select.Trigger
aria-label="Forecast days input"
class="h-12 cursor-pointer pt-6 [&_svg]:mb-3">{modelSelected?.label}</Select.Trigger
{#if $params.models && $params.models.length > 0}
{@const modelValue = $params.models[0]}
<Select.Root
name="model_selection"
type="single"
value={modelValue}
onValueChange={(val) => {
if ($params.models && val) {
$params.models = [val];
}
}}
>
<Select.Content preventScroll={false} class="border-border">
{#each models as mo (mo.value)}
<Select.Item class="cursor-pointer" value={mo.value}>{mo.label}</Select.Item>
{/each}
</Select.Content>
<Label class="absolute top-[0.35rem] left-2 z-10 px-1 text-xs text-muted-foreground"
>Weather model</Label
>
</Select.Root>
<Select.Trigger
aria-label="Forecast days input"
class="h-12 cursor-pointer pt-6 [&_svg]:mb-3">{modelSelected?.label}</Select.Trigger
>
<Select.Content preventScroll={false} class="border-border">
{#each models as mo (mo.value)}
<Select.Item class="cursor-pointer" value={mo.value}>{mo.label}</Select.Item>
{/each}
</Select.Content>
<Label class="absolute top-[0.35rem] left-2 z-10 px-1 text-xs text-muted-foreground"
>Weather model</Label
>
</Select.Root>
{/if}
</div>
</div>
</div>