1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
"use client";
import { CardResponse } from "@/lib/types/cards";
// export default function ({ user }: { user: { name: string; id: number } }) {
// const [state, formAction, isPending] = useActionState(postLogout, 0);
// return (
// <form action={formAction}>
// <Card>
// <CardHeader>
// <CardTitle>Profile</CardTitle>
// {state}
// </CardHeader>
// <CardContent>
// <p>Username: {user.name}</p>
// <p>User ID: {user.id}</p>
// </CardContent>
// <CardFooter>
// <Button type="submit">Log out</Button>
// </CardFooter>
// </Card>
// </form>
// );
// }
// "use client";
// --- Flashcard Component ---
interface FlashcardProps {
data: CardResponse;
isFlipped: boolean;
onFlip: () => void;
animationDirection:
| "enter-left"
| "enter-right"
| "exit-left"
| "exit-right"
| "none";
}
const Flashcard: React.FC<FlashcardProps> = ({
data,
isFlipped,
onFlip,
animationDirection,
}) => {
const getAnimationClass = () => {
switch (animationDirection) {
case "enter-right":
return "animate-slide-in-right";
case "enter-left":
return "animate-slide-in-left";
case "exit-right":
return "animate-slide-out-right";
case "exit-left":
return "animate-slide-out-left";
default:
return "";
}
};
return (
<div
className={`w-full max-w-md h-80 perspective group ${getAnimationClass()}`}
onClick={onFlip}
>
<div
className={`relative w-full h-full rounded-xl shadow-xl transition-transform duration-700 ease-in-out transform-style-preserve-3d cursor-pointer ${
isFlipped ? "rotate-y-180" : ""
}`}
>
{/* Front of the card */}
<div className="absolute w-full h-full bg-white dark:bg-slate-800 rounded-xl backface-hidden flex flex-col justify-between items-center p-6">
<span className="text-xs text-slate-500 dark:text-slate-400 self-start">
{data.expression.ipa.map((ip, i) => (
<span key={ip.ipa + i} className="ipa">
{ip.ipa}
</span>
))}
</span>
<p className="text-3xl md:text-4xl font-semibold text-slate-800 dark:text-slate-100 text-center">
{data.expression.spelling}
</p>
<div className="w-full h-6">
{" "}
{/* Placeholder for spacing, mimics bottom controls */}
<span className="text-xs text-slate-400 dark:text-slate-500 self-end invisible">
Flip
</span>
</div>
</div>
{/* Back of the card */}
<div className="absolute w-full h-full bg-slate-50 dark:bg-slate-700 rounded-xl backface-hidden rotate-y-180 flex flex-col justify-between items-center p-6">
<span className="text-lg text-slate-500 dark:text-slate-400 self-start">
{data.expression.senses.map((ss, i) => (
<div key={`ss${i}`}>
{ss.senses.map((sss, i) => (
<div key={`sss${i}`}>
{sss.glosses.map((ssss, i) => (
<p key={ssss + i}>{ssss}</p>
))}
</div>
))}
</div>
))}
</span>
<p className="text-3xl md:text-4xl font-semibold text-slate-800 dark:text-slate-100 text-center">
{data.note}
</p>
<div className="w-full h-6">
<span className="text-xs text-slate-400 dark:text-slate-500 self-end invisible">
Flip
</span>
</div>
</div>
</div>
</div>
);
};
export default Flashcard;
|