64 lines
3.2 KiB
TypeScript
64 lines
3.2 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 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 (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 localWarnings = warnings.filter((warning) => warning.provinces.includes(province));
|
|
const otherWarnings = warnings.filter((warning) => !warning.provinces.includes(province));
|
|
|
|
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">{provinceLabel}</h2>
|
|
<p className="mt-1 max-w-2xl text-sm leading-6 text-muted">{t("warnings.myProvinceDescription", { province: provinceLabel })}</p>
|
|
</div>
|
|
{localWarnings.length
|
|
? <WarningGrid warnings={localWarnings} />
|
|
: <EmptyState title={t("warnings.myProvinceEmptyTitle")} description={t("warnings.myProvinceEmptyDescription", { province: provinceLabel })} />}
|
|
</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>
|
|
);
|
|
}
|