60 lines
2.2 KiB
TypeScript
60 lines
2.2 KiB
TypeScript
import { cn } from '@/lib/utils'
|
|
|
|
interface FlashCardProps {
|
|
word: string
|
|
phonetic: string
|
|
meaningVi: string
|
|
example: string
|
|
topicBadge: string
|
|
isFlipped: boolean
|
|
onFlip: () => void
|
|
}
|
|
|
|
/** 3D flip flashcard. Front shows word/phonetic; back shows Vietnamese meaning + example. */
|
|
export function FlashCard({ word, phonetic, meaningVi, example, topicBadge, isFlipped, onFlip }: FlashCardProps) {
|
|
const highlightedExample = example.replace(
|
|
new RegExp(`\\b${word}\\b`, 'gi'),
|
|
(match) => `<strong>${match}</strong>`,
|
|
)
|
|
|
|
return (
|
|
<div
|
|
className="flashcard-scene w-full cursor-pointer select-none"
|
|
style={{ height: 280 }}
|
|
onClick={onFlip}
|
|
role="button"
|
|
aria-label={isFlipped ? 'Nhấn để xem từ' : 'Nhấn để xem nghĩa'}
|
|
>
|
|
<div className={cn('flashcard-inner w-full h-full', isFlipped && 'is-flipped')}>
|
|
{/* Front */}
|
|
<div className="flashcard-face bg-white border border-slate-200 shadow-lg flex flex-col items-center justify-center p-8">
|
|
<div className="text-4xl font-extrabold text-slate-800 mb-2">{word}</div>
|
|
<div className="text-slate-400 text-lg mb-4">{phonetic}</div>
|
|
<span className="bg-blue-50 text-blue-600 text-xs font-bold px-3 py-1 rounded-full">
|
|
{topicBadge}
|
|
</span>
|
|
<p className="mt-6 text-xs text-slate-400 flex items-center gap-1">
|
|
<span className="material-symbols-outlined" style={{ fontSize: 14 }}>touch_app</span>
|
|
Nhấn để xem nghĩa
|
|
</p>
|
|
</div>
|
|
|
|
{/* Back */}
|
|
<div
|
|
className="flashcard-face flashcard-back flex flex-col items-center justify-center p-8"
|
|
style={{ background: 'linear-gradient(135deg, #eff6ff, #dbeafe)' }}
|
|
>
|
|
<div className="text-3xl font-extrabold text-blue-600 mb-1">{meaningVi}</div>
|
|
<div className="text-xs text-slate-400 font-semibold uppercase tracking-wide mb-4">
|
|
Nghĩa tiếng Việt
|
|
</div>
|
|
<div
|
|
className="bg-white rounded-xl p-3 border border-blue-100 text-sm text-slate-500 italic text-center"
|
|
dangerouslySetInnerHTML={{ __html: `"${highlightedExample}"` }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|