136 lines
4.8 KiB
TypeScript
136 lines
4.8 KiB
TypeScript
"use client";
|
||
|
||
import { useMemo, useState } from "react";
|
||
import { useToast } from "@/lib/toast";
|
||
import type { Destination } from "@/lib/types";
|
||
|
||
interface Phrase {
|
||
local: string;
|
||
pinyin?: string;
|
||
zh: string;
|
||
}
|
||
|
||
const PHRASES: Record<string, { lang: string; flag: string; items: Phrase[] }> = {
|
||
bali: {
|
||
lang: "印尼语", flag: "🇮🇩",
|
||
items: [
|
||
{ local: "Halo", zh: "你好" },
|
||
{ local: "Terima kasih", zh: "谢谢" },
|
||
{ local: "Berapa harganya?", zh: "这个多少钱?" },
|
||
{ local: "WiFi-nya bagus?", zh: "网速好吗?" },
|
||
{ local: "Saya mau sewa sebulan", zh: "我想租一个月" },
|
||
{ local: "Di mana toilet?", zh: "洗手间在哪?" },
|
||
],
|
||
},
|
||
chiangmai: {
|
||
lang: "泰语", flag: "🇹🇭",
|
||
items: [
|
||
{ local: "สวัสดี", pinyin: "Sawatdee", zh: "你好" },
|
||
{ local: "ขอบคุณ", pinyin: "Khop khun", zh: "谢谢" },
|
||
{ local: "เท่าไหร่", pinyin: "Tao rai", zh: "多少钱?" },
|
||
{ local: "WiFi แรงไหม", pinyin: "WiFi raeng mai", zh: "网快吗?" },
|
||
{ local: "อร่อยมาก", pinyin: "Aroi mak", zh: "很好吃" },
|
||
{ local: "ไม่เผ็ด", pinyin: "Mai phet", zh: "不要辣" },
|
||
],
|
||
},
|
||
lisbon: {
|
||
lang: "葡萄牙语", flag: "🇵🇹",
|
||
items: [
|
||
{ local: "Olá", zh: "你好" },
|
||
{ local: "Obrigado / Obrigada", zh: "谢谢(男/女)" },
|
||
{ local: "Quanto custa?", zh: "多少钱?" },
|
||
{ local: "O WiFi é bom?", zh: "网好吗?" },
|
||
{ local: "Uma cerveja, por favor", zh: "请来一杯啤酒" },
|
||
{ local: "Onde fica o coworking?", zh: "联合办公在哪?" },
|
||
],
|
||
},
|
||
barcelona: {
|
||
lang: "西班牙语", flag: "🇪🇸",
|
||
items: [
|
||
{ local: "Hola", zh: "你好" },
|
||
{ local: "Gracias", zh: "谢谢" },
|
||
{ local: "¿Cuánto cuesta?", zh: "多少钱?" },
|
||
{ local: "¿Hay buen WiFi?", zh: "有好网吗?" },
|
||
{ local: "La cuenta, por favor", zh: "买单" },
|
||
{ local: "¿Dónde está el metro?", zh: "地铁在哪?" },
|
||
],
|
||
},
|
||
mexico: {
|
||
lang: "西班牙语", flag: "🇲🇽",
|
||
items: [
|
||
{ local: "Qué onda", zh: "嘿(口语)" },
|
||
{ local: "Gracias", zh: "谢谢" },
|
||
{ local: "¿Cuánto cuesta?", zh: "多少钱?" },
|
||
{ local: "Sin chile, por favor", zh: "不要辣" },
|
||
{ local: "¿Tienen WiFi?", zh: "有 WiFi 吗?" },
|
||
{ local: "La cuenta, por favor", zh: "买单" },
|
||
],
|
||
},
|
||
tokyo: {
|
||
lang: "日语", flag: "🇯🇵",
|
||
items: [
|
||
{ local: "こんにちは", pinyin: "Konnichiwa", zh: "你好" },
|
||
{ local: "ありがとう", pinyin: "Arigatou", zh: "谢谢" },
|
||
{ local: "いくらですか", pinyin: "Ikura desu ka", zh: "多少钱?" },
|
||
{ local: "Wi-Fiはありますか", pinyin: "Wi-Fi wa arimasu ka", zh: "有 WiFi 吗?" },
|
||
{ local: "おいしい", pinyin: "Oishii", zh: "好吃" },
|
||
{ local: "すみません", pinyin: "Sumimasen", zh: "不好意思 / 借过" },
|
||
],
|
||
},
|
||
};
|
||
|
||
interface Props {
|
||
destinations: Destination[];
|
||
}
|
||
|
||
export default function Phrasebook({ destinations }: Props) {
|
||
const { toast } = useToast();
|
||
const [slug, setSlug] = useState(destinations[0]?.slug || "bali");
|
||
const book = useMemo(() => PHRASES[slug] || PHRASES.bali, [slug]);
|
||
const dest = destinations.find((d) => d.slug === slug);
|
||
|
||
const copy = async (text: string) => {
|
||
await navigator.clipboard.writeText(text);
|
||
toast(`已复制:${text}`);
|
||
};
|
||
|
||
return (
|
||
<section className="section phrase-section" id="phrases">
|
||
<div className="container">
|
||
<div className="section-header reveal">
|
||
<span className="section-tag">🗣️ PHRASES</span>
|
||
<h2>游民生存短语本</h2>
|
||
<p>点一下复制常用语,落地就能开口</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>
|
||
|
||
<div className="phrase-card reveal">
|
||
<div className="phrase-lang">
|
||
{book.flag} {dest?.name} · {book.lang}
|
||
</div>
|
||
<div className="phrase-grid">
|
||
{book.items.map((p) => (
|
||
<button key={p.local} className="phrase-item" onClick={() => copy(p.local)} title="点击复制">
|
||
<strong>{p.local}</strong>
|
||
{p.pinyin && <span className="phrase-pinyin">{p.pinyin}</span>}
|
||
<span className="phrase-zh">{p.zh}</span>
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
);
|
||
}
|