87 lines
2.8 KiB
TypeScript
87 lines
2.8 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> = {}) => {
|
|
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 {
|
|
// 根據 CEFR 等級設置顏色主題
|
|
const cefr = wordAnalysis.cefr || 'A1'
|
|
switch (cefr) {
|
|
case 'A1':
|
|
case 'A2':
|
|
classes += 'bg-green-50 text-green-700 border-green-200 hover:bg-green-100'
|
|
break
|
|
case 'B1':
|
|
case 'B2':
|
|
classes += 'bg-blue-50 text-blue-700 border-blue-200 hover:bg-blue-100'
|
|
break
|
|
case 'C1':
|
|
case 'C2':
|
|
classes += 'bg-red-50 text-red-700 border-red-200 hover:bg-red-100'
|
|
break
|
|
default:
|
|
classes += 'bg-gray-50 text-gray-700 border-gray-200 hover:bg-gray-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
|
|
}
|
|
} |