Spaces:
Running
Running
File size: 4,009 Bytes
72f0edb |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
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;
|