dramaling-vocab-learning/frontend/app/settings/page.tsx

209 lines
7.0 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 { useState, useEffect } from 'react'
interface LanguageLevel {
value: string;
label: string;
description: string;
examples: string[];
}
export default function SettingsPage() {
const [userLevel, setUserLevel] = useState('A2');
const [isLoading, setIsLoading] = useState(false);
const levels: LanguageLevel[] = [
{
value: 'A1',
label: 'A1 - 初學者',
description: '能理解基本詞彙和簡單句子',
examples: ['hello', 'good', 'house', 'eat', 'happy']
},
{
value: 'A2',
label: 'A2 - 基礎',
description: '能處理日常對話和常見主題',
examples: ['important', 'difficult', 'interesting', 'beautiful', 'understand']
},
{
value: 'B1',
label: 'B1 - 中級',
description: '能理解清楚標準語言的要點',
examples: ['analyze', 'opportunity', 'environment', 'responsibility', 'development']
},
{
value: 'B2',
label: 'B2 - 中高級',
description: '能理解複雜文本的主要內容',
examples: ['sophisticated', 'implications', 'comprehensive', 'substantial', 'methodology']
},
{
value: 'C1',
label: 'C1 - 高級',
description: '能流利表達,理解含蓄意思',
examples: ['meticulous', 'predominantly', 'intricate', 'corroborate', 'paradigm']
},
{
value: 'C2',
label: 'C2 - 精通',
description: '接近母語水平',
examples: ['ubiquitous', 'ephemeral', 'perspicacious', 'multifarious', 'idiosyncratic']
}
];
// 載入用戶已設定的程度
useEffect(() => {
const savedLevel = localStorage.getItem('userEnglishLevel');
if (savedLevel) {
setUserLevel(savedLevel);
}
}, []);
const saveUserLevel = async () => {
setIsLoading(true);
try {
// 保存到本地存儲
localStorage.setItem('userEnglishLevel', userLevel);
// TODO: 如果用戶已登入,也保存到伺服器
// const token = localStorage.getItem('authToken');
// if (token) {
// await fetch('/api/user/update-level', {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json',
// 'Authorization': `Bearer ${token}`
// },
// body: JSON.stringify({ englishLevel: userLevel })
// });
// }
alert('✅ 程度設定已保存!系統將為您提供個人化的詞彙標記。');
} catch (error) {
console.error('Error saving user level:', error);
alert('❌ 保存失敗,請稍後再試');
} finally {
setIsLoading(false);
}
};
const getHighValueRange = (level: string) => {
const ranges = {
'A1': 'A2-B1',
'A2': 'B1-B2',
'B1': 'B2-C1',
'B2': 'C1-C2',
'C1': 'C2',
'C2': 'C2'
};
return ranges[level as keyof typeof ranges] || 'B1-B2';
};
return (
<div className="max-w-4xl mx-auto p-6">
<div className="mb-8">
<h1 className="text-3xl font-bold mb-4">🎯 </h1>
<p className="text-gray-600">
1-2
</p>
</div>
<div className="grid gap-4 mb-8">
{levels.map(level => (
<label
key={level.value}
className={`
p-6 border-2 rounded-xl cursor-pointer transition-all hover:shadow-md
${userLevel === level.value
? 'border-blue-500 bg-blue-50 shadow-md'
: 'border-gray-200 hover:border-gray-300'
}
`}
>
<input
type="radio"
name="level"
value={level.value}
checked={userLevel === level.value}
onChange={(e) => setUserLevel(e.target.value)}
className="sr-only"
/>
<div className="flex items-start justify-between">
<div className="flex-1">
<div className="font-bold text-xl text-gray-800 mb-2">
{level.label}
</div>
<div className="text-gray-600 mb-3">
{level.description}
</div>
<div className="flex flex-wrap gap-2">
{level.examples.map(example => (
<span
key={example}
className="px-3 py-1 bg-gray-100 text-gray-700 rounded-full text-sm"
>
{example}
</span>
))}
</div>
</div>
{userLevel === level.value && (
<div className="ml-4">
<div className="w-6 h-6 bg-blue-500 rounded-full flex items-center justify-center">
<svg className="w-4 h-4 text-white" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
</svg>
</div>
</div>
)}
</div>
</label>
))}
</div>
{/* 個人化效果預覽 */}
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 p-6 rounded-xl mb-8">
<h3 className="font-bold text-lg text-blue-800 mb-3">
💡
</h3>
<div className="grid md:grid-cols-2 gap-4">
<div>
<h4 className="font-semibold text-blue-700 mb-2"></h4>
<p className="text-blue-600">
<span className="font-bold">{getHighValueRange(userLevel)}</span>
</p>
</div>
<div>
<h4 className="font-semibold text-blue-700 mb-2"></h4>
<p className="text-blue-600 text-sm">
({userLevel})1-2
</p>
</div>
</div>
</div>
<button
onClick={saveUserLevel}
disabled={isLoading}
className={`
w-full py-4 rounded-xl font-semibold text-lg transition-all
${isLoading
? 'bg-gray-300 text-gray-500 cursor-not-allowed'
: 'bg-blue-500 text-white hover:bg-blue-600 shadow-lg hover:shadow-xl'
}
`}
>
{isLoading ? '⏳ 保存中...' : '✅ 保存程度設定'}
</button>
<div className="mt-4 text-center">
<p className="text-sm text-gray-500">
💡 提示: 您隨時可以回到這裡調整程度設定
</p>
</div>
</div>
);
}