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 DirectFollowerModalProps { open: boolean; onOpenChange: (open: boolean) => void; followerPort: string; setFollowerPort: (value: string) => void; followerConfig: string; setFollowerConfig: (value: string) => void; followerConfigs: string[]; isLoadingConfigs: boolean; onStart: () => void; } const DirectFollowerModal: React.FC = ({ open, onOpenChange, followerPort, setFollowerPort, followerConfig, setFollowerConfig, followerConfigs, isLoadingConfigs, onStart, }) => { const { baseUrl, fetchWithHeaders } = useApi(); const { debouncedSavePort, debouncedSaveConfig } = useAutoSave(); const [showPortDetection, setShowPortDetection] = useState(false); // Load saved follower port and configuration on component mount useEffect(() => { const loadSavedData = async () => { try { // 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 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 && followerConfigs.length > 0) { loadSavedData(); } }, [open, setFollowerPort, setFollowerConfig, followerConfigs, baseUrl, fetchWithHeaders]); const handlePortDetection = () => { setShowPortDetection(true); }; const handlePortDetected = (port: string) => { setFollowerPort(port); }; // Enhanced port change handler that saves automatically const handleFollowerPortChange = (value: string) => { setFollowerPort(value); // Auto-save with debouncing to avoid excessive API calls debouncedSavePort("follower", value); }; // Enhanced config change handler that saves automatically const handleFollowerConfigChange = (value: string) => { setFollowerConfig(value); // Auto-save with debouncing to avoid excessive API calls debouncedSaveConfig("follower", value); }; return (
Configure Direct Follower Control
Configure the follower robot arm for direct control with 6-axis commands.
handleFollowerPortChange(e.target.value)} placeholder="/dev/tty.usbmodem5A460816621" className="bg-gray-800 border-gray-700 text-white flex-1" />
); }; export default DirectFollowerModal;