feat: 完整記錄詞彙選擇題設計規格 - 為階段2擴展做準備

## 技術實作規格增強
- 🎨 完整記錄您設計的 VocabChoiceTest 組件架構
- 📋 詳細的 ChoiceGrid 響應式網格設計
- 🎯 完整的 ChoiceOption 狀態樣式系統
- 🔧 三區域設計: 問題顯示/選項網格/結果顯示

## 設計規格詳情
- 組件接口: VocabChoiceTestProps 完整定義
- 狀態管理: selectedAnswer + showResult 邏輯
- 樣式系統: 正確(綠)/錯誤(紅)/選中(藍)/默認(灰)
- 響應式: grid-cols-1 sm:grid-cols-2 自適應布局

## 階段2擴展準備
-  有完整設計規格可參考實作
-  有明確的組件分工和職責
-  有詳細的UI樣式和交互邏輯
-  受開發控制規範約束避免過度工程

為未來的階段2詞彙選擇功能提供完整的實作指南

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
鄭沛軒 2025-10-04 16:19:23 +08:00
parent 9307cb593d
commit 07a72da006
1 changed files with 157 additions and 10 deletions

View File

@ -94,25 +94,172 @@ const confidenceToScore = {
} }
``` ```
### **階段2: 詞彙選擇題 (計劃中)** ### **階段2: 詞彙選擇題 (已設計完成)**
**組件架構** (基於您的設計):
```typescript
interface VocabChoiceTestProps {
cardData: FlashcardData
options: string[] // 4選1選項
onAnswer: (answer: string) => void
onReportError: () => void
disabled?: boolean
}
// 組件分區設計
const VocabChoiceTest = () => {
const questionArea = // 問題顯示區域
const optionsArea = // 選項網格區域
const resultArea = // 結果顯示區域
return (
<ChoiceTestContainer
questionArea={questionArea}
optionsArea={optionsArea}
resultArea={resultArea}
/>
)
}
```
**問題顯示區域設計**:
```typescript
const questionArea = (
<div className="text-center">
<div className="bg-gray-50 rounded-lg p-6">
<h3 className="font-semibold text-gray-900 mb-3 text-left">定義</h3>
<p className="text-gray-700 text-left text-lg leading-relaxed">
{cardData.definition}
</p>
</div>
<p className="text-lg text-gray-700 mt-4 text-left">
請選擇符合上述定義的英文詞彙:
</p>
</div>
)
```
**狀態管理設計**:
```typescript
const [selectedAnswer, setSelectedAnswer] = useState<string | null>(null)
const [showResult, setShowResult] = useState(false)
// 答案驗證邏輯
const isCorrect = useMemo(() =>
selectedAnswer === cardData.word,
[selectedAnswer, cardData.word]
)
// 選擇處理
const handleAnswerSelect = useCallback((answer: string) => {
if (disabled || showResult) return
setSelectedAnswer(answer)
setShowResult(true)
onAnswer(answer)
}, [disabled, showResult, onAnswer])
```
**選項生成算法**: **選項生成算法**:
```typescript ```typescript
// 暫時使用固定選項 (MVP階段) // MVP階段: 固定選項
const mockOptions = ['apple', 'orange', 'banana', correctAnswer] const generateSimpleOptions = (correctWord: string): string[] => {
const shuffledOptions = shuffle(mockOptions) const fixedDistractors = ['apple', 'orange', 'banana']
``` return shuffle([correctWord, ...fixedDistractors])
}
**未來升級方案**: // 階段3升級方案: 智能干擾項
```typescript const generateSmartOptions = (correctWord: Flashcard, allWords: Flashcard[]): string[] => {
// 基於詞性和CEFR等級生成干擾項
const generateDistractors = (correctWord, allWords) => {
const samePOS = allWords.filter(w => w.partOfSpeech === correctWord.partOfSpeech) const samePOS = allWords.filter(w => w.partOfSpeech === correctWord.partOfSpeech)
const sameCEFR = allWords.filter(w => w.cefr === correctWord.cefr) const sameCEFR = allWords.filter(w => w.cefr === correctWord.cefr)
return selectRandom([...samePOS, ...sameCEFR], 3) const distractors = selectRandom([...samePOS, ...sameCEFR], 3)
return shuffle([correctWord.word, ...distractors.map(w => w.word)])
} }
``` ```
**ChoiceGrid組件設計** (您的完整設計):
```typescript
interface ChoiceGridProps {
options: string[] // 4個選項
selectedOption?: string | null
correctAnswer?: string
showResult?: boolean // 控制結果顯示
onSelect: (option: string) => void
disabled?: boolean
className?: string
}
// 響應式網格布局
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{options.map((option, index) => (
<ChoiceOption
key={`${option}-${index}`}
option={option}
index={index}
isSelected={selectedOption === option}
isCorrect={showResult && option === correctAnswer}
isIncorrect={showResult && option !== correctAnswer}
showResult={showResult}
onSelect={onSelect}
disabled={disabled}
/>
))}
</div>
```
**ChoiceOption樣式規格** (您的設計):
```typescript
// 選項按鈕狀態樣式
const getOptionStyles = (isSelected, isCorrect, isIncorrect, showResult) => {
if (showResult) {
if (isCorrect) return 'border-green-500 bg-green-50 text-green-700'
if (isIncorrect && isSelected) return 'border-red-500 bg-red-50 text-red-700'
return 'border-gray-200 bg-gray-50 text-gray-500'
}
if (isSelected) return 'border-blue-500 bg-blue-50 text-blue-700'
return 'border-gray-200 hover:border-blue-300 hover:bg-blue-50'
}
// 按鈕基礎樣式
className={`p-4 text-center rounded-lg border-2 transition-all ${getOptionStyles()}`}
```
**UI組件層次設計**:
```typescript
// 您設計的完整組件結構
<ChoiceTestContainer> // 外層容器和錯誤處理
<TestHeader title="詞彙選擇" cefr={cardData.cefr} />
<QuestionArea> // 問題顯示區域
<div className="bg-gray-50 rounded-lg p-6">
<h3>定義</h3>
<p className="text-lg leading-relaxed">{definition}</p>
</div>
<p className="text-lg mt-4">請選擇符合上述定義的英文詞彙:</p>
</QuestionArea>
<OptionsArea> // 選項區域
<ChoiceGrid // 響應式2x2網格
options={options}
selectedOption={selectedAnswer}
correctAnswer={cardData.word}
showResult={showResult}
onSelect={handleAnswerSelect}
disabled={disabled}
/>
</OptionsArea>
<ResultArea> // 結果顯示區域
{showResult && (
<TestResultDisplay
isCorrect={isCorrect}
correctAnswer={cardData.word}
userAnswer={selectedAnswer}
pronunciation={cardData.pronunciation}
example={cardData.example}
/>
)}
</ResultArea>
</ChoiceTestContainer>
```
--- ---
## 🎨 **UI/UX實作規格** ## 🎨 **UI/UX實作規格**