46 lines
2.4 KiB
TypeScript
46 lines
2.4 KiB
TypeScript
"use client";
|
|
|
|
import { useMemo, useState } from "react";
|
|
import type { SynopStation } from "@/types/imgw";
|
|
import { StationGrid } from "@/components/weather/station-grid";
|
|
import { StationSearch } from "@/components/weather/station-search";
|
|
|
|
export type StationSort = "alphabetical" | "temperature-desc" | "temperature-asc" | "humidity-desc" | "pressure-desc";
|
|
export type StationFilter = "all" | "warmest" | "coldest" | "windy" | "rainy";
|
|
|
|
function compareNumbers(a: number | null, b: number | null, direction: "asc" | "desc") {
|
|
if (a === null) return 1;
|
|
if (b === null) return -1;
|
|
return direction === "asc" ? a - b : b - a;
|
|
}
|
|
|
|
export function StationsExplorer({ stations }: { stations: SynopStation[] }) {
|
|
const [query, setQuery] = useState("");
|
|
const [sort, setSort] = useState<StationSort>("alphabetical");
|
|
const [filter, setFilter] = useState<StationFilter>("all");
|
|
const visibleStations = useMemo(() => {
|
|
const searched = stations.filter((station) => station.name.toLocaleLowerCase("pl").includes(query.trim().toLocaleLowerCase("pl")));
|
|
const sorted = [...searched].sort((a, b) => {
|
|
if (sort === "temperature-desc") return compareNumbers(a.temperature, b.temperature, "desc");
|
|
if (sort === "temperature-asc") return compareNumbers(a.temperature, b.temperature, "asc");
|
|
if (sort === "humidity-desc") return compareNumbers(a.humidity, b.humidity, "desc");
|
|
if (sort === "pressure-desc") return compareNumbers(a.pressure, b.pressure, "desc");
|
|
return a.name.localeCompare(b.name, "pl");
|
|
});
|
|
if (filter === "all") return sorted;
|
|
const key = { warmest: "temperature", coldest: "temperature", windy: "windSpeed", rainy: "rainfall" }[filter] as keyof SynopStation;
|
|
return [...sorted].sort((a, b) => compareNumbers(a[key] as number | null, b[key] as number | null, filter === "coldest" ? "asc" : "desc")).slice(0, 12);
|
|
}, [filter, query, sort, stations]);
|
|
|
|
return (
|
|
<section className="space-y-4">
|
|
<div>
|
|
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-sky-700 dark:text-sky-300">Stacje synoptyczne</p>
|
|
<h2 className="mt-2 text-2xl font-semibold tracking-tight">Pogoda w Polsce</h2>
|
|
</div>
|
|
<StationSearch query={query} onQueryChange={setQuery} sort={sort} onSortChange={setSort} filter={filter} onFilterChange={setFilter} />
|
|
<StationGrid stations={visibleStations} />
|
|
</section>
|
|
);
|
|
}
|