File size: 2,749 Bytes
6a7089a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | import { Card, Badge, Button } from "../atoms";
import type { Profile, Instance } from "../../types";
interface Props {
profile: Profile;
instance?: Instance;
onLaunch: () => void;
onStop?: () => void;
onDetails?: () => void;
}
function InfoRow({ label, value }: { label: string; value: string }) {
return (
<div className="flex items-center justify-between gap-3 text-xs">
<span className="dashboard-section-title text-[0.68rem]">{label}</span>
<span className="dashboard-mono text-text-secondary">{value}</span>
</div>
);
}
export default function ProfileCard({
profile,
instance,
onLaunch,
onStop,
onDetails,
}: Props) {
const isRunning = instance?.status === "running";
const isError = instance?.status === "error";
const accountText = profile.accountEmail || profile.accountName || "—";
const sizeText = profile.sizeMB ? `${profile.sizeMB.toFixed(0)} MB` : "—";
return (
<Card hover className="flex flex-col">
{/* Header */}
<div className="flex items-center justify-between border-b border-border-subtle bg-black/10 px-4 py-3">
<span className="truncate font-medium text-text-primary">
{profile.name}
</span>
{isRunning ? (
<Badge variant="success">:{instance.port}</Badge>
) : isError ? (
<Badge variant="danger">error</Badge>
) : (
<Badge>stopped</Badge>
)}
</div>
{/* Body */}
<div className="flex flex-1 flex-col gap-2 px-4 py-4">
<InfoRow label="Size" value={sizeText} />
<InfoRow label="Account" value={accountText} />
{profile.useWhen && (
<div className="mt-2 rounded-sm border border-border-subtle bg-[rgb(var(--brand-surface-code-rgb)/0.4)] p-3">
<div className="dashboard-section-title text-[0.68rem]">
Use when
</div>
<div className="mt-1 line-clamp-2 text-xs leading-5 text-text-secondary">
{profile.useWhen}
</div>
</div>
)}
{isError && instance?.error && (
<div className="mt-1 text-xs text-destructive">{instance.error}</div>
)}
</div>
{/* Actions */}
<div className="flex justify-end gap-2 border-t border-border-subtle bg-black/10 px-4 py-3">
{onDetails && (
<Button size="sm" variant="ghost" onClick={onDetails}>
Details
</Button>
)}
{isRunning ? (
<Button size="sm" variant="danger" onClick={onStop}>
Stop
</Button>
) : (
<Button size="sm" variant="primary" onClick={onLaunch}>
Start
</Button>
)}
</div>
</Card>
);
}
|