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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
"use client";
import { thaiAnalysis } from "@/actions/lang";
import { CardResponse } from "@/lib/types/cards";
import { useTransition } from "react";
import { Spinner } from "../ui/spinner";
// 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 "";
}
};
const [isPending, startTransition] = useTransition();
const handleClick = () => {
startTransition(async () => {
const res = await thaiAnalysis(data.expression.spelling);
});
};
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
onClick={handleClick}
className="text-3xl cursor-pointer hover:text-blue-700 md:text-4xl font-semibold text-slate-800 dark:text-slate-100 text-center"
>
{data.expression.spelling}
</p>
{isPending && <Spinner />}
<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;
|