description-improv / src /components /game /SentenceBuilder.tsx
Felix Zieger
update
65676ec
import { useState } from "react";
import { motion } from "framer-motion";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { useTranslation } from "@/hooks/useTranslation";
import { RoundHeader } from "./sentence-builder/RoundHeader";
import { WordDisplay } from "./sentence-builder/WordDisplay";
import { SentenceDisplay } from "./sentence-builder/SentenceDisplay";
import { InputForm } from "./sentence-builder/InputForm";
import { Button } from "@/components/ui/button";
interface SentenceWord {
word: string;
provider: 'player' | 'ai';
}
interface SentenceBuilderProps {
currentWord: string;
successfulRounds: number;
sentence: SentenceWord[];
playerInput: string;
isAiThinking: boolean;
onInputChange: (value: string) => void;
onSubmitWord: (e: React.FormEvent) => void;
onMakeGuess: () => void;
normalizeWord: (word: string) => string;
onBack?: () => void;
onClose: () => void;
}
export const SentenceBuilder = ({
currentWord,
successfulRounds,
sentence,
playerInput,
isAiThinking,
onInputChange,
onSubmitWord,
onMakeGuess,
normalizeWord,
onBack,
onClose,
}: SentenceBuilderProps) => {
const [showConfirmDialog, setShowConfirmDialog] = useState(false);
const [hasMultipleWords, setHasMultipleWords] = useState(false);
const [containsTargetWord, setContainsTargetWord] = useState(false);
const [isTooLong, setIsTooLong] = useState(false);
const t = useTranslation();
console.log("SentenceBuilder - Rendering with showConfirmDialog:", showConfirmDialog);
const validateInput = (input: string) => {
setHasMultipleWords(input.trim().split(/\s+/).length > 1);
setContainsTargetWord(
normalizeWord(input).includes(normalizeWord(currentWord))
);
setIsTooLong(input.trim().length >= 30);
};
const handleInputChange = (value: string) => {
validateInput(value);
onInputChange(value);
};
const handleSetShowConfirmDialog = (show: boolean) => {
console.log("SentenceBuilder - Setting showConfirmDialog to:", show);
setShowConfirmDialog(show);
};
const isValidInput = !playerInput || /^[\p{L} ]+$/u.test(playerInput);
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="text-center relative"
>
<RoundHeader
successfulRounds={successfulRounds}
onBack={onBack}
showConfirmDialog={showConfirmDialog}
setShowConfirmDialog={handleSetShowConfirmDialog}
/>
<WordDisplay currentWord={currentWord} />
<SentenceDisplay sentence={sentence} />
<InputForm
playerInput={playerInput}
onInputChange={handleInputChange}
onSubmitWord={onSubmitWord}
onMakeGuess={onMakeGuess}
isAiThinking={isAiThinking}
hasMultipleWords={hasMultipleWords}
containsTargetWord={containsTargetWord}
isTooLong={isTooLong}
isValidInput={isValidInput}
sentence={sentence}
/>
<AlertDialog open={showConfirmDialog} onOpenChange={handleSetShowConfirmDialog}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{t.game.leaveGameTitle}</AlertDialogTitle>
<AlertDialogDescription>
{t.game.leaveGameDescription}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={() => setShowConfirmDialog(false)}>
{t.game.cancel}
</AlertDialogCancel>
<AlertDialogAction onClick={onBack}>
{t.game.confirm}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</motion.div>
);
};