nomadweb/frontend/src/components/AtmCashGuide.tsx
eric 4ab2d7e412 Add tools hub, changelog, ATM guide, and slim section nav
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 00:24:44 -05:00

90 lines
3.7 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";
import type { Destination } from "@/lib/types";
interface AtmTip {
emoji: string;
title: string;
detail: string;
}
const TIPS: Record<string, AtmTip[]> = {
bali: [
{ emoji: "🏦", title: "优先银行 ATM", detail: "BCA / Mandiri 手续费相对透明,避开独立小黄机。" },
{ emoji: "💳", title: "Wise / 实体卡", detail: "尽量用无外汇手续费卡,按需取现。" },
{ emoji: "💵", title: "别一次取太多", detail: "现金够用即可,酒店与餐厅多数可刷卡。" },
],
chiangmai: [
{ emoji: "🏧", title: "Aeon / 银行柜员机", detail: "注意屏幕提示的「动态汇率」选项,尽量选拒绝。" },
{ emoji: "💱", title: "拒绝 DCC", detail: "出现「用人民币结算?」选 No,用泰铢记账更划算。" },
{ emoji: "🧾", title: "保留小票", detail: "便于核对手续费与异常扣款。" },
],
lisbon: [
{ emoji: "🇪🇺", title: "欧元区友好", detail: "多数 ATM 支持国际卡,留意 Multibanco 标识。" },
{ emoji: "🚫", title: "拒绝动态货币转换", detail: "选以欧元扣款,避免银行额外加点。" },
{ emoji: "🪙", title: "小面额现金", detail: "市场与有轨电车偶尔需要硬币。" },
],
barcelona: [
{ emoji: "🏧", title: "银行网点 ATM", detail: "CaixaBank / Santander 更稳,避开街头独立机。" },
{ emoji: "🚫", title: "拒 DCC", detail: "选欧元结算,别让机器帮你换汇。" },
{ emoji: "👛", title: "现金备用量", detail: "堂食可刷卡,小摊与夜市准备现金。" },
],
mexico: [
{ emoji: "🏦", title: "BBVA / Santander", detail: "大行 ATM 更安全,白天取现。" },
{ emoji: "⚠️", title: "警惕侧录", detail: "检查插卡口是否松动,优先商场内机器。" },
{ emoji: "💵", title: "小费文化", detail: "预留小额比索现金给餐厅与快递。" },
],
tokyo: [
{ emoji: "🏪", title: "7-Eleven ATM", detail: "对国际卡最友好,便利店随处可取。" },
{ emoji: "💴", title: "日元现金仍重要", detail: "部分居酒屋与神社只收现金。" },
{ emoji: "💱", title: "少在机场换汇", detail: "汇率通常较差,落地后便利店 ATM 更优。" },
],
};
interface Props {
destinations: Destination[];
}
export default function AtmCashGuide({ destinations }: Props) {
const [slug, setSlug] = useState(destinations[0]?.slug || "chiangmai");
const tips = useMemo(() => TIPS[slug] || TIPS.chiangmai, [slug]);
const dest = destinations.find((d) => d.slug === slug);
return (
<section className="section atm-section" id="atm">
<div className="container">
<div className="section-header reveal">
<span className="section-tag">🏧 ATM</span>
<h2>取现与换汇避坑</h2>
<p>拒 DCC、选对机器,少交「智商税」</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="atm-grid">
{tips.map((t, i) => (
<div key={t.title} className="atm-card reveal" style={{ transitionDelay: `${i * 0.08}s` }}>
<span className="atm-emoji">{t.emoji}</span>
<h4>{t.title}</h4>
<p>{t.detail}</p>
</div>
))}
</div>
</div>
</section>
);
}