96 lines
3.9 KiB
TypeScript
96 lines
3.9 KiB
TypeScript
"use client";
|
||
|
||
import { useMemo, useState } from "react";
|
||
import type { Destination } from "@/lib/types";
|
||
|
||
interface SimPlan {
|
||
name: string;
|
||
emoji: string;
|
||
data: string;
|
||
price: string;
|
||
tip: string;
|
||
}
|
||
|
||
const SIMS: Record<string, SimPlan[]> = {
|
||
bali: [
|
||
{ name: "Telkomsel", emoji: "📶", data: "50GB / 30天", price: "约 ¥60", tip: "覆盖最好,机场可办" },
|
||
{ name: "XL / Axis", emoji: "📱", data: "40GB / 30天", price: "约 ¥40", tip: "性价比高,市区够用" },
|
||
{ name: "eSIM Airalo", emoji: "✈️", data: "按需充值", price: "约 $8 起", tip: "落地即用,免换卡" },
|
||
],
|
||
chiangmai: [
|
||
{ name: "AIS", emoji: "📶", data: "无限量套餐", price: "约 ¥80/月", tip: "网速稳,游民常用" },
|
||
{ name: "TrueMove", emoji: "📱", data: "大流量包", price: "约 ¥60/月", tip: "7-Eleven 随处可买" },
|
||
{ name: "eSIM Holafly", emoji: "✈️", data: "无限流量", price: "约 $19/周", tip: "适合短期跳岛" },
|
||
],
|
||
lisbon: [
|
||
{ name: "Vodafone PT", emoji: "📶", data: "20–50GB", price: "€15–25", tip: "覆盖全国,店内可办" },
|
||
{ name: "NOS / MEO", emoji: "📱", data: "Prepaid", price: "€10–20", tip: "预付费灵活" },
|
||
{ name: "eSIM Airalo", emoji: "✈️", data: "按需", price: "$5 起", tip: "抵达前先装好" },
|
||
],
|
||
barcelona: [
|
||
{ name: "Orange / Movistar", emoji: "📶", data: "20–50GB", price: "€10–20", tip: "申根区漫游友好" },
|
||
{ name: "Digi", emoji: "📱", data: "大流量便宜", price: "€5–15", tip: "预算优先之选" },
|
||
{ name: "eSIM", emoji: "✈️", data: "按需", price: "$6 起", tip: "免排队办卡" },
|
||
],
|
||
mexico: [
|
||
{ name: "Telcel", emoji: "📶", data: "Amigo 套餐", price: "$10–20", tip: "覆盖最广" },
|
||
{ name: "AT&T MX", emoji: "📱", data: "预付费", price: "$10–18", tip: "市中心信号好" },
|
||
{ name: "eSIM", emoji: "✈️", data: "按需", price: "$8 起", tip: "对接北美出差方便" },
|
||
],
|
||
tokyo: [
|
||
{ name: "IIJmio / SoftBank", emoji: "📶", data: "10–20GB", price: "¥2,000–4,000", tip: "便利店可买" },
|
||
{ name: "Sakura Mobile", emoji: "📱", data: "游民友好", price: "¥3,000+", tip: "支持英文客服" },
|
||
{ name: "eSIM Airalo", emoji: "✈️", data: "按需", price: "$6 起", tip: "机场落地即连" },
|
||
],
|
||
};
|
||
|
||
interface Props {
|
||
destinations: Destination[];
|
||
}
|
||
|
||
export default function SimGuide({ destinations }: Props) {
|
||
const [slug, setSlug] = useState(destinations[0]?.slug || "bali");
|
||
const plans = useMemo(() => SIMS[slug] || SIMS.bali, [slug]);
|
||
const dest = destinations.find((d) => d.slug === slug);
|
||
|
||
return (
|
||
<section className="section sim-section" id="sim">
|
||
<div className="container">
|
||
<div className="section-header reveal">
|
||
<span className="section-tag">📱 SIM / eSIM</span>
|
||
<h2>当地上网方案</h2>
|
||
<p>落地第一件事:连上网。实体卡与 eSIM 怎么选</p>
|
||
</div>
|
||
|
||
<div className="housing-cities reveal">
|
||
{destinations.map((d) => (
|
||
<button
|
||
key={d.slug}
|
||
className={`season-city-btn${slug === d.slug ? " active" : ""}`}
|
||
onClick={() => setSlug(d.slug)}
|
||
>
|
||
{d.emoji} {d.name}
|
||
</button>
|
||
))}
|
||
</div>
|
||
|
||
<h3 className="sim-city-title reveal">{dest?.emoji} {dest?.name} 推荐套餐</h3>
|
||
|
||
<div className="sim-grid">
|
||
{plans.map((p, i) => (
|
||
<div key={p.name} className="sim-card reveal" style={{ transitionDelay: `${i * 0.08}s` }}>
|
||
<span className="sim-emoji">{p.emoji}</span>
|
||
<h4>{p.name}</h4>
|
||
<div className="sim-meta">
|
||
<span>📦 {p.data}</span>
|
||
<span className="sim-price">{p.price}</span>
|
||
</div>
|
||
<p>{p.tip}</p>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
);
|
||
}
|