nomadweb/frontend/src/components/InsuranceGuide.tsx
eric 341fcdd15e Add insurance, expenses, SIM guide, about page; unify trip storage
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 00:09:10 -05:00

107 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useMemo, useState } from "react";
interface Plan {
id: string;
emoji: string;
name: string;
price: string;
cover: string[];
best: string;
note: string;
}
const PLANS: Plan[] = [
{
id: "safetywing", emoji: "🛡️", name: "SafetyWing Nomad",
price: "$45–80/月", best: "多数数字游民首选",
cover: ["门诊/住院", "紧急医疗运送", "旅行延误"],
note: "覆盖全球多数国家,按月订阅灵活",
},
{
id: "worldnomads", emoji: "🌍", name: "World Nomads",
price: "按行程报价", best: "多国跳跃旅行",
cover: ["冒险运动", "行李丢失", "紧急救援"],
note: "适合含户外活动的行程,按段购买",
},
{
id: "genki", emoji: "🇯🇵", name: "Genki",
price: "€60–100/月", best: "欧洲长期旅居",
cover: ["欧盟医疗", "牙科可选", "签证材料支持"],
note: "对申根签证申请材料较友好",
},
{
id: "local", emoji: "🏥", name: "目的地本地保险",
price: "因地而异", best: "停留 6 个月+",
cover: ["本地医院", "报销便捷", "费用通常更低"],
note: "需了解当地条款与语言,适合长期定居",
},
];
const FILTERS = [
{ key: "all", label: "🌏 全部" },
{ key: "flex", label: "📅 按月灵活" },
{ key: "trip", label: "✈️ 按行程" },
{ key: "long", label: "🏠 长期" },
];
export default function InsuranceGuide() {
const [filter, setFilter] = useState("all");
const [picked, setPicked] = useState<string | null>(null);
const filtered = useMemo(() => {
if (filter === "all") return PLANS;
if (filter === "flex") return PLANS.filter((p) => p.id === "safetywing" || p.id === "genki");
if (filter === "trip") return PLANS.filter((p) => p.id === "worldnomads");
return PLANS.filter((p) => p.id === "local" || p.id === "genki");
}, [filter]);
return (
<section className="section insurance-section" id="insurance">
<div className="container">
<div className="section-header reveal">
<span className="section-tag">🏥 INSURANCE</span>
<h2>旅居保险指南</h2>
<p>远程工作不等于裸奔——选对国际医疗保险再出发</p>
</div>
<div className="events-filters reveal">
{FILTERS.map((f) => (
<button
key={f.key}
className={`filter-btn${filter === f.key ? " active" : ""}`}
onClick={() => setFilter(f.key)}
>
{f.label}
</button>
))}
</div>
<div className="insurance-grid">
{filtered.map((p, i) => (
<div
key={p.id}
className={`insurance-card reveal${picked === p.id ? " selected" : ""}`}
style={{ transitionDelay: `${i * 0.08}s` }}
onClick={() => setPicked(p.id === picked ? null : p.id)}
>
<div className="insurance-top">
<span className="insurance-emoji">{p.emoji}</span>
<span className="insurance-price">{p.price}</span>
</div>
<h3>{p.name}</h3>
<p className="insurance-best">👍 {p.best}</p>
<ul className="insurance-cover">
{p.cover.map((c) => <li key={c}>✓ {c}</li>)}
</ul>
<p className="insurance-note">{p.note}</p>
{picked === p.id && <span className="insurance-picked">✓ 已标记关注</span>}
</div>
))}
</div>
</div>
</section>
);
}