import React, { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, } from "@/components/ui/dialog"; import { Settings } from "lucide-react"; import PortDetectionModal from "@/components/ui/PortDetectionModal"; import PortDetectionButton from "@/components/ui/PortDetectionButton"; import { useApi } from "@/contexts/ApiContext"; import { useAutoSave } from "@/hooks/useAutoSave"; interface TeleoperationModalProps { open: boolean; onOpenChange: (open: boolean) => void; leaderPort: string; setLeaderPort: (value: string) => void; followerPort: string; setFollowerPort: (value: string) => void; leaderConfig: string; setLeaderConfig: (value: string) => void; followerConfig: string; setFollowerConfig: (value: string) => void; leaderConfigs: string[]; followerConfigs: string[]; isLoadingConfigs: boolean; onStart: () => void; } const TeleoperationModal: React.FC = ({ open, onOpenChange, leaderPort, setLeaderPort, followerPort, setFollowerPort, leaderConfig, setLeaderConfig, followerConfig, setFollowerConfig, leaderConfigs, followerConfigs, isLoadingConfigs, onStart, }) => { const { baseUrl, fetchWithHeaders } = useApi(); const { debouncedSavePort, debouncedSaveConfig } = useAutoSave(); const [showPortDetection, setShowPortDetection] = useState(false); const [detectionRobotType, setDetectionRobotType] = useState< "leader" | "follower" >("leader"); // Load saved ports and configurations on component mount useEffect(() => { const loadSavedData = async () => { try { // Load leader port const leaderResponse = await fetchWithHeaders( `${baseUrl}/robot-port/leader` ); const leaderData = await leaderResponse.json(); if (leaderData.status === "success" && leaderData.default_port) { setLeaderPort(leaderData.default_port); } // Load follower port const followerResponse = await fetchWithHeaders( `${baseUrl}/robot-port/follower` ); const followerData = await followerResponse.json(); if (followerData.status === "success" && followerData.default_port) { setFollowerPort(followerData.default_port); } // Load leader configuration const leaderConfigResponse = await fetchWithHeaders( `${baseUrl}/robot-config/leader?available_configs=${leaderConfigs.join(',')}` ); const leaderConfigData = await leaderConfigResponse.json(); if (leaderConfigData.status === "success" && leaderConfigData.default_config) { setLeaderConfig(leaderConfigData.default_config); } // Load follower configuration const followerConfigResponse = await fetchWithHeaders( `${baseUrl}/robot-config/follower?available_configs=${followerConfigs.join(',')}` ); const followerConfigData = await followerConfigResponse.json(); if (followerConfigData.status === "success" && followerConfigData.default_config) { setFollowerConfig(followerConfigData.default_config); } } catch (error) { console.error("Error loading saved data:", error); } }; if (open && leaderConfigs.length > 0 && followerConfigs.length > 0) { loadSavedData(); } }, [open, setLeaderPort, setFollowerPort, setLeaderConfig, setFollowerConfig, leaderConfigs, followerConfigs, baseUrl, fetchWithHeaders]); const handlePortDetection = (robotType: "leader" | "follower") => { setDetectionRobotType(robotType); setShowPortDetection(true); }; const handlePortDetected = (port: string) => { if (detectionRobotType === "leader") { setLeaderPort(port); } else { setFollowerPort(port); } }; // Enhanced port change handlers that save automatically const handleLeaderPortChange = (value: string) => { setLeaderPort(value); // Auto-save with debouncing to avoid excessive API calls debouncedSavePort("leader", value); }; const handleFollowerPortChange = (value: string) => { setFollowerPort(value); // Auto-save with debouncing to avoid excessive API calls debouncedSavePort("follower", value); }; // Enhanced config change handlers that save automatically const handleLeaderConfigChange = (value: string) => { setLeaderConfig(value); // Auto-save with debouncing to avoid excessive API calls debouncedSaveConfig("leader", value); }; const handleFollowerConfigChange = (value: string) => { setFollowerConfig(value); // Auto-save with debouncing to avoid excessive API calls debouncedSaveConfig("follower", value); }; return (
Configure Teleoperation
Configure the robot arm ports and calibration settings for teleoperation.
handleLeaderPortChange(e.target.value)} placeholder="/dev/tty.usbmodem5A460816421" className="bg-gray-800 border-gray-700 text-white flex-1" /> handlePortDetection("leader")} robotType="leader" />
handleFollowerPortChange(e.target.value)} placeholder="/dev/tty.usbmodem5A460816621" className="bg-gray-800 border-gray-700 text-white flex-1" /> handlePortDetection("follower")} robotType="follower" />
); }; export default TeleoperationModal;