'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.
Number of Syllables
{[1, 2, 3, 4, 5].map(num => (
{num} Syllable{num > 1 ? 's' : ''}
))}
{Array.from({ length: syllableCount }).map((_, index) => (
Tone for Syllable {index + 1}
handleToneChange(index, value)}
>
Any Tone
{thaiTones.map(tone => (
{tone.label}
))}
))}
{isLoading ? 'Searching...' : 'Find Word'}
{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.
)}
);
}