dramaling-vocab-learning/frontend/components/generate/IdiomDisplaySection.tsx

71 lines
2.3 KiB
TypeScript

import React from 'react'
import { ContentBlock } from '@/components/shared/ContentBlock'
import { compareCEFRLevels } from '@/lib/utils/cefrUtils'
interface IdiomAnalysis {
idiom: string
translation: string
meaning: string
cefrLevel?: string
frequency?: string
[key: string]: any
}
interface IdiomDisplaySectionProps {
idioms: IdiomAnalysis[]
onIdiomClick: (idiom: IdiomAnalysis, position: { x: number; y: number }) => void
className?: string
}
export const IdiomDisplaySection: React.FC<IdiomDisplaySectionProps> = ({
idioms,
onIdiomClick,
className = ''
}) => {
if (!idioms || idioms.length === 0) {
return null
}
const handleIdiomClick = (idiom: IdiomAnalysis, event: React.MouseEvent<HTMLSpanElement>) => {
const rect = event.currentTarget.getBoundingClientRect()
const position = {
x: rect.left + rect.width / 2,
y: rect.bottom + 10
}
onIdiomClick(idiom, position)
}
const shouldShowStar = (idiom: IdiomAnalysis) => {
const userLevel = localStorage.getItem('userEnglishLevel') || 'A2'
const isHighFrequency = idiom?.frequency === 'high'
const idiomCefr = idiom?.cefrLevel || 'A1'
const isNotSimpleIdiom = !compareCEFRLevels(userLevel, idiomCefr, '>')
return isHighFrequency && isNotSimpleIdiom
}
return (
<ContentBlock title="慣用語" variant="gray" className={className}>
<div className="flex flex-wrap gap-2">
{idioms.map((idiom: IdiomAnalysis, index: number) => (
<span
key={index}
className="cursor-pointer transition-all duration-200 rounded-lg relative mx-0.5 px-1 py-0.5 inline-flex items-center gap-1 bg-blue-50 border border-blue-200 hover:bg-blue-100 hover:shadow-lg transform hover:-translate-y-0.5 text-blue-700 font-medium"
onClick={(e) => handleIdiomClick(idiom, e)}
title={`${idiom.idiom}: ${idiom.translation}`}
>
{idiom.idiom}
{shouldShowStar(idiom) && (
<span
className="absolute -top-1 -right-1 text-xs pointer-events-none z-10"
style={{ fontSize: '8px', lineHeight: 1 }}
>
</span>
)}
</span>
))}
</div>
</ContentBlock>
)
}