"use client"; import { memo, useState } from "react"; import { City } from "../data/cities"; import { getCitySocialSummary } from "../data/city-social"; import { useLocale, useTranslation } from "@/i18n/navigation"; import { type CityWeatherLive, weatherCodeLabel } from "@/app/lib/city-weather"; function ratingToPercent(rating: string): number { const m: Record = { 极好: 95, 很好: 80, 好: 60, 一般: 40, 差: 20, }; return m[rating] || 50; } function getBarColor(p: number): string { if (p >= 60) return "#22c55e"; if (p >= 35) return "#eab308"; return "#ef4444"; } interface ScoreBarProps { icon: string; label: string; percent: number; animate: boolean; } const ScoreBar = memo(function ScoreBar({ icon, label, percent, animate }: ScoreBarProps) { return (
{icon} {label}
); }); interface CityCardProps { city: City; rank: number; onClick?: () => void; liveWeather?: CityWeatherLive | null; } function CityCardComponent({ city, rank, onClick, liveWeather }: CityCardProps) { const [hovered, setHovered] = useState(false); const locale = useLocale(); const { t } = useTranslation("cityCard"); const socialSummary = getCitySocialSummary(city); const temperature = liveWeather?.temperature ?? city.temperature; const weatherLabel = weatherCodeLabel(liveWeather?.weatherCode, locale === "zh" ? "zh" : "en"); const scores = [ { icon: "⭐", label: "综合", percent: (city.overallScore / 5) * 100, }, { icon: "👥", label: "游民", percent: Math.min(95, (city.nomadsNow / 1200) * 100), }, { icon: "🌡", label: "天气", percent: Math.max(20, Math.min(95, 100 - Math.abs(temperature - 22) * 4)), }, { icon: "👍", label: "好评", percent: ratingToPercent(city.liked), }, { icon: "👮", label: "安全", percent: ratingToPercent(city.safety), }, ]; return (
e.key === "Enter" && onClick?.()} className="city-card cursor-pointer" style={{ background: `linear-gradient(135deg, ${city.gradientFrom}, ${city.gradientTo})`, }} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)} > {/* Icon watermark */} {city.icon} {/* ===== Default state ===== */}
{/* Top row */}
{rank} 🌡 {temperature}°C {weatherLabel ? ( · {weatherLabel} ) : null}
{/* Center: city name */}

{city.name}

{/* Bottom: temp + cost + nomads */}
☕ {socialSummary.coffeechat} 🧭 {socialSummary.localGuide} 🥾 {socialSummary.cityWalk}
{city.description} 👥 {city.nomadsNow.toLocaleString()}{t("nomadsHere")}
{/* ===== Hover overlay (desktop only) ===== */}
); } export default memo(CityCardComponent);