fiemwl / src /shared /components /cli /CliToolCard.tsx
automindy's picture
Upload 1980 files
6111b2b verified
Raw
History Blame Contribute Delete
5.26 kB
"use client";
import Link from "next/link";
import Image from "next/image";
import type { CliCatalogEntry } from "@/shared/schemas/cliCatalog";
import type { ToolBatchStatus } from "@/shared/types/cliBatchStatus";
import CliStatusBadge from "@/app/(dashboard)/dashboard/cli-code/components/CliStatusBadge";
import { cn } from "@/shared/utils/cn";
export interface CliToolCardProps {
tool: CliCatalogEntry;
batchStatus: ToolBatchStatus | null;
detailHref: string;
hasActiveProviders: boolean;
}
export default function CliToolCard({
tool,
batchStatus,
detailHref,
hasActiveProviders,
}: CliToolCardProps) {
const installed = batchStatus?.detection.installed ?? false;
const configStatus = batchStatus?.config.status ?? null;
const version = batchStatus?.detection.version ?? "not found";
const endpoint = batchStatus?.config.endpoint ?? null;
const showInstallChips = !installed && tool.configType !== "guide";
const title = (
<div className="flex items-center gap-2.5">
{/* Icon / image */}
{tool.image ? (
<Image
src={tool.image}
alt={tool.name}
width={32}
height={32}
className="rounded-md object-contain flex-shrink-0"
/>
) : (
<span
className="material-symbols-outlined text-[20px] flex-shrink-0"
style={{ color: tool.color }}
aria-hidden="true"
>
{tool.icon ?? "terminal"}
</span>
)}
<div className="min-w-0 flex-1">
<div className="flex items-center gap-2 flex-wrap">
<span className="font-semibold text-text-main text-sm leading-tight truncate">
{tool.name}
</span>
<span className="text-[11px] text-text-muted font-mono bg-black/5 dark:bg-white/5 px-1.5 py-0.5 rounded">
{version}
</span>
</div>
<p className="text-xs text-text-muted line-clamp-1 mt-0.5">{tool.description}</p>
</div>
<span className="material-symbols-outlined text-[18px] text-text-muted flex-shrink-0">
chevron_right
</span>
</div>
);
return (
<Link
href={detailHref}
className={cn(
"block min-h-[180px]",
"bg-surface border border-black/5 dark:border-white/5 rounded-lg shadow-sm",
"hover:shadow-md hover:border-primary/30 transition-all",
"p-4 flex flex-col gap-3"
)}
>
{/* Header */}
{title}
{/* Status strip */}
<div className="flex items-center gap-2 flex-wrap">
{/* Detection */}
<span
className={cn(
"inline-flex items-center gap-1 text-[11px] font-medium px-1.5 py-0.5 rounded",
installed
? "text-green-600 dark:text-green-400"
: "text-zinc-500 dark:text-zinc-400"
)}
>
<span aria-hidden="true">{installed ? "✓" : "✗"}</span>
{installed ? "Detectado" : "Não detectado"}
</span>
{/* Config status */}
{configStatus && (
<CliStatusBadge
effectiveConfigStatus={configStatus}
batchStatus={null}
lastConfiguredAt={batchStatus?.config.lastConfiguredAt ?? null}
/>
)}
{/* Endpoint */}
{endpoint && (
<span className="text-[10px] text-text-muted font-mono truncate max-w-[140px]">
{endpoint}
</span>
)}
</div>
{/* Badges row */}
<div className="flex items-center gap-1.5 flex-wrap">
{tool.baseUrlSupport === "partial" && (
<span className="inline-flex items-center gap-1 px-2 py-0.5 text-[11px] font-medium rounded-full bg-amber-500/10 text-amber-600 dark:text-amber-400">
<span aria-hidden="true"></span> Base URL parcial
</span>
)}
{tool.acpSpawnable === true && (
<span className="inline-flex items-center gap-1 px-2 py-0.5 text-[11px] font-medium rounded-full bg-blue-500/10 text-blue-600 dark:text-blue-400">
também ACP
</span>
)}
{showInstallChips && (
<>
<span className="inline-flex items-center gap-1 px-2 py-0.5 text-[11px] font-medium rounded-full bg-black/5 dark:bg-white/5 text-text-muted">
📋 Manual config
</span>
<span className="inline-flex items-center gap-1 px-2 py-0.5 text-[11px] font-medium rounded-full bg-black/5 dark:bg-white/5 text-text-muted">
⬇ Install
</span>
</>
)}
</div>
{/* Footer */}
<div className="mt-auto pt-1 flex items-center justify-between">
<span className="text-xs text-primary font-medium">
{installed ? "Configurar →" : "Como instalar →"}
</span>
{!hasActiveProviders && (
<span
className="text-[10px] text-text-muted italic"
title="Conecte um provider em Providers"
>
Conecte um provider em Providers
</span>
)}
</div>
</Link>
);
}