Rework homepage toward reference dashboard

This commit is contained in:
2569718930@qq.com
2026-04-23 02:17:31 +08:00
parent 040313175f
commit 2589e11415
4 changed files with 487 additions and 150 deletions
+41 -2
View File
@@ -2,7 +2,7 @@
import { startTransition, useEffect, useMemo, useRef, useState } from "react";
import clsx from "clsx";
import { Clock } from "lucide-react";
import { Clock, Search } from "lucide-react";
import { useDashboardStore } from "@/hooks/useDashboardStore";
import { useI18n } from "@/hooks/useI18n";
import { getLocalizedCityName } from "@/lib/dashboard-home-copy";
@@ -62,7 +62,9 @@ export function CitySidebar() {
const [expandedGroups, setExpandedGroups] = useState<
Record<RiskGroupKey, boolean>
>(DEFAULT_EXPANDED_GROUPS);
const [searchQuery, setSearchQuery] = useState("");
const cityItemRefs = useRef<Record<string, HTMLButtonElement | null>>({});
const normalizedQuery = searchQuery.trim().toLowerCase();
const sortedCities = useMemo(
() =>
@@ -91,10 +93,36 @@ export function CitySidebar() {
other: [],
};
sortedCities.forEach((city) => {
const summary = store.citySummariesByName[city.name];
const detail = store.cityDetailsByName[city.name];
const localizedName = getLocalizedCityName(
city.name,
summary?.display_name || detail?.display_name || city.display_name,
locale,
);
if (normalizedQuery) {
const searchCorpus = [
city.name,
city.display_name,
city.airport,
city.icao,
localizedName,
]
.filter(Boolean)
.join(" ")
.toLowerCase();
if (!searchCorpus.includes(normalizedQuery)) return;
}
groups[toPerformanceGroup(city)].push(city);
});
return groups;
}, [sortedCities]);
}, [
locale,
normalizedQuery,
sortedCities,
store.cityDetailsByName,
store.citySummariesByName,
]);
useEffect(() => {
if (!selectedCity) return;
@@ -166,6 +194,17 @@ export function CitySidebar() {
<span className="city-count">{store.cities.length}</span>
</div>
<div className="city-search">
<Search size={14} strokeWidth={2} aria-hidden="true" />
<input
type="search"
value={searchQuery}
onChange={(event) => setSearchQuery(event.target.value)}
placeholder={locale === "en-US" ? "Search city" : "搜索城市"}
aria-label={locale === "en-US" ? "Search city" : "搜索城市"}
/>
</div>
<div className="city-list-items">
{groupMeta.map((group) => {
const citiesInGroup = groupedCities[group.key];