From 7f7f710fe84eca8fbcadc9566f56942f63224d36 Mon Sep 17 00:00:00 2001 From: Alex Lebens Date: Wed, 11 Feb 2026 14:43:13 -0600 Subject: [PATCH] feat: make weather fetching dynamic --- src/components/Footer.astro | 38 ++++++++-------- .../ui/sections/WeatherSection.astro | 6 +-- src/lib/directusTypes.ts | 1 + src/pages/index.astro | 11 ++++- src/support/weather.ts | 44 +++++++++---------- 5 files changed, 54 insertions(+), 46 deletions(-) diff --git a/src/components/Footer.astro b/src/components/Footer.astro index 0cf9156..c97ae49 100644 --- a/src/components/Footer.astro +++ b/src/components/Footer.astro @@ -108,7 +108,23 @@ const currentYear = new Date().getFullYear(); © {currentYear} All rights reserved.

-
+
+

+ Weather provided by +

+ + + Open-Meteo. + + + +
+ Built with - - - - - - Astro - - + + Astro.
diff --git a/src/components/ui/sections/WeatherSection.astro b/src/components/ui/sections/WeatherSection.astro index 31a9aba..e1452f7 100644 --- a/src/components/ui/sections/WeatherSection.astro +++ b/src/components/ui/sections/WeatherSection.astro @@ -1,8 +1,8 @@ --- import { getFiveDayForecast } from '@support/weather'; -const { latitude = "44.95", longitude = "-93.09", cityName = "St. Paul, Minnesota" } = Astro.props; -const { forecastDays, error } = await getFiveDayForecast(latitude, longitude); +const { latitude = "44.95", longitude = "-93.09", cityName = "St. Paul, Minnesota", timezone = "America/Chicago" } = Astro.props; +const { forecastDays, error } = await getFiveDayForecast(latitude, longitude, timezone); const borderClasses = 'border border-neutral-100 dark:border-stone-500/20'; const bgColorClasses = 'bg-neutral-100/80 hover:bg-neutral-100 dark:bg-neutral-800/60 dark:hover:bg-neutral-800/90'; @@ -16,7 +16,7 @@ const shadowClasses = 'shadow-xs hover:shadow-md dark:shadow-md dark:hover:shado

- 5 day forecast for {cityName} + Five day forecast for {cityName}

diff --git a/src/lib/directusTypes.ts b/src/lib/directusTypes.ts index eb51dab..643b46a 100644 --- a/src/lib/directusTypes.ts +++ b/src/lib/directusTypes.ts @@ -28,6 +28,7 @@ export type Weather = { location: string; latitude: string; longitude: string; + timezone: string; } export type Post = { diff --git a/src/pages/index.astro b/src/pages/index.astro index 9f5a4b0..ee724de 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -45,10 +45,13 @@ const weather = await directus.request(readSingleton('site_weather')); + timezone={weather.timezone} + > + @@ -109,5 +112,11 @@ const weather = await directus.request(readSingleton('site_weather')); }; animateContent(); + + const observer = new MutationObserver(() => { + animateContent(); + }); + + observer.observe(document.body, { childList: true, subtree: true }); }); diff --git a/src/support/weather.ts b/src/support/weather.ts index e756c7e..7cb0b16 100644 --- a/src/support/weather.ts +++ b/src/support/weather.ts @@ -28,40 +28,38 @@ const getWeatherInfo = (code: number) => { return { label: 'Unknown', icon: '03d' }; }; -const getDayName = (dateStr: string) => { - return new Date(dateStr).toLocaleDateString('en-US', { weekday: 'short' }); +export const getDayName = (dateStr: string) => { + const date = new Date(`${dateStr}T00:00:00`); + return date.toLocaleDateString('en-US', { weekday: 'short' }); }; -async function getFiveDayForecast(latitude: string, longitude: string): Promise { - const url = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=weather_code,temperature_2m_max&timezone=auto&temperature_unit=fahrenheit`; +async function getFiveDayForecast(latitude: string, longitude: string, timezone: string): Promise { + const url = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=weather_code,temperature_2m_max&timezone=${timezone}&temperature_unit=fahrenheit`; + let data: any; try { const response = await fetch(url); if (!response.ok) throw new Error("Weather service unavailable"); - - const data = await response.json(); - - const forecastDays = data.daily.time.map((date: string, index: number): DayForecast => { - const code = data.daily.weather_code[index]; - const info = getWeatherInfo(code); - + data = await response.json(); + + } catch (e: unknown) { + return { forecastDays: [], error: "Failed to load weather" }; + } + + const forecastDays = data.daily.time + .slice(0, 5) + .map((date: string, index: number): DayForecast => { return { date, temp: Math.round(data.daily.temperature_2m_max[index]), - code, - label: info.label, - icon: info.icon, - dayName: getDayName(date) + code: data.daily.weather_code[index], + label: getWeatherInfo(data.daily.weather_code[index]).label, + icon: getWeatherInfo(data.daily.weather_code[index]).icon, + dayName: getDayName(date) }; - }).slice(0, 5); + }); - return { forecastDays, error: null }; - } catch (e: unknown) { - return { - forecastDays: [], - error: e instanceof Error ? e.message : "An unexpected error occurred" - }; - } + return { forecastDays, error: null }; } export { getFiveDayForecast };