feat: prefer IMGW ALARO forecast data

This commit is contained in:
zv
2026-06-02 20:23:55 +02:00
parent ad4248efdf
commit b97a1cf1ea
11 changed files with 371 additions and 69 deletions

View File

@@ -2,9 +2,10 @@
import { useEffect, useMemo, useRef } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { CloudSun, Droplets, ExternalLink, Sunrise, Sunset, Wind, X } from "lucide-react";
import { CloudSun, Droplets, Sunrise, Sunset, Wind, X } from "lucide-react";
import { DayForecastCharts } from "@/components/charts/day-forecast-charts";
import { ForecastIcon } from "@/components/forecast/forecast-icon";
import { ForecastSources } from "@/components/forecast/forecast-sources";
import { Card } from "@/components/ui/card";
import { useI18n } from "@/lib/i18n";
import { cn } from "@/lib/utils";
@@ -15,7 +16,7 @@ import {
getForecastCondition,
isForecastHourPast,
} from "@/lib/forecast-utils";
import type { DailyForecast, HourlyForecast } from "@/types/forecast";
import type { DailyForecast, ForecastSource, HourlyForecast } from "@/types/forecast";
function formatHour(value: string | null) {
if (!value) return "—";
@@ -43,11 +44,13 @@ export function DayForecastModal({
day,
hours,
locationName,
sources,
onClose,
}: {
day: DailyForecast | null;
hours: HourlyForecast[];
locationName: string;
sources: ForecastSource[];
onClose: () => void;
}) {
const { language, locale, t } = useI18n();
@@ -169,12 +172,7 @@ export function DayForecastModal({
<DayForecastCharts hours={hours} />
<p className="text-[0.68rem] text-slate-500 dark:text-slate-400">
{t("forecast.source")}{" "}
<a href="https://open-meteo.com/" target="_blank" rel="noreferrer" className="inline-flex items-center gap-1 underline decoration-slate-400/60 underline-offset-2 transition hover:text-sky-700 dark:hover:text-sky-300">
Open-Meteo <ExternalLink className="size-3" />
</a>
</p>
<ForecastSources sources={sources} />
</div>
</motion.section>
</motion.div>

View File

@@ -2,10 +2,11 @@
import { useCallback, useState } from "react";
import { motion } from "framer-motion";
import { CalendarDays, ChevronRight, Clock3, CloudRain, CloudSun, Droplets, ExternalLink, RefreshCw, ThermometerSun, Wind, type LucideIcon } from "lucide-react";
import { CalendarDays, ChevronRight, Clock3, CloudRain, CloudSun, Droplets, RefreshCw, ThermometerSun, Wind, type LucideIcon } from "lucide-react";
import { DayForecastCharts } from "@/components/charts/day-forecast-charts";
import { DayForecastModal } from "@/components/forecast/day-forecast-modal";
import { ForecastIcon } from "@/components/forecast/forecast-icon";
import { ForecastSources } from "@/components/forecast/forecast-sources";
import { LoadingSkeleton } from "@/components/states/loading-skeleton";
import { EmptyState } from "@/components/states/empty-state";
import { Button } from "@/components/ui/button";
@@ -188,11 +189,9 @@ export function ForecastPanel({ latitude, longitude, locationName }: { latitude?
</div>
)}
<p className="text-[0.68rem] text-slate-500 dark:text-slate-400">
{t("forecast.source")} <a href="https://open-meteo.com/" target="_blank" rel="noreferrer" className="inline-flex items-center gap-1 underline decoration-slate-400/60 underline-offset-2 transition hover:text-sky-700 dark:hover:text-sky-300">Open-Meteo <ExternalLink className="size-3" /></a>
</p>
{forecast && <ForecastSources sources={forecast.sources} />}
<DayForecastModal day={selectedDay} hours={selectedDayHours} locationName={locationName} onClose={closeDayDetails} />
<DayForecastModal day={selectedDay} hours={selectedDayHours} locationName={locationName} sources={forecast?.sources ?? []} onClose={closeDayDetails} />
</section>
);
}

View File

@@ -0,0 +1,28 @@
"use client";
import { ExternalLink } from "lucide-react";
import { useI18n } from "@/lib/i18n";
import type { ForecastSource } from "@/types/forecast";
export function ForecastSources({ sources }: { sources: ForecastSource[] }) {
const { t } = useI18n();
const hasImgw = sources.includes("imgw-alaro");
return (
<p className="text-[0.68rem] leading-5 text-slate-500 dark:text-slate-400">
{t("forecast.source")}{" "}
{hasImgw && (
<>
<a href="https://meteo.imgw.pl/pogoda/" target="_blank" rel="noreferrer" className="inline-flex items-center gap-1 underline decoration-slate-400/60 underline-offset-2 transition hover:text-sky-700 dark:hover:text-sky-300">
IMGW ALARO <ExternalLink className="size-3" />
</a>
{", "}
</>
)}
<a href="https://open-meteo.com/" target="_blank" rel="noreferrer" className="inline-flex items-center gap-1 underline decoration-slate-400/60 underline-offset-2 transition hover:text-sky-700 dark:hover:text-sky-300">
Open-Meteo <ExternalLink className="size-3" />
</a>
. {t(hasImgw ? "forecast.sourceCombinedDescription" : "forecast.sourceFallbackDescription")}
</p>
);
}