dramaling-vocab-learning/frontend/hooks/word/useWordAnalysis.ts

89 lines
3.1 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.

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
}
}