Spaces:
Running
Running
import React, { useState } from "react"; | |
import { | |
Dialog, | |
DialogContent, | |
DialogHeader, | |
DialogTitle, | |
DialogFooter, | |
} from "./ui/dialog"; | |
import { Button } from "./ui/button"; | |
import { Textarea } from "./ui/textarea"; | |
import { Loader } from "lucide-react"; | |
import { toast } from "sonner"; | |
import { useCreateAnimation } from "@/hooks/useCreateAnimation"; | |
import { AnimationRequest, RobotAnimationConfig } from "@/lib/types"; | |
import { useUrdf } from "@/hooks/useUrdf"; | |
interface AnimationDialogProps { | |
open: boolean; | |
onOpenChange: (open: boolean) => void; | |
robotName: string; | |
} | |
const AnimationDialog: React.FC<AnimationDialogProps> = ({ | |
open, | |
onOpenChange, | |
robotName, | |
}) => { | |
const [animationPrompt, setAnimationPrompt] = useState(""); | |
const [isGeneratingAnimation, setIsGeneratingAnimation] = useState(false); | |
const { createAnimation, clearError } = useCreateAnimation(); | |
const { urdfContent, currentRobotData, setCurrentAnimationConfig } = | |
useUrdf(); | |
// Handle dialog close - clear error states | |
const handleOpenChange = (open: boolean) => { | |
if (!open) { | |
clearError(); | |
} | |
onOpenChange(open); | |
}; | |
const handleAnimationRequest = async () => { | |
if (!animationPrompt.trim()) { | |
toast.error("Please enter an animation description"); | |
return; | |
} | |
if (!urdfContent) { | |
toast.error("No URDF content available", { | |
description: "Please upload a URDF model first.", | |
}); | |
return; | |
} | |
setIsGeneratingAnimation(true); | |
try { | |
// Create the animation request | |
const request: AnimationRequest = { | |
robotName: currentRobotData?.name || robotName, | |
urdfContent, | |
description: animationPrompt, | |
}; | |
// Call the createAnimation function | |
const animationResult = await createAnimation(request); | |
setIsGeneratingAnimation(false); | |
onOpenChange(false); | |
// Reset the prompt for next time | |
setAnimationPrompt(""); | |
// Store animation in the context instead of using the onAnimationApplied callback | |
if (animationResult) { | |
setCurrentAnimationConfig(animationResult); | |
// Show success message | |
toast.success("Animation applied successfully", { | |
description: `Applied: "${animationPrompt}"`, | |
duration: 2000, | |
}); | |
} | |
} catch (error) { | |
setIsGeneratingAnimation(false); | |
// The error toast is already handled in the hook | |
console.error("Animation generation failed:", error); | |
} | |
}; | |
return ( | |
<Dialog open={open} onOpenChange={handleOpenChange}> | |
<DialogContent className="sm:max-w-[425px] font-mono"> | |
<DialogHeader> | |
<DialogTitle className="text-center"> | |
Animation Request for {currentRobotData?.name || robotName} | |
</DialogTitle> | |
</DialogHeader> | |
<div className="py-4"> | |
<Textarea | |
placeholder="Describe the animation you want to see (e.g., 'Make the robot wave its arm' or 'Make one of the wheels spin in circles')" | |
className="min-h-[100px] font-mono" | |
value={animationPrompt} | |
onChange={(e) => setAnimationPrompt(e.target.value)} | |
disabled={isGeneratingAnimation} | |
/> | |
</div> | |
<DialogFooter> | |
<Button | |
onClick={() => handleOpenChange(false)} | |
variant="outline" | |
disabled={isGeneratingAnimation} | |
> | |
Cancel | |
</Button> | |
<Button | |
onClick={handleAnimationRequest} | |
disabled={isGeneratingAnimation || !urdfContent} | |
className="ml-2" | |
> | |
{isGeneratingAnimation ? ( | |
<> | |
<Loader className="mr-2 h-4 w-4 animate-spin" /> | |
Generating... | |
</> | |
) : ( | |
"Apply Animation" | |
)} | |
</Button> | |
</DialogFooter> | |
</DialogContent> | |
</Dialog> | |
); | |
}; | |
export default AnimationDialog; | |