diff options
Diffstat (limited to 'packages/prosody-ui/src/components/word/Semantic.tsx')
| -rw-r--r-- | packages/prosody-ui/src/components/word/Semantic.tsx | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/packages/prosody-ui/src/components/word/Semantic.tsx b/packages/prosody-ui/src/components/word/Semantic.tsx new file mode 100644 index 0000000..059194c --- /dev/null +++ b/packages/prosody-ui/src/components/word/Semantic.tsx @@ -0,0 +1,184 @@ +import { useEffect, useState } from "react"; +import type { Example, FullWordData } from "@sortug/langlib"; +import { IconBadgeFilled, IconSparkles } from "@tabler/icons-react"; + +type Tab = "meanings" | "grammar" | "examples"; +function Semantic({ data }: { data: FullWordData }) { + return ( + <div className=""> + <div className="flex-col"> + <div className="tab-container"> + {data.senses.map((sense, i) => ( + <div> + <div key={data.spelling + sense.etymology + i} className=""> + {sense.pos && <div className="">{sense.pos}</div>} + + <ul className=""> + {sense.glosses.map((gloss, idx: number) => ( + <li key={idx} className="text-gray-700"> + {gloss} + </li> + ))} + </ul> + + {sense.etymology && ( + <div className=""> + <strong>Etymology:</strong> {sense.etymology} + </div> + )} + + {sense.categories.length > 0 && ( + <div className=""> + <strong>Categories:</strong> {sense.categories.join(", ")} + </div> + )} + {sense.derivation.length > 0 && ( + <div className=""> + <strong>Derived forms:</strong> + {sense.derivation.map((dr, i) => ( + <div key={dr.text + i}> + {dr.type}: {dr.text} - {dr.tags} + </div> + ))} + </div> + )} + {sense.examples.length > 0 && ( + <Examples data={data} examples={sense.examples} /> + )} + </div> + </div> + ))} + </div> + </div> + </div> + ); +} + +export default Semantic; + +function ExamplesTab({ + data, + examples, +}: { + data: FullWordData; + examples: Example[]; +}) { + const [isGenerating, setIsGenerating] = useState(false); + const [generatedExamples, setGeneratedExamples] = useState<any[]>([]); + + const generateExamples = async () => { + setIsGenerating(true); + + try { + // Get the primary meaning from the first sense + const primaryMeaning = + data.senses?.[0]?.glosses?.[0] || "unknown meaning"; + + const response = await fetch("/api/generate-examples", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + word: data.spelling, + meaning: primaryMeaning, + examples, + }), + }); + + if (!response.ok) { + throw new Error("Failed to generate examples"); + } + + const j = await response.json(); + setGeneratedExamples(j.examples || []); + } catch (err) { + console.error("Error generating examples:", err); + } finally { + setIsGenerating(false); + } + }; + return ( + <div className=""> + <div className=""> + <h4 className="">Usage Examples</h4> + + {/* Generate More Button */} + <div className=""> + <button + onClick={generateExamples} + disabled={isGenerating} + className="" + > + {isGenerating ? ( + <> + <div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white" /> + Generating Examples... + </> + ) : ( + <> + <IconSparkles size={16} /> + Generate More Example Sentences + </> + )} + </button> + </div> + + {/* Examples Display */} + <div className=""> + {examples.map((example, idx) => ( + <div + key={`original-${idx}`} + className="p-3 bg-white rounded border-l-4 border-blue-400" + > + <p className="text-sm text-gray-700 italic"> + {example?.text || ""} + </p> + {example.ref && ( + <p className="text-xs text-gray-500 mt-1"> + Source: {example.ref} + </p> + )} + </div> + ))} + + {generatedExamples.length > 0 && ( + <> + <h5 className="text-sm font-medium text-gray-700 mb-2 mt-4"> + AI-Generated Examples: + </h5> + {generatedExamples.map((example, idx) => ( + <div + key={`generated-${idx}`} + className="p-3 bg-white rounded border-l-4 border-green-400" + > + <p className="text-sm text-gray-800 font-medium mb-1"> + {example.thai} + </p> + <p className="text-sm text-gray-600 mb-1"> + {example.english} + </p> + {example.context && ( + <p className="text-xs text-gray-500 italic"> + Context: {example.context} + </p> + )} + </div> + ))} + </> + )} + + {/* No Examples */} + {!moreExamples?.length && !generatedExamples.length && ( + <div className="p-3 bg-white rounded border-l-4 border-orange-400"> + <p className="text-sm text-gray-600 italic"> + No examples available for this word. Click "Generate More + Example Sentences" to get AI-generated examples. + </p> + </div> + )} + </div> + </div> + </div> + ); +} |
