diff options
author | polwex <polwex@sortug.com> | 2025-05-21 14:00:28 +0700 |
---|---|---|
committer | polwex <polwex@sortug.com> | 2025-05-21 14:00:28 +0700 |
commit | e839a5f61f0faa21ca8b4bd5767f7575d5e576ee (patch) | |
tree | 53e5bcc3977b6ebef687521a7ac387a89aeb21c8 /src/components/Flashcard/Card.tsx | |
parent | 4f2bd597beaa778476b84c10b571db1b13524301 (diff) |
the card flip animation is legit
Diffstat (limited to 'src/components/Flashcard/Card.tsx')
-rw-r--r-- | src/components/Flashcard/Card.tsx | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/components/Flashcard/Card.tsx b/src/components/Flashcard/Card.tsx new file mode 100644 index 0000000..7cada24 --- /dev/null +++ b/src/components/Flashcard/Card.tsx @@ -0,0 +1,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; |