From ba2dbc660c229d3e86662d35513dfa7c904d9870 Mon Sep 17 00:00:00 2001
From: polwex <polwex@sortug.com>
Date: Sun, 23 Nov 2025 13:29:28 +0700
Subject: wew

---
 .../src/components/word/FullWordData.tsx           | 156 +++++++++++++++++++++
 1 file changed, 156 insertions(+)
 create mode 100644 packages/prosody-ui/src/components/word/FullWordData.tsx

(limited to 'packages/prosody-ui/src/components/word/FullWordData.tsx')

diff --git a/packages/prosody-ui/src/components/word/FullWordData.tsx b/packages/prosody-ui/src/components/word/FullWordData.tsx
new file mode 100644
index 0000000..9b1fc69
--- /dev/null
+++ b/packages/prosody-ui/src/components/word/FullWordData.tsx
@@ -0,0 +1,156 @@
+import React, { useCallback, useEffect, useState } from "react";
+import spinner from "../assets/icons/spinner.svg";
+import likeIcon from "../assets/icons/heart.svg";
+import commentsIcon from "../assets/icons/quote.svg";
+import shareIcon from "../assets/icons/share.svg";
+import fontIcon from "../assets/icons/font.svg";
+import bookmarkIcon from "@/assets/icons/bookmark.svg";
+import speakerIcon from "@/assets/icons/speaker.svg";
+import type { AnalyzeRes, ColorTheme, Meaning } from "@/logic/types";
+import { ColoredText } from "../Sentence.tsx";
+import { P, Span, useSpeechSynthesis } from "@/hooks/useLang.tsx";
+import type { FullWordData } from "@sortug/langlib";
+import { cycleNext } from "@sortug/lib";
+import FontChanger from "@/fonts/FontChanger.tsx";
+import Phonetic from "./Phonetic.tsx";
+
+function Word({
+  data,
+  lang,
+  theme,
+}: {
+  data: FullWordData;
+  lang: string;
+  theme: ColorTheme;
+}) {
+  async function load() {
+    // const wiki = await fetchWiki(data.word);
+    // console.log(wiki, "wiki res");
+    // if ("ok" in wiki) setM(wiki.ok.meanings);
+    // else setError(wiki.error);
+    // setLoading(false);
+  }
+  useEffect(() => {
+    load();
+  }, []);
+  const [error, setError] = useState("");
+  const [loading, setLoading] = useState(false);
+  const [meanings, setM] = useState<Meaning[]>([]);
+  const [fontIdx, setFont] = useState(0);
+
+  const { voices, speaking, speak, stop } = useSpeechSynthesis();
+  function playAudio() {
+    console.log({ voices, speaking });
+    console.log("word", data);
+    speak(data.spelling);
+  }
+  console.log({ data });
+
+  async function saveW() {}
+
+  return (
+    <div id="word-modal" title={data.spelling}>
+      <FontChanger text={data.spelling}>
+        <img className="save-icon cp" onClick={saveW} src={bookmarkIcon} />
+        <div className="original">
+          <ColoredText
+            frags={data.phonetic.syllables.map((s) => ({
+              data: s,
+              display: s.spelling,
+              colorBy: s.tone.name,
+            }))}
+            theme={theme}
+          />
+        </div>
+        <Phonetic data={data} lang={lang} theme={theme} />
+        <div className="pronunciation IPA flex1 flex-center">
+          <P>{data.phonetic.ipa}</P>
+          <img onClick={playAudio} className="icon cp" src={speakerIcon} />
+        </div>
+        <div className="meanings">
+          {loading ? (
+            <img src={spinner} className="spinner bc" />
+          ) : (
+            data.senses.map((m) => (
+              <div key={JSON.stringify(m)} className="meaning">
+                <div className="pos">
+                  <Span>{m.pos}</Span>
+                </div>
+                <ol>
+                  {m.glosses.map((t, i) => (
+                    <li key={t + i} className="translation">
+                      <P>{t}</P>
+                    </li>
+                  ))}
+                </ol>
+              </div>
+            ))
+          )}
+          {error && <div className="error">{error}</div>}
+        </div>
+      </FontChanger>
+    </div>
+  );
+}
+
+export default Word;
+
+<Card className="absolute inset-0 backface-hidden rotate-y-180 flex flex-col overflow-hidden border-slate-200 dark:border-slate-800 shadow-lg bg-slate-50/50">
+  <div className="flex-1 overflow-hidden flex flex-col">
+    <Tabs defaultValue="meanings" className="flex-1 flex flex-col">
+      <div className="px-6 pt-6 pb-2 bg-white border-b">
+        <TabsList className="grid w-full grid-cols-3">
+          <TabsTrigger value="meanings">Meanings</TabsTrigger>
+          <TabsTrigger value="grammar">Grammar</TabsTrigger>
+          <TabsTrigger value="examples">Examples</TabsTrigger>
+        </TabsList>
+      </div>
+
+      <div className="flex-1 overflow-y-auto p-6">
+        <TabsContent value="meanings" className="mt-0 space-y-4">
+          <EnhancedWordMeanings word={word} />
+        </TabsContent>
+
+        <TabsContent value="grammar" className="mt-0 space-y-6">
+          <div className="space-y-4">
+            <div className="bg-blue-50 p-4 rounded-lg border border-blue-100">
+              <h3 className="font-semibold text-blue-900 mb-2">
+                Tone Analysis
+              </h3>
+              <div className="flex flex-wrap gap-2">
+                {tones.map((tone, idx) => (
+                  <Badge key={idx} variant="outline" className="bg-white">
+                    Syl {idx + 1}:{" "}
+                    <span
+                      className={cn("ml-1 font-bold", getColorByTone(tone))}
+                    >
+                      {tone}
+                    </span>
+                  </Badge>
+                ))}
+              </div>
+            </div>
+
+            <div className="bg-slate-100 p-4 rounded-lg border border-slate-200">
+              <h3 className="font-semibold text-slate-900 mb-2">
+                Word Structure
+              </h3>
+              <p className="text-sm text-slate-600">
+                This word consists of {syls.length} syllable
+                {syls.length > 1 ? "s" : ""}. The tone pattern is essential for
+                conveying the correct meaning.
+              </p>
+            </div>
+          </div>
+        </TabsContent>
+
+        <TabsContent value="examples" className="mt-0 space-y-4">
+          <ExamplesTab
+            word={word}
+            moreExamples={word.senses?.flatMap((s) => s.examples || [])}
+          />
+        </TabsContent>
+      </div>
+    </Tabs>
+  </div>
+</Card>;
-- 
cgit v1.2.3

