urdf-visualizer / viewer /src /components /AnimationDialog.tsx
jurmy24's picture
feat: add viewer code
72f0edb
raw
history blame
4.01 kB
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;