89 lines
3.1 KiB
TypeScript
89 lines
3.1 KiB
TypeScript
import { useMemo, useCallback } from 'react'
|
||
import { getCEFRColor } from '@/lib/utils/flashcardUtils'
|
||
import type { WordAnalysis } from '@/lib/types/word'
|
||
|
||
export function useWordAnalysis() {
|
||
const getWordProperty = useCallback((analysis: WordAnalysis, property: keyof WordAnalysis, fallback: any = 'N/A') => {
|
||
if (!analysis) return fallback
|
||
const value = analysis[property]
|
||
|
||
if (value === undefined || value === null || value === '') {
|
||
return fallback
|
||
}
|
||
|
||
if (Array.isArray(value) && value.length === 0) {
|
||
return fallback
|
||
}
|
||
|
||
return value
|
||
}, [])
|
||
|
||
const findWordAnalysis = useCallback((word: string, analysis: Record<string, WordAnalysis> = {}) => {
|
||
const cleanWord = word.toLowerCase().replace(/[^\w]/g, '')
|
||
|
||
const directMatch = analysis[word] || analysis[cleanWord]
|
||
if (directMatch) return directMatch
|
||
|
||
const keys = Object.keys(analysis)
|
||
const matchKey = keys.find(key =>
|
||
key.toLowerCase().replace(/[^\w]/g, '') === cleanWord
|
||
)
|
||
|
||
return matchKey ? analysis[matchKey] : null
|
||
}, [])
|
||
|
||
const getWordClass = useCallback((word: string, analysis: Record<string, WordAnalysis> = {}, userLevel: string = 'A2') => {
|
||
const wordAnalysis = findWordAnalysis(word, analysis)
|
||
if (!wordAnalysis) return 'cursor-default text-gray-900'
|
||
|
||
// 基礎按鈕樣式 - 類似慣用語區塊
|
||
let classes = 'cursor-pointer transition-all duration-200 rounded px-1 py-0.5 border font-medium hover:shadow-md transform hover:-translate-y-0.5 '
|
||
|
||
if (wordAnalysis.isIdiom) {
|
||
classes += 'bg-purple-50 text-purple-700 border-purple-200 hover:bg-purple-100'
|
||
} else {
|
||
// 根據用戶等級與詞彙等級的相對關係設置顏色
|
||
const cefr = wordAnalysis.cefr || 'A1'
|
||
const levelOrder = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2']
|
||
const userLevelIndex = levelOrder.indexOf(userLevel)
|
||
const wordLevelIndex = levelOrder.indexOf(cefr)
|
||
const levelDiff = wordLevelIndex - userLevelIndex
|
||
|
||
if (levelDiff <= -1) {
|
||
// 太簡單(低於用戶等級)- 綠色
|
||
classes += 'bg-green-50 text-green-700 border-green-200 hover:bg-green-100'
|
||
} else if (levelDiff === 0) {
|
||
// 適中(等於用戶等級)- 藍色
|
||
classes += 'bg-blue-50 text-blue-700 border-blue-200 hover:bg-blue-100'
|
||
} else if (levelDiff === 1) {
|
||
// 挑戰(高1級)- 橘色
|
||
classes += 'bg-orange-50 text-orange-700 border-orange-200 hover:bg-orange-100'
|
||
} else {
|
||
// 困難(高2級以上)- 紅色
|
||
classes += 'bg-red-50 text-red-700 border-red-200 hover:bg-red-100'
|
||
}
|
||
}
|
||
|
||
return classes
|
||
}, [findWordAnalysis])
|
||
|
||
const shouldShowStar = useCallback((analysis: WordAnalysis) => {
|
||
if (!analysis) return false
|
||
|
||
const conditions = [
|
||
analysis.isHighValue,
|
||
analysis.learningPriority === 'high',
|
||
analysis.cefr && ['B2', 'C1', 'C2'].includes(analysis.cefr),
|
||
analysis.frequency === 'high'
|
||
]
|
||
|
||
return conditions.some(Boolean)
|
||
}, [])
|
||
|
||
return {
|
||
getWordProperty,
|
||
findWordAnalysis,
|
||
getWordClass,
|
||
shouldShowStar
|
||
}
|
||
} |