Files
english/src/features/flash-card/components/FlashCard.tsx
2026-04-15 00:41:02 +07:00

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