From a3f24ea79b14394b24c4b60a010651eb29eeb872 Mon Sep 17 00:00:00 2001 From: polwex Date: Thu, 29 May 2025 12:10:22 +0700 Subject: glorious new db --- src/components/tones/ToneSelectorClient.tsx | 199 ++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 src/components/tones/ToneSelectorClient.tsx (limited to 'src/components/tones/ToneSelectorClient.tsx') diff --git a/src/components/tones/ToneSelectorClient.tsx b/src/components/tones/ToneSelectorClient.tsx new file mode 100644 index 0000000..0ee9433 --- /dev/null +++ b/src/components/tones/ToneSelectorClient.tsx @@ -0,0 +1,199 @@ +'use client'; + +import { useState, useEffect, useTransition } from 'react'; +import { WordData } from '@/zoom/logic/types'; +import { fetchWordsByToneAndSyllables } from '@/actions/tones'; +import { Button } from '@/components/ui/button'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'; +import { Label } from '@/components/ui/label'; +import { Skeleton } from '@/components/ui/skeleton'; // For loading state + +// Helper to display tones prominently +const ProminentToneDisplay = ({ wordData }: { wordData: WordData }) => { + if (!wordData.prosody || !Array.isArray(wordData.prosody)) { + return

No prosody data

; + } + + return ( +
+

{wordData.spelling}

+
+ {wordData.prosody.map((p, index) => ( +
+

Syllable {index + 1}

+

{p.tone ?? '?'}

+
+ ))} +
+ {wordData.ipa && wordData.ipa.length > 0 && ( +

+ {wordData.ipa.map(i => i.ipa).join(' / ')} +

+ )} +
+ ); +}; + + +export default function ToneSelectorClient({ initialWord }: { initialWord: WordData | null }) { + const [currentWord, setCurrentWord] = useState(initialWord); + const [syllableCount, setSyllableCount] = useState(initialWord?.syllables || 1); + const [selectedTones, setSelectedTones] = useState<(number | null)[]>( + initialWord?.prosody?.map(p => p.tone ?? null) || [null] + ); + const [isLoading, startTransition] = useTransition(); + + useEffect(() => { + // Adjust selectedTones array length when syllableCount changes + setSelectedTones(prevTones => { + const newTones = Array(syllableCount).fill(null); + for (let i = 0; i < Math.min(prevTones.length, syllableCount); i++) { + newTones[i] = prevTones[i]; + } + return newTones; + }); + }, [syllableCount]); + + const handleFetchWord = () => { + startTransition(async () => { + const word = await fetchWordsByToneAndSyllables(syllableCount, selectedTones); + setCurrentWord(word); + }); + }; + + const handleSyllableCountChange = (value: string) => { + const count = parseInt(value, 10); + if (!isNaN(count) && count > 0 && count <= 5) { // Max 5 syllables for simplicity + setSyllableCount(count); + } + }; + + const handleToneChange = (syllableIndex: number, value: string) => { + const tone = value === 'any' ? null : parseInt(value, 10); + setSelectedTones(prevTones => { + const newTones = [...prevTones]; + newTones[syllableIndex] = tone; + return newTones; + }); + }; + + const thaiTones = [ + { value: '1', label: '1 (Mid)' }, + { value: '2', label: '2 (Low)' }, + { value: '3', label: '3 (Falling)' }, + { value: '4', label: '4 (High)' }, + { value: '5', label: '5 (Rising)' }, + ]; + + return ( +
+ + + Thai Tone Explorer + Select syllable count and tones to find Thai words. + + +
+ + +
+ + {Array.from({ length: syllableCount }).map((_, index) => ( +
+ + +
+ ))} +
+ + + +
+ + {isLoading && !currentWord && ( + + + + + + + + + )} + + {!isLoading && currentWord && ( + + + Current Word + + + + {/* You can add more details from WordData here if needed, like definitions */} + {currentWord.senses && currentWord.senses.length > 0 && ( +
+

Meanings:

+ {currentWord.senses.map((sense, sIdx) => ( +
+

{sense.pos}

+ {sense.senses && Array.isArray(sense.senses) && sense.senses.map((subSense, ssIdx) => ( + subSense.glosses && Array.isArray(subSense.glosses) && subSense.glosses.map((gloss: string, gIdx: number) => ( +

- {gloss}

+ )) + ))} +
+ ))} +
+ )} +
+
+ )} + + {!isLoading && !currentWord && ( + + + No Word Found + + +

+ Could not find a Thai word matching your criteria. Try different selections. +

+
+
+ )} +
+ ); +} -- cgit v1.2.3