diff --git a/components/forecast/day-forecast-modal.tsx b/components/forecast/day-forecast-modal.tsx index 708cdea..0d2e85e 100644 --- a/components/forecast/day-forecast-modal.tsx +++ b/components/forecast/day-forecast-modal.tsx @@ -14,6 +14,7 @@ import { formatForecastTemperature, formatForecastWind, getForecastCondition, + isForecastNight, } from "@/lib/forecast-utils"; import { useWeatherStore } from "@/lib/store"; import type { DailyForecast, ForecastSource, HourlyForecast } from "@/types/forecast"; @@ -156,7 +157,7 @@ export function DayForecastModal({ title={getForecastCondition(hour.weatherCode, language)} >

{formatHour(hour.time)}

- +

{formatForecastTemperature(hour.temperature, language, temperatureUnit)}

diff --git a/components/forecast/forecast-icon.tsx b/components/forecast/forecast-icon.tsx index 191d167..309d0fe 100644 --- a/components/forecast/forecast-icon.tsx +++ b/components/forecast/forecast-icon.tsx @@ -1,8 +1,8 @@ -import { Cloud, CloudDrizzle, CloudFog, CloudLightning, CloudRain, CloudSnow, CloudSun, Sun } from "lucide-react"; +import { Cloud, CloudDrizzle, CloudFog, CloudLightning, CloudMoon, CloudRain, CloudSnow, CloudSun, MoonStar, Sun } from "lucide-react"; -export function ForecastIcon({ code, className = "" }: { code: number | null; className?: string }) { - const Icon = code === 0 ? Sun - : code === 1 || code === 2 ? CloudSun +export function ForecastIcon({ code, className = "", isNight = false }: { code: number | null; className?: string; isNight?: boolean }) { + const Icon = code === 0 ? isNight ? MoonStar : Sun + : code === 1 || code === 2 ? isNight ? CloudMoon : CloudSun : code === 45 || code === 48 ? CloudFog : code !== null && code >= 51 && code <= 57 ? CloudDrizzle : code !== null && ((code >= 61 && code <= 67) || (code >= 80 && code <= 82)) ? CloudRain diff --git a/components/forecast/forecast-panel.tsx b/components/forecast/forecast-panel.tsx index 9117cb2..8ea1c3b 100644 --- a/components/forecast/forecast-panel.tsx +++ b/components/forecast/forecast-panel.tsx @@ -17,9 +17,11 @@ import { formatForecastRainfall, formatForecastTemperature, formatForecastWind, + getDailyForecastForHour, getForecastCondition, getHourlyForecastForDay, getUpcomingHourlyForecast, + isForecastNight, } from "@/lib/forecast-utils"; import { useWeatherStore } from "@/lib/store"; import type { DailyForecast, HourlyForecast } from "@/types/forecast"; @@ -153,35 +155,38 @@ export function ForecastPanel({ latitude, longitude, locationName }: { latitude?

{t("forecast.hourly")}

    - {upcomingHours.map((hour, index) => ( - -

    {formatHour(hour.time)}

    - -

    {formatForecastTemperature(hour.temperature, language, temperatureUnit)}

    -

    {hour.precipitationProbability === null ? "—" : `${hour.precipitationProbability}%`}

    -
    -

    - - {formatForecastTemperature(hour.feelsLike, language, temperatureUnit)} -

    -

    - - {formatForecastWind(hour.windSpeed, language, windSpeedUnit)} -

    -

    - - {formatForecastRainfall(hour.precipitation, language)} -

    -
    -
    - ))} + {upcomingHours.map((hour, index) => { + const day = getDailyForecastForHour(forecast.daily, hour.time); + return ( + +

    {formatHour(hour.time)}

    + +

    {formatForecastTemperature(hour.temperature, language, temperatureUnit)}

    +

    {hour.precipitationProbability === null ? "—" : `${hour.precipitationProbability}%`}

    +
    +

    + + {formatForecastTemperature(hour.feelsLike, language, temperatureUnit)} +

    +

    + + {formatForecastWind(hour.windSpeed, language, windSpeedUnit)} +

    +

    + + {formatForecastRainfall(hour.precipitation, language)} +

    +
    +
    + ); + })}
diff --git a/lib/forecast-utils.ts b/lib/forecast-utils.ts index c9a6621..90a95c3 100644 --- a/lib/forecast-utils.ts +++ b/lib/forecast-utils.ts @@ -1,7 +1,7 @@ import type { Language, TranslationKey } from "@/lib/i18n"; import { translate } from "@/lib/i18n"; import { DEFAULT_TEMPERATURE_UNIT, DEFAULT_WIND_SPEED_UNIT, formatTemperature, formatWindSpeed } from "@/lib/weather-utils"; -import type { HourlyForecast } from "@/types/forecast"; +import type { DailyForecast, HourlyForecast } from "@/types/forecast"; import type { TemperatureUnit, WindSpeedUnit } from "@/types/units"; export function getForecastConditionKey(code: number | null): TranslationKey { @@ -89,6 +89,23 @@ export function getHourlyForecastForDay(hours: HourlyForecast[], date: string) { return hours.filter((hour) => hour.time.startsWith(`${date}T`)); } +export function getDailyForecastForHour(days: DailyForecast[], time: string) { + return days.find((day) => time.startsWith(`${day.date}T`)) ?? null; +} + +export function isForecastNight(time: string, day: Pick | null | undefined) { + const hourTimestamp = parseForecastHour(time); + const sunriseTimestamp = day?.sunrise ? parseForecastHour(day.sunrise) : null; + const sunsetTimestamp = day?.sunset ? parseForecastHour(day.sunset) : null; + + if (hourTimestamp !== null && sunriseTimestamp !== null && sunsetTimestamp !== null) { + return hourTimestamp < sunriseTimestamp || hourTimestamp >= sunsetTimestamp; + } + + const hour = getForecastHourOfDay(time); + return hour !== null && (hour < 6 || hour >= 21); +} + export function isForecastHourPast(time: string) { const currentHour = getWarsawForecastHour(); const hourTimestamp = parseForecastHour(time);