Files
wtr/components/warnings/warnings-panel.tsx
zv ee55521803
All checks were successful
CI / Lint, typecheck and build (push) Successful in 9m56s
chore: add prettier formatting
2026-06-14 20:26:56 +02:00

94 lines
3.8 KiB
TypeScript

"use client";
import { Map, MapPinned } from "lucide-react";
import { useWarnings } from "@/hooks/use-warnings";
import { WarningCard } from "@/components/warnings/warning-card";
import { PageLoadingSkeleton } from "@/components/states/loading-skeleton";
import { EmptyState } from "@/components/states/empty-state";
import { ErrorState } from "@/components/states/error-state";
import { DEFAULT_STATION_ID } from "@/lib/constants";
import { useI18n } from "@/lib/i18n";
import { formatProvinceName, getProvinceForSelection } from "@/lib/provinces";
import { useWeatherStore } from "@/lib/store";
import { warningMatchesLocalSelection } from "@/lib/warning-regions";
import type { WeatherWarning } from "@/types/imgw";
function WarningGrid({ warnings, indexOffset = 0 }: { warnings: WeatherWarning[]; indexOffset?: number }) {
return (
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
{warnings.map((warning, index) => (
<WarningCard key={warning.id} warning={warning} index={index + indexOffset} />
))}
</div>
);
}
export function WarningsPanel() {
const { language, t } = useI18n();
const { data: warnings, isPending, isError, refetch } = useWarnings();
const selectedStationId = useWeatherStore((state) => state.selectedStationId);
const selectedLocation = useWeatherStore((state) => state.selectedLocation);
if (selectedLocation?.region === "GLOBAL") {
return (
<EmptyState
title={t("warnings.globalUnavailableTitle")}
description={t("warnings.globalUnavailableDescription")}
/>
);
}
if (isPending) return <PageLoadingSkeleton />;
if (isError) return <ErrorState onRetry={() => refetch()} description={t("warnings.error")} />;
if (!warnings?.length)
return <EmptyState title={t("warnings.emptyTitle")} description={t("warnings.emptyDescription")} />;
const province = getProvinceForSelection(selectedLocation?.province, selectedStationId ?? DEFAULT_STATION_ID);
if (!province) return <WarningGrid warnings={warnings} />;
const provinceLabel = formatProvinceName(province, language);
const localLabel = selectedLocation?.countyTeryt
? (selectedLocation.district ?? selectedLocation.name)
: provinceLabel;
const localWarnings = warnings.filter((warning) => warningMatchesLocalSelection(warning, province, selectedLocation));
const otherWarnings = warnings.filter(
(warning) => !warningMatchesLocalSelection(warning, province, selectedLocation),
);
return (
<div className="space-y-9">
<section className="space-y-4">
<div>
<p className="section-kicker flex items-center gap-2">
<MapPinned className="size-4" />
{t("warnings.myProvince")}
</p>
<h2 className="mt-2 text-2xl font-semibold capitalize tracking-tight">{localLabel}</h2>
<p className="mt-1 max-w-2xl text-sm leading-6 text-muted">
{t("warnings.myProvinceDescription", { province: localLabel })}
</p>
</div>
{localWarnings.length ? (
<WarningGrid warnings={localWarnings} />
) : (
<EmptyState
title={t("warnings.myProvinceEmptyTitle")}
description={t("warnings.myProvinceEmptyDescription", { province: localLabel })}
/>
)}
</section>
{otherWarnings.length > 0 && (
<section className="space-y-4">
<div>
<p className="flex items-center gap-2 text-xs font-semibold uppercase tracking-[0.16em] text-muted">
<Map className="size-4" />
{t("warnings.otherRegions")}
</p>
<p className="mt-1 max-w-2xl text-sm leading-6 text-muted">{t("warnings.otherRegionsDescription")}</p>
</div>
<WarningGrid warnings={otherWarnings} indexOffset={localWarnings.length} />
</section>
)}
</div>
);
}