151 lines
4.9 KiB
TypeScript
151 lines
4.9 KiB
TypeScript
'use client'
|
|
|
|
import React, { useState, useCallback } from 'react'
|
|
import { SyllableBow, simpleSyllableSplit } from './SyllableBow'
|
|
|
|
interface FlashCardProps {
|
|
front: string
|
|
back: string
|
|
cardNumber: number
|
|
totalCards: number
|
|
leitnerBox: number
|
|
onCorrect: () => void
|
|
onIncorrect: () => void
|
|
isDark: boolean
|
|
syllablesFront?: string[]
|
|
syllablesBack?: string[]
|
|
ipaFront?: string
|
|
ipaBack?: string
|
|
}
|
|
|
|
const boxLabels = ['Neu', 'Gelernt', 'Gefestigt']
|
|
const boxColors = ['text-yellow-400', 'text-blue-400', 'text-green-400']
|
|
|
|
export function FlashCard({
|
|
front,
|
|
back,
|
|
cardNumber,
|
|
totalCards,
|
|
leitnerBox,
|
|
onCorrect,
|
|
onIncorrect,
|
|
isDark,
|
|
syllablesFront,
|
|
syllablesBack,
|
|
ipaFront,
|
|
ipaBack,
|
|
}: FlashCardProps) {
|
|
const [isFlipped, setIsFlipped] = useState(false)
|
|
|
|
const handleFlip = useCallback(() => {
|
|
setIsFlipped((f) => !f)
|
|
}, [])
|
|
|
|
const handleCorrect = useCallback(() => {
|
|
setIsFlipped(false)
|
|
onCorrect()
|
|
}, [onCorrect])
|
|
|
|
const handleIncorrect = useCallback(() => {
|
|
setIsFlipped(false)
|
|
onIncorrect()
|
|
}, [onIncorrect])
|
|
|
|
return (
|
|
<div className="flex flex-col items-center gap-6 w-full max-w-lg mx-auto">
|
|
{/* Card */}
|
|
<div
|
|
onClick={handleFlip}
|
|
className="w-full cursor-pointer select-none"
|
|
style={{ perspective: '1000px' }}
|
|
>
|
|
<div
|
|
className="relative w-full transition-transform duration-500"
|
|
style={{
|
|
transformStyle: 'preserve-3d',
|
|
transform: isFlipped ? 'rotateY(180deg)' : 'rotateY(0deg)',
|
|
}}
|
|
>
|
|
{/* Front */}
|
|
<div
|
|
className={`w-full min-h-[280px] rounded-3xl p-8 flex flex-col items-center justify-center ${
|
|
isDark
|
|
? 'bg-white/10 backdrop-blur-xl border border-white/20'
|
|
: 'bg-white shadow-xl border border-slate-200'
|
|
}`}
|
|
style={{ backfaceVisibility: 'hidden' }}
|
|
>
|
|
<span className={`text-xs font-medium mb-4 ${isDark ? 'text-white/40' : 'text-slate-400'}`}>
|
|
ENGLISCH
|
|
</span>
|
|
{syllablesFront && syllablesFront.length > 0 ? (
|
|
<SyllableBow word={front} syllables={syllablesFront} isDark={isDark} size="md" />
|
|
) : (
|
|
<span className={`text-3xl font-bold text-center ${isDark ? 'text-white' : 'text-slate-900'}`}>
|
|
{front}
|
|
</span>
|
|
)}
|
|
{ipaFront && <span className={`text-sm mt-2 ${isDark ? 'text-white/30' : 'text-slate-400'}`}>{ipaFront}</span>}
|
|
<span className={`text-sm mt-4 ${isDark ? 'text-white/30' : 'text-slate-400'}`}>
|
|
Klick zum Umdrehen
|
|
</span>
|
|
</div>
|
|
|
|
{/* Back */}
|
|
<div
|
|
className={`w-full min-h-[280px] rounded-3xl p-8 flex flex-col items-center justify-center absolute inset-0 ${
|
|
isDark
|
|
? 'bg-gradient-to-br from-blue-500/20 to-cyan-500/20 backdrop-blur-xl border border-blue-400/30'
|
|
: 'bg-gradient-to-br from-blue-50 to-cyan-50 shadow-xl border border-blue-200'
|
|
}`}
|
|
style={{ backfaceVisibility: 'hidden', transform: 'rotateY(180deg)' }}
|
|
>
|
|
<span className={`text-xs font-medium mb-4 ${isDark ? 'text-blue-300/60' : 'text-blue-500'}`}>
|
|
DEUTSCH
|
|
</span>
|
|
<span className={`text-3xl font-bold text-center ${isDark ? 'text-white' : 'text-slate-900'}`}>
|
|
{back}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Status Bar */}
|
|
<div className={`flex items-center justify-between w-full px-2 ${isDark ? 'text-white/50' : 'text-slate-500'}`}>
|
|
<span className="text-sm">
|
|
Karte {cardNumber} von {totalCards}
|
|
</span>
|
|
<span className={`text-sm font-medium ${boxColors[leitnerBox] || boxColors[0]}`}>
|
|
Box: {boxLabels[leitnerBox] || boxLabels[0]}
|
|
</span>
|
|
</div>
|
|
|
|
{/* Progress */}
|
|
<div className="w-full h-1.5 rounded-full bg-white/10 overflow-hidden">
|
|
<div
|
|
className="h-full rounded-full bg-gradient-to-r from-blue-500 to-cyan-500 transition-all"
|
|
style={{ width: `${(cardNumber / totalCards) * 100}%` }}
|
|
/>
|
|
</div>
|
|
|
|
{/* Answer Buttons */}
|
|
{isFlipped && (
|
|
<div className="flex gap-4 w-full">
|
|
<button
|
|
onClick={handleIncorrect}
|
|
className="flex-1 py-4 rounded-2xl font-semibold text-lg transition-all bg-gradient-to-r from-red-500 to-rose-500 text-white hover:shadow-lg hover:shadow-red-500/25 hover:scale-[1.02]"
|
|
>
|
|
Falsch
|
|
</button>
|
|
<button
|
|
onClick={handleCorrect}
|
|
className="flex-1 py-4 rounded-2xl font-semibold text-lg transition-all bg-gradient-to-r from-green-500 to-emerald-500 text-white hover:shadow-lg hover:shadow-green-500/25 hover:scale-[1.02]"
|
|
>
|
|
Richtig
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|