feat: add Polish and English language switcher
This commit is contained in:
@@ -13,40 +13,42 @@ import { WeatherDetailsGrid } from "@/components/weather/current-conditions-card
|
||||
import { SnapshotChart } from "@/components/charts/snapshot-chart";
|
||||
import { PageLoadingSkeleton } from "@/components/states/loading-skeleton";
|
||||
import { ErrorState } from "@/components/states/error-state";
|
||||
import { useI18n } from "@/lib/i18n";
|
||||
|
||||
export function StationDetailPage({ id }: { id: string }) {
|
||||
const { language, t } = useI18n();
|
||||
const { data: station, isPending, isError, refetch } = useWeatherStation(id);
|
||||
const favoriteIds = useWeatherStore((state) => state.favorites);
|
||||
const toggleFavorite = useWeatherStore((state) => state.toggleFavorite);
|
||||
if (isPending) return <PageLoadingSkeleton />;
|
||||
if (isError || !station) return <ErrorState onRetry={() => refetch()} description="Nie udało się pobrać danych wybranej stacji IMGW." />;
|
||||
if (isError || !station) return <ErrorState onRetry={() => refetch()} description={t("station.error")} />;
|
||||
const favorite = favoriteIds.includes(station.id);
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<Link href="/" className="inline-flex items-center gap-2 rounded-full px-1 py-1 text-sm font-medium text-slate-600 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-500 dark:text-slate-300"><ArrowLeft className="size-4" />Wszystkie stacje</Link>
|
||||
<Link href="/" className="inline-flex items-center gap-2 rounded-full px-1 py-1 text-sm font-medium text-slate-600 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-500 dark:text-slate-300"><ArrowLeft className="size-4" />{t("station.all")}</Link>
|
||||
<Button variant="glass" onClick={() => toggleFavorite(station.id)}>
|
||||
<Heart className={cn("size-4", favorite && "fill-rose-500 text-rose-500")} />
|
||||
{favorite ? "Usuń z ulubionych" : "Dodaj do ulubionych"}
|
||||
{favorite ? t("favorites.remove") : t("favorites.add")}
|
||||
</Button>
|
||||
</div>
|
||||
<WeatherHero station={station} />
|
||||
<section>
|
||||
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-sky-700 dark:text-sky-300">Stacja {station.name}</p>
|
||||
<h1 className="mt-2 text-2xl font-semibold tracking-tight">Aktualne parametry</h1>
|
||||
<p className="mb-4 mt-1 text-sm leading-6 text-slate-600 dark:text-slate-300">Najnowszy pomiar udostępniony przez IMGW. Brakujące wartości są oznaczone bez uzupełniania ich danymi szacunkowymi.</p>
|
||||
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-sky-700 dark:text-sky-300">{t("station.label", { name: station.name })}</p>
|
||||
<h1 className="mt-2 text-2xl font-semibold tracking-tight">{t("station.parameters")}</h1>
|
||||
<p className="mb-4 mt-1 text-sm leading-6 text-slate-600 dark:text-slate-300">{t("station.parametersDescription")}</p>
|
||||
<WeatherDetailsGrid station={station} />
|
||||
</section>
|
||||
<div className="grid gap-4 lg:grid-cols-[1.3fr_0.7fr]">
|
||||
<SnapshotChart station={station} />
|
||||
<Card className="p-5">
|
||||
<div className="flex items-center gap-2 text-sky-700 dark:text-sky-300"><ShieldCheck className="size-5" /><p className="text-xs font-semibold uppercase tracking-[0.18em]">Jakość danych</p></div>
|
||||
<h2 className="mt-4 text-xl font-semibold tracking-tight">Ostatni pomiar IMGW</h2>
|
||||
<p className="mt-2 text-sm leading-6 text-slate-600 dark:text-slate-300">Czas poniżej pochodzi bezpośrednio z najnowszego odczytu udostępnionego przez IMGW.</p>
|
||||
<div className="flex items-center gap-2 text-sky-700 dark:text-sky-300"><ShieldCheck className="size-5" /><p className="text-xs font-semibold uppercase tracking-[0.18em]">{t("station.quality")}</p></div>
|
||||
<h2 className="mt-4 text-xl font-semibold tracking-tight">{t("station.lastMeasurementImgw")}</h2>
|
||||
<p className="mt-2 text-sm leading-6 text-slate-600 dark:text-slate-300">{t("station.qualityDescription")}</p>
|
||||
<dl className="mt-6 space-y-3 text-sm">
|
||||
<div><dt className="text-slate-500 dark:text-slate-400">Ostatni pomiar</dt><dd className="mt-0.5 font-medium">{formatDateTime(station.measuredAt)}</dd></div>
|
||||
<div><dt className="text-slate-500 dark:text-slate-400">Źródło</dt><dd className="mt-0.5 font-medium">Publiczne API IMGW</dd></div>
|
||||
<div><dt className="text-slate-500 dark:text-slate-400">{t("station.lastMeasurement")}</dt><dd className="mt-0.5 font-medium">{formatDateTime(station.measuredAt, language)}</dd></div>
|
||||
<div><dt className="text-slate-500 dark:text-slate-400">{t("station.source")}</dt><dd className="mt-0.5 font-medium">{t("station.publicApi")}</dd></div>
|
||||
</dl>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user