From 274a7bbb1f82e99cdc9876f6d0de430585282797 Mon Sep 17 00:00:00 2001
From: polwex <polwex@sortug.com>
Date: Sat, 16 Aug 2025 13:38:27 +0700
Subject: beautiful flip animation by chatgpt

---
 src/components/tones/ToneSelectorClient.tsx | 119 +++++++++++++++++++---------
 1 file changed, 81 insertions(+), 38 deletions(-)

(limited to 'src/components/tones/ToneSelectorClient.tsx')

diff --git a/src/components/tones/ToneSelectorClient.tsx b/src/components/tones/ToneSelectorClient.tsx
index 48580a4..8abbd38 100644
--- a/src/components/tones/ToneSelectorClient.tsx
+++ b/src/components/tones/ToneSelectorClient.tsx
@@ -27,7 +27,7 @@ import { Label } from "@/components/ui/label";
 import { Skeleton } from "@/components/ui/skeleton"; // For loading state
 import { MutationOrder, ToneQuery } from "@/lib/types/phonetics";
 import { ProsodySyllable } from "@/lib/types/cards";
-import { ArrowLeft, ArrowRight, Volume2 } from "lucide-react";
+import { ArrowLeft, ArrowRight, Volume2, FlipHorizontal2 } from "lucide-react";
 
 function getColorByTone(tone: string): string {
   if (tone === "mid") return "blue";
@@ -192,43 +192,86 @@ type IProps = {
   goNext: () => void;
 };
 function Inner({ isLoading, currentWord, goPrev, goNext }: IProps) {
-  return isLoading ? (
-    <Card>
-      <CardHeader>
-        <Skeleton className="h-12 w-3/4" />
-      </CardHeader>
-      <CardContent className="space-y-4">
-        <Skeleton className="h-8 w-1/2" />
-        <Skeleton className="h-20 w-full" />
-        <Skeleton className="h-6 w-full" />
-      </CardContent>
-    </Card>
-  ) : currentWord ? (
-    <Card>
-      <CardHeader>
-        <CardTitle className="text-center">Current Word</CardTitle>
-      </CardHeader>
-      <CardContent>
-        <ProminentToneDisplay word={currentWord} />
-        {/* You can add more details from WordData here if needed, like definitions */}
-      </CardContent>
-      <CardFooter className="justify-between">
-        <ArrowLeft onClick={goPrev} />
-        <ArrowRight onClick={goNext} />
-      </CardFooter>
-    </Card>
-  ) : (
-    <Card>
-      <CardHeader>
-        <CardTitle className="text-center">No Word Found</CardTitle>
-      </CardHeader>
-      <CardContent>
-        <p className="text-center text-gray-600">
-          Could not find a Thai word matching your criteria. Try different
-          selections.
-        </p>
-      </CardContent>
-    </Card>
+  const [isFlipped, setIsFlipped] = useState(false);
+  const toggleFlip = () => setIsFlipped((f) => !f);
+
+  if (isLoading) {
+    return (
+      <Card>
+        <CardHeader>
+          <Skeleton className="h-12 w-3/4" />
+        </CardHeader>
+        <CardContent className="space-y-4">
+          <Skeleton className="h-8 w-1/2" />
+          <Skeleton className="h-20 w-full" />
+          <Skeleton className="h-6 w-full" />
+        </CardContent>
+      </Card>
+    );
+  }
+
+  if (!currentWord) {
+    return (
+      <Card>
+        <CardHeader>
+          <CardTitle className="text-center">No Word Found</CardTitle>
+        </CardHeader>
+        <CardContent>
+          <p className="text-center text-gray-600">
+            Could not find a Thai word matching your criteria. Try different
+            selections.
+          </p>
+        </CardContent>
+      </Card>
+    );
+  }
+
+  return (
+    <div className="relative w-full max-w-2xl mx-auto h-100 perspective">
+      <button
+        type="button"
+        onClick={toggleFlip}
+        className="absolute z-20 top-2 right-2 p-2 rounded-md hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors"
+        title="Flip"
+      >
+        <FlipHorizontal2 size={18} />
+      </button>
+      <div
+        className={`relative w-full h-full rounded-xl shadow-xl transition-transform duration-700 ease-in-out transform-style-preserve-3d ${
+          isFlipped ? "rotate-y-180" : ""
+        }`}
+      >
+        {/* Front */}
+        <div className="absolute inset-0 bg-white dark:bg-slate-800 rounded-xl backface-hidden flex flex-col">
+          <div className="px-6 pt-6 pb-2">
+            <h3 className="text-center text-lg font-semibold">Current Word</h3>
+          </div>
+          <div className="flex-1 px-6 overflow-auto">
+            <ProminentToneDisplay word={currentWord} />
+          </div>
+          <div className="px-6 py-4 flex items-center justify-between">
+            <ArrowLeft onClick={goPrev} className="cursor-pointer" />
+            <ArrowRight onClick={goNext} className="cursor-pointer" />
+          </div>
+        </div>
+
+        {/* Back */}
+        <div className="absolute inset-0 bg-slate-50 dark:bg-slate-700 rounded-xl backface-hidden rotate-y-180 flex flex-col">
+          <div className="px-6 pt-6 pb-2">
+            <h3 className="text-center text-lg font-semibold">Details</h3>
+          </div>
+          <div className="flex-1 px-6 py-2 overflow-auto text-sm text-slate-700 dark:text-slate-100">
+            {/* Placeholder for user-provided data */}
+            <pre className="whitespace-pre-wrap break-words text-xs opacity-80">
+              {JSON.stringify(currentWord, null, 2)}
+            </pre>
+          </div>
+          <div className="px-6 py-4 flex items-center justify-center text-xs opacity-60">
+            Back of card – replace with your data
+          </div>
+        </div>
+      </div>
+    </div>
   );
 }
 
-- 
cgit v1.2.3

