LeLab / src /components /training /config /TargetCard.tsx
GitHub CI
Sync from leLab @ 7317f7103e3a9d7f45fe4c0d6e4660a8f9d295e3
fc9bd9f
import React from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { ConfigComponentProps } from "../types";
import { RunnerFlavor } from "@/lib/jobsApi";
interface TargetCardProps extends ConfigComponentProps {
authenticated: boolean;
flavors: RunnerFlavor[];
loading: boolean;
}
const formatHourly = (unitCostUsd: number, unitLabel: string): string => {
const hourly = unitLabel === "minute" ? unitCostUsd * 60 : unitCostUsd;
return `$${hourly.toFixed(2)}/hr`;
};
const formatFlavorLine = (f: RunnerFlavor): string => {
const accel = f.accelerator ? f.accelerator : f.cpu;
return `${f.pretty_name} · ${accel} · ${formatHourly(f.unit_cost_usd, f.unit_label)}`;
};
const TargetCard: React.FC<TargetCardProps> = ({
config,
updateConfig,
authenticated,
flavors,
loading,
}) => {
const target = config.target;
const value =
target.runner === "local" ? "local" : `hf:${target.flavor ?? ""}`;
const handleChange = (v: string) => {
if (v === "local") {
updateConfig("target", { runner: "local" });
} else if (v.startsWith("hf:")) {
const flavor = v.slice("hf:".length);
updateConfig("target", { runner: "hf_cloud", flavor });
}
};
return (
<Card className="bg-slate-800/50 border-slate-700 rounded-xl">
<CardHeader>
<CardTitle className="text-white">Compute target</CardTitle>
</CardHeader>
<CardContent className="space-y-3">
<div>
<Label className="text-slate-300">Run training on</Label>
<Select value={value} onValueChange={handleChange}>
<SelectTrigger className="bg-slate-900 border-slate-600 text-white rounded-lg mt-1">
<SelectValue placeholder={loading ? "Loading…" : "Select target"} />
</SelectTrigger>
<SelectContent className="bg-slate-800 border-slate-600 text-white">
<SelectItem value="local">Local — your machine (free)</SelectItem>
{flavors.map((f) => (
<SelectItem
key={f.name}
value={`hf:${f.name}`}
disabled={!authenticated}
>
{formatFlavorLine(f)}
{!authenticated && (
<span className="text-amber-300 ml-2 text-xs">
log in to HF
</span>
)}
</SelectItem>
))}
</SelectContent>
</Select>
<p className="text-xs text-slate-500 mt-1">
Cost shown is per running hour. Final policy uploads to your HF
account when training completes.
</p>
</div>
</CardContent>
</Card>
);
};
export default TargetCard;