NERDDISCO's picture
feat: make the cyberpunk example work with @lerobot/web
7a0c9ff
raw
history blame
8.3 kB
"use client";
import {
Settings,
Gamepad2,
Trash2,
Pencil,
Plus,
ExternalLink,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card, CardFooter } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
import HudCorners from "@/components/hud-corners";
import type { RobotConnection } from "@/types/robot";
interface DeviceDashboardProps {
robots: RobotConnection[];
onCalibrate: (robot: RobotConnection) => void;
onTeleoperate: (robot: RobotConnection) => void;
onRemove: (robotId: string) => void;
onEdit: (robot: RobotConnection) => void;
onFindNew: () => void;
isConnecting: boolean;
onScrollToHardware: () => void;
}
export function DeviceDashboard({
robots,
onCalibrate,
onTeleoperate,
onRemove,
onEdit,
onFindNew,
isConnecting,
onScrollToHardware,
}: DeviceDashboardProps) {
return (
<Card className="border-0 rounded-none">
<div className="p-4 border-b border-white/10 flex items-center justify-between">
<div className="flex items-center gap-4">
<div className="w-1 h-8 bg-primary"></div>
<div>
<h3 className="text-xl font-bold text-foreground font-mono tracking-wider uppercase">
device registry
</h3>
<div className="flex items-center gap-2 mt-1">
<span className="text-xs text-muted-foreground font-mono">
currently supports SO-100{" "}
</span>
<button
onClick={onScrollToHardware}
className="text-xs text-primary hover:text-accent transition-colors underline font-mono flex items-center gap-1"
>
<ExternalLink className="w-3 h-3" />
add more devices
</button>
</div>
</div>
</div>
{robots.length > 0 && (
<Button
onClick={onFindNew}
disabled={isConnecting}
size="lg"
className="font-mono uppercase"
>
<Plus className="w-4 h-4 mr-2" />
add unit
</Button>
)}
</div>
<div className="pt-6 p-6">
{robots.length === 0 ? (
<div className="relative">
<HudCorners className="p-16">
<div className="text-center font-mono">
<div className="mb-6">
{isConnecting ? (
<>
<div className="w-16 h-16 mx-auto mb-4 border-2 border-primary/50 rounded-lg flex items-center justify-center animate-pulse">
<Plus className="w-8 h-8 text-primary animate-spin" />
</div>
<h4 className="text-xl text-primary mb-2 tracking-wider uppercase">
scanning for units
</h4>
<p className="text-sm text-muted-foreground mb-8">
searching for available devices...
</p>
</>
) : (
<>
<div className="w-16 h-16 mx-auto mb-4 border-2 border-dashed border-primary/50 rounded-lg flex items-center justify-center">
<Plus className="w-8 h-8 text-primary/50" />
</div>
<h4 className="text-xl text-primary mb-2 tracking-wider uppercase">
no units detected
</h4>
<Button
onClick={onFindNew}
size="lg"
className="font-mono uppercase"
>
<Plus className="w-4 h-4 mr-2" />
add unit
</Button>
</>
)}
</div>
</div>
</HudCorners>
</div>
) : (
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
{robots.map((robot) => (
<HudCorners key={robot.robotId}>
<Card className="flex flex-col h-full">
<div className="p-4 border-b border-white/10">
<div className="flex items-start justify-between mb-3">
<div className="flex-1">
<h4 className="text-xl font-bold text-primary font-mono tracking-wider">
{robot.name}
</h4>
<div className="flex items-center gap-2 mt-1">
<span className="text-xs text-muted-foreground font-mono">
{robot.serialNumber}
</span>
<span className="text-xs text-muted-foreground">
</span>
<span className="text-xs font-mono uppercase text-muted-foreground">
{robot.robotType}
</span>
</div>
</div>
<Badge
variant="outline"
className={cn(
"border-primary/50 bg-primary/20 text-primary font-mono text-xs",
robot.isConnected && "animate-pulse-slow"
)}
>
{robot.isConnected ? "ONLINE" : "OFFLINE"}
</Badge>
</div>
</div>
<div className="flex-grow p-4">
<div className="grid grid-cols-2 gap-4 text-xs font-mono">
<div>
<span className="text-muted-foreground uppercase">
status:
</span>
<div className="text-primary uppercase">
{robot.isConnected ? "operational" : "disconnected"}
</div>
</div>
<div>
<span className="text-muted-foreground uppercase">
type:
</span>
<div className="text-accent uppercase">
{robot.robotType}
</div>
</div>
</div>
</div>
<CardFooter className="p-4 border-t border-white/10 flex flex-wrap gap-2">
<Button
variant="outline"
size="sm"
onClick={() => onEdit(robot)}
className="font-mono text-xs uppercase"
>
<Pencil className="w-3 h-3 mr-1" /> edit
</Button>
<Button
variant="outline"
size="sm"
onClick={() => onCalibrate(robot)}
className="font-mono text-xs uppercase"
>
<Settings className="w-3 h-3 mr-1" /> calibrate
</Button>
<Button
variant="outline"
size="sm"
onClick={() => onTeleoperate(robot)}
className="font-mono text-xs uppercase"
>
<Gamepad2 className="w-3 h-3 mr-1" /> control
</Button>
<Button
variant="destructive"
size="sm"
onClick={() =>
onRemove(
robot.robotId || robot.serialNumber || "unknown"
)
}
className="font-mono text-xs uppercase"
>
<Trash2 className="w-3 h-3 mr-1" /> remove
</Button>
</CardFooter>
</Card>
</HudCorners>
))}
</div>
)}
</div>
</Card>
);
}