"use client"; import { Activity, AlertTriangle, Battery, BatteryLow, Bot, CheckCircle, Clock, RefreshCw, Signal, SignalHigh, SignalLow, SignalMedium, WifiOff, } from "lucide-react"; import { useEffect, useState } from "react"; import { Alert, AlertDescription } from "~/components/ui/alert"; import { Badge } from "~/components/ui/badge"; import { Button } from "~/components/ui/button"; import { Progress } from "~/components/ui/progress"; interface RobotStatusProps { trialId: string; } interface RobotStatus { id: string; name: string; connectionStatus: "connected" | "disconnected" | "connecting" | "error"; batteryLevel?: number; signalStrength?: number; currentMode: string; lastHeartbeat?: Date; errorMessage?: string; capabilities: string[]; communicationProtocol: string; isMoving: boolean; position?: { x: number; y: number; z?: number; orientation?: number; }; sensors?: Record; } export function RobotStatus({ trialId: _trialId }: RobotStatusProps) { const [robotStatus, setRobotStatus] = useState(null); const [lastUpdate, setLastUpdate] = useState(new Date()); const [refreshing, setRefreshing] = useState(false); // Mock robot status - in real implementation, this would come from API/WebSocket useEffect(() => { // Simulate robot status updates const mockStatus: RobotStatus = { id: "robot_001", name: "TurtleBot3 Burger", connectionStatus: "connected", batteryLevel: 85, signalStrength: 75, currentMode: "autonomous_navigation", lastHeartbeat: new Date(), capabilities: ["navigation", "manipulation", "speech", "vision"], communicationProtocol: "ROS2", isMoving: false, position: { x: 1.2, y: 0.8, orientation: 45, }, sensors: { lidar: "operational", camera: "operational", imu: "operational", odometry: "operational", }, }; setRobotStatus(mockStatus); // Simulate periodic updates const interval = setInterval(() => { setRobotStatus((prev) => { if (!prev) return prev; return { ...prev, batteryLevel: Math.max( 0, (prev.batteryLevel ?? 0) - Math.random() * 0.5, ), signalStrength: Math.max( 0, Math.min( 100, (prev.signalStrength ?? 0) + (Math.random() - 0.5) * 10, ), ), lastHeartbeat: new Date(), position: prev.position ? { ...prev.position, x: prev.position.x + (Math.random() - 0.5) * 0.1, y: prev.position.y + (Math.random() - 0.5) * 0.1, } : undefined, }; }); setLastUpdate(new Date()); }, 3000); return () => clearInterval(interval); }, []); const getConnectionStatusConfig = (status: string) => { switch (status) { case "connected": return { icon: CheckCircle, color: "text-green-600", bgColor: "bg-green-100", label: "Connected", }; case "connecting": return { icon: RefreshCw, color: "text-blue-600", bgColor: "bg-blue-100", label: "Connecting", }; case "disconnected": return { icon: WifiOff, color: "text-gray-600", bgColor: "bg-gray-100", label: "Disconnected", }; case "error": return { icon: AlertTriangle, color: "text-red-600", bgColor: "bg-red-100", label: "Error", }; default: return { icon: WifiOff, color: "text-gray-600", bgColor: "bg-gray-100", label: "Unknown", }; } }; const getSignalIcon = (strength: number) => { if (strength >= 75) return SignalHigh; if (strength >= 50) return SignalMedium; if (strength >= 25) return SignalLow; return Signal; }; const getBatteryIcon = (level: number) => { return level <= 20 ? BatteryLow : Battery; }; const handleRefreshStatus = async () => { setRefreshing(true); // Simulate API call setTimeout(() => { setRefreshing(false); setLastUpdate(new Date()); }, 1000); }; if (!robotStatus) { return (

No robot connected

); } const statusConfig = getConnectionStatusConfig(robotStatus.connectionStatus); const StatusIcon = statusConfig.icon; const SignalIcon = getSignalIcon(robotStatus.signalStrength ?? 0); const BatteryIcon = getBatteryIcon(robotStatus.batteryLevel ?? 0); return (
{/* Main Status Card */}
{/* Robot Info */}
{robotStatus.name}
{statusConfig.label}
{/* Connection Details */}
Protocol: {robotStatus.communicationProtocol}
{/* Status Indicators */}
{/* Battery */} {robotStatus.batteryLevel !== undefined && (
Battery
{Math.round(robotStatus.batteryLevel)}%
)} {/* Signal Strength */} {robotStatus.signalStrength !== undefined && (
Signal
{Math.round(robotStatus.signalStrength)}%
)}
{/* Current Mode */}
Mode:
{robotStatus.currentMode .replace(/_/g, " ") .replace(/\b\w/g, (l) => l.toUpperCase())}
{robotStatus.isMoving && (
Robot is moving
)}
{/* Position Info */} {robotStatus.position && (
Position
X: {robotStatus.position.x.toFixed(2)}m
Y: {robotStatus.position.y.toFixed(2)}m
{robotStatus.position.orientation !== undefined && (
Orientation: {Math.round(robotStatus.position.orientation)}°
)}
)} {/* Sensors Status */} {robotStatus.sensors && (
Sensors
{Object.entries(robotStatus.sensors).map(([sensor, status]) => (
{sensor}: {status}
))}
)} {/* Error Alert */} {robotStatus.errorMessage && ( {robotStatus.errorMessage} )} {/* Last Update */}
Last update: {lastUpdate.toLocaleTimeString()}
); }