152 lines
6.7 KiB
TypeScript
152 lines
6.7 KiB
TypeScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
import { useTranslation } from "@/i18n/navigation";
|
||
import Footer from "@/app/components/Footer";
|
||
|
||
const RATES = [
|
||
{ from: "CNY", to: "USD", rate: 0.14 },
|
||
{ from: "CNY", to: "EUR", rate: 0.13 },
|
||
{ from: "CNY", to: "THB", rate: 5.2 },
|
||
{ from: "USD", to: "CNY", rate: 7.2 },
|
||
];
|
||
|
||
export default function ToolsPage() {
|
||
const { t } = useTranslation("tools");
|
||
const [income, setIncome] = useState(100000);
|
||
const [cnyAmount, setCnyAmount] = useState(10000);
|
||
const [visaDate, setVisaDate] = useState("2025-06-15");
|
||
|
||
const taxEstimate = Math.round(income * 0.15);
|
||
const cnyToUsd = (v: number) => (v * 0.14).toFixed(2);
|
||
const daysLeft = Math.ceil(
|
||
(new Date(visaDate).getTime() - Date.now()) / (1000 * 60 * 60 * 24)
|
||
);
|
||
|
||
return (
|
||
<div className="min-h-screen bg-[#fafafa] dark:bg-gray-950">
|
||
<div className="max-w-4xl mx-auto px-4 sm:px-6 py-12">
|
||
<div className="mb-10">
|
||
<h1 className="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">
|
||
{t("title")}
|
||
</h1>
|
||
<p className="mt-1 text-gray-500 dark:text-gray-400">
|
||
{t("subtitle")}
|
||
</p>
|
||
</div>
|
||
|
||
<div className="space-y-6">
|
||
<section className="rounded-2xl bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 p-6">
|
||
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-4">
|
||
💱 {t("exchange")}
|
||
</h2>
|
||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-4">
|
||
{RATES.map((r) => (
|
||
<div
|
||
key={`${r.from}-${r.to}`}
|
||
className="p-4 rounded-xl bg-gray-50 dark:bg-gray-800"
|
||
>
|
||
<p className="text-xs text-gray-500 dark:text-gray-400">
|
||
{r.from} → {r.to}
|
||
</p>
|
||
<p className="mt-1 text-lg font-bold text-gray-900 dark:text-gray-100">
|
||
{r.rate}
|
||
</p>
|
||
</div>
|
||
))}
|
||
</div>
|
||
<div className="mt-4 p-4 rounded-xl bg-gray-50 dark:bg-gray-800">
|
||
<label className="block text-xs text-gray-500 dark:text-gray-400 mb-2">CNY → USD</label>
|
||
<div className="flex gap-2 items-center">
|
||
<input
|
||
type="number"
|
||
value={cnyAmount}
|
||
onChange={(e) => setCnyAmount(Number(e.target.value) || 0)}
|
||
className="flex-1 rounded-lg border border-gray-200 dark:border-gray-700 px-3 py-2 text-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100"
|
||
/>
|
||
<span className="text-gray-400">≈</span>
|
||
<span className="font-semibold text-gray-900 dark:text-gray-100">${cnyToUsd(cnyAmount)}</span>
|
||
</div>
|
||
</div>
|
||
<p className="mt-3 text-xs text-gray-400 dark:text-gray-500">
|
||
{t("disclaimer")}
|
||
</p>
|
||
</section>
|
||
|
||
<section className="rounded-2xl bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 p-6">
|
||
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-4">
|
||
📊 {t("tax")}
|
||
</h2>
|
||
<div className="space-y-4">
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||
{t("incomeCountry")} (年收入 ¥)
|
||
</label>
|
||
<input
|
||
type="number"
|
||
value={income}
|
||
onChange={(e) => setIncome(Number(e.target.value))}
|
||
className="w-full rounded-lg border border-gray-200 dark:border-gray-700 px-4 py-2 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
|
||
/>
|
||
</div>
|
||
<div className="p-4 rounded-xl bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800/50">
|
||
<p className="text-sm text-amber-800 dark:text-amber-200">
|
||
{t("estimate")}: 约 ¥{taxEstimate.toLocaleString()}/年
|
||
</p>
|
||
<p className="mt-1 text-xs text-amber-600 dark:text-amber-300">
|
||
{t("taxDisclaimer")}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section className="rounded-2xl bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 p-6">
|
||
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-4">
|
||
🛂 {t("visa")}
|
||
</h2>
|
||
<div className="space-y-4">
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||
{t("visaExpiry")}
|
||
</label>
|
||
<input
|
||
type="date"
|
||
value={visaDate}
|
||
onChange={(e) => setVisaDate(e.target.value)}
|
||
className="w-full rounded-lg border border-gray-200 dark:border-gray-700 px-4 py-2 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
|
||
/>
|
||
</div>
|
||
<div className="p-4 rounded-xl bg-emerald-50 dark:bg-emerald-900/20 border border-emerald-200 dark:border-emerald-800/50">
|
||
<p className="text-lg font-semibold text-emerald-800 dark:text-emerald-200">
|
||
{daysLeft > 0 ? `${daysLeft} ${t("daysLeft")}` : t("expired")}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section className="rounded-2xl bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 p-6">
|
||
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-2">
|
||
🌱 {t("fireCalculator")}
|
||
</h2>
|
||
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">{t("fireDesc")}</p>
|
||
<div className="p-4 rounded-xl bg-gray-50 dark:bg-gray-800 text-center text-sm text-gray-500 dark:text-gray-400">
|
||
{t("comingSoon")}
|
||
</div>
|
||
</section>
|
||
|
||
<section className="rounded-2xl bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 p-6">
|
||
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-2">
|
||
🌤️ {t("climateFinder")}
|
||
</h2>
|
||
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">{t("climateDesc")}</p>
|
||
<div className="p-4 rounded-xl bg-gray-50 dark:bg-gray-800 text-center text-sm text-gray-500 dark:text-gray-400">
|
||
{t("comingSoon")}
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
<Footer />
|
||
</div>
|
||
);
|
||
}
|