143 lines
5.4 KiB
TypeScript
143 lines
5.4 KiB
TypeScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
|
||
const QUESTIONS = [
|
||
{
|
||
q: "你的远程工作收入是否稳定?",
|
||
options: [
|
||
{ label: "非常稳定,有固定客户/薪资", score: 25, emoji: "💪" },
|
||
{ label: "基本稳定,偶尔波动", score: 18, emoji: "👍" },
|
||
{ label: "还在起步阶段", score: 8, emoji: "🌱" },
|
||
],
|
||
},
|
||
{
|
||
q: "你的月预算大约多少?",
|
||
options: [
|
||
{ label: "¥5,000 以下", score: 20, emoji: "💰" },
|
||
{ label: "¥5,000 – 10,000", score: 22, emoji: "💳" },
|
||
{ label: "¥10,000 以上", score: 25, emoji: "💎" },
|
||
],
|
||
},
|
||
{
|
||
q: "你对签证/税务了解多少?",
|
||
options: [
|
||
{ label: "已研究清楚,有方案", score: 25, emoji: "📋" },
|
||
{ label: "了解基础,还需深入", score: 15, emoji: "📖" },
|
||
{ label: "完全不了解", score: 5, emoji: "❓" },
|
||
],
|
||
},
|
||
{
|
||
q: "你的英语/沟通能力如何?",
|
||
options: [
|
||
{ label: "流利,可无障碍交流", score: 25, emoji: "🗣️" },
|
||
{ label: "基础够用,能应对日常", score: 15, emoji: "💬" },
|
||
{ label: "需要提升", score: 8, emoji: "📚" },
|
||
],
|
||
},
|
||
{
|
||
q: "你愿意离开舒适区吗?",
|
||
options: [
|
||
{ label: "非常期待新体验", score: 25, emoji: "🚀" },
|
||
{ label: "愿意尝试,略有顾虑", score: 18, emoji: "🌤️" },
|
||
{ label: "更喜欢熟悉的环境", score: 8, emoji: "🏠" },
|
||
],
|
||
},
|
||
];
|
||
|
||
const LEVELS = [
|
||
{ min: 0, max: 40, label: "🌱 萌芽游民", desc: "建议先从短期旅居开始,选择清迈或巴厘岛积累经验", color: "#FF6B6B" },
|
||
{ min: 41, max: 70, label: "🌤️ 准游民", desc: "你已经具备基础条件,可以规划 3-6 个月的旅居试点", color: "#FFE66D" },
|
||
{ min: 71, max: 90, label: "🚀 就绪游民", desc: "条件成熟!可以开始规划你的环球旅居之旅了", color: "#4ECDC4" },
|
||
{ min: 91, max: 100, label: "👑 资深游民", desc: "你就是为这种生活而生的!随时可以出发", color: "#A78BFA" },
|
||
];
|
||
|
||
export default function NomadScore() {
|
||
const [step, setStep] = useState(0);
|
||
const [scores, setScores] = useState<number[]>([]);
|
||
const [done, setDone] = useState(false);
|
||
const [animating, setAnimating] = useState(false);
|
||
|
||
const totalScore = scores.reduce((a, b) => a + b, 0);
|
||
const maxScore = QUESTIONS.length * 25;
|
||
const pct = Math.round((totalScore / maxScore) * 100);
|
||
const level = LEVELS.find((l) => pct >= l.min && pct <= l.max) || LEVELS[LEVELS.length - 1];
|
||
|
||
const select = (score: number) => {
|
||
setAnimating(true);
|
||
const next = [...scores, score];
|
||
setScores(next);
|
||
setTimeout(() => {
|
||
setAnimating(false);
|
||
if (step < QUESTIONS.length - 1) setStep(step + 1);
|
||
else setDone(true);
|
||
}, 300);
|
||
};
|
||
|
||
const reset = () => {
|
||
setStep(0);
|
||
setScores([]);
|
||
setDone(false);
|
||
};
|
||
|
||
return (
|
||
<section className="section nomad-score-section" id="nomad-score">
|
||
<div className="container">
|
||
<div className="section-header reveal">
|
||
<span className="section-tag">📊 READINESS</span>
|
||
<h2>游民就绪度测评</h2>
|
||
<p>5 个问题,测测你离数字游民生活还有多远</p>
|
||
</div>
|
||
|
||
<div className="nomad-score-card reveal">
|
||
{!done ? (
|
||
<div className={`nomad-quiz${animating ? " animating" : ""}`}>
|
||
<div className="nomad-quiz-progress">
|
||
{QUESTIONS.map((_, i) => (
|
||
<div key={i} className={`nomad-quiz-dot${i <= step ? " filled" : ""}${i === step ? " current" : ""}`} />
|
||
))}
|
||
</div>
|
||
<span className="nomad-quiz-step">问题 {step + 1} / {QUESTIONS.length}</span>
|
||
<h3>{QUESTIONS[step].q}</h3>
|
||
<div className="nomad-quiz-options">
|
||
{QUESTIONS[step].options.map((opt) => (
|
||
<button key={opt.label} className="nomad-quiz-option" onClick={() => select(opt.score)}>
|
||
<span>{opt.emoji}</span>
|
||
<span>{opt.label}</span>
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
) : (
|
||
<div className="nomad-result">
|
||
<div className="nomad-score-ring" style={{ "--score-color": level.color } as React.CSSProperties}>
|
||
<svg viewBox="0 0 120 120">
|
||
<circle cx="60" cy="60" r="52" fill="none" stroke="rgba(255,255,255,0.06)" strokeWidth="8" />
|
||
<circle
|
||
cx="60" cy="60" r="52" fill="none"
|
||
stroke={level.color} strokeWidth="8"
|
||
strokeLinecap="round"
|
||
strokeDasharray={`${pct * 3.27} 327`}
|
||
transform="rotate(-90 60 60)"
|
||
className="nomad-score-arc"
|
||
/>
|
||
</svg>
|
||
<div className="nomad-score-center">
|
||
<strong>{pct}</strong>
|
||
<span>就绪度</span>
|
||
</div>
|
||
</div>
|
||
<h3 className="nomad-level-label">{level.label}</h3>
|
||
<p className="nomad-level-desc">{level.desc}</p>
|
||
<div className="nomad-result-actions">
|
||
<button className="btn btn-ghost" onClick={reset}>🔄 重新测评</button>
|
||
<a href="#destinations" className="btn btn-primary">探索目的地 🌍</a>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
);
|
||
}
|