import React, { useState, useEffect } from "react"; import { Button } from "./ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "./ui/card"; import { Alert, AlertDescription, AlertTitle } from "./ui/alert"; import { Badge } from "./ui/badge"; import { calibrateWithPort } from "../../lerobot/web/calibrate"; import type { ConnectedRobot } from "../types"; interface CalibrationWizardProps { robot: ConnectedRobot; onComplete: () => void; onCancel: () => void; } interface CalibrationStep { id: string; title: string; description: string; status: "pending" | "running" | "complete" | "error"; message?: string; } export function CalibrationWizard({ robot, onComplete, onCancel, }: CalibrationWizardProps) { const [currentStepIndex, setCurrentStepIndex] = useState(0); const [steps, setSteps] = useState([ { id: "init", title: "Initialize Robot", description: "Connecting to robot and checking status", status: "pending", }, { id: "calibrate", title: "Calibrate Motors", description: "Running calibration sequence", status: "pending", }, { id: "verify", title: "Verify Calibration", description: "Testing calibrated positions", status: "pending", }, { id: "complete", title: "Complete", description: "Calibration finished successfully", status: "pending", }, ]); const [isRunning, setIsRunning] = useState(false); const [error, setError] = useState(null); useEffect(() => { startCalibration(); }, []); const updateStep = ( stepId: string, status: CalibrationStep["status"], message?: string ) => { setSteps((prev) => prev.map((step) => step.id === stepId ? { ...step, status, message } : step ) ); }; const startCalibration = async () => { if (!robot.port || !robot.robotType) { setError("Invalid robot configuration"); return; } setIsRunning(true); setError(null); try { // Step 1: Initialize setCurrentStepIndex(0); updateStep("init", "running"); await new Promise((resolve) => setTimeout(resolve, 1000)); updateStep("init", "complete", "Robot initialized successfully"); // Step 2: Calibrate setCurrentStepIndex(1); updateStep("calibrate", "running"); try { await calibrateWithPort(robot.port, robot.robotType); updateStep("calibrate", "complete", "Motor calibration completed"); } catch (error) { updateStep( "calibrate", "error", error instanceof Error ? error.message : "Calibration failed" ); throw error; } // Step 3: Verify setCurrentStepIndex(2); updateStep("verify", "running"); await new Promise((resolve) => setTimeout(resolve, 1500)); updateStep("verify", "complete", "Calibration verified"); // Step 4: Complete setCurrentStepIndex(3); updateStep("complete", "complete", "Robot is ready for use"); setTimeout(() => { onComplete(); }, 2000); } catch (error) { setError(error instanceof Error ? error.message : "Calibration failed"); } finally { setIsRunning(false); } }; const getStepIcon = (status: CalibrationStep["status"]) => { switch (status) { case "pending": return "⏳"; case "running": return "🔄"; case "complete": return "✅"; case "error": return "❌"; default: return "⏳"; } }; const getStepBadgeVariant = (status: CalibrationStep["status"]) => { switch (status) { case "pending": return "secondary" as const; case "running": return "default" as const; case "complete": return "default" as const; case "error": return "destructive" as const; default: return "secondary" as const; } }; return (

Calibration in Progress

Calibrating {robot.robotId} ({robot.robotType?.replace("_", " ")})

{error && ( {error} )}
{steps.map((step, index) => (
{getStepIcon(step.status)}
{step.title} {step.description}
{step.status.charAt(0).toUpperCase() + step.status.slice(1)}
{step.message && (

{step.message}

)}
))}
{error && }
); }