feat: revue de code, doc CODE_REVIEW, forfaits 2026, traduction LLM, providers avec modèle

Made-with: Cursor
This commit is contained in:
Sepehr Ramezani
2026-03-07 11:42:58 +01:00
parent 3d37ce4582
commit 473b3e26c7
181 changed files with 30617 additions and 7170 deletions

View File

@@ -0,0 +1,141 @@
"use client";
import { Badge } from "@/components/ui/badge";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import type { AdminDashboardData, ProviderStatus } from "./types";
interface ProviderStatusProps {
data: AdminDashboardData | null;
isLoading: boolean;
}
const PROVIDER_LABELS: Record<string, string> = {
google: "Google Translate",
deepl: "DeepL",
ollama: "Ollama (Local)",
openai: "OpenAI",
openrouter: "OpenRouter",
};
const STATUS_CONFIG = {
online: {
dotClass: "bg-green-500",
label: "Online",
badgeClass:
"border-green-200/30 bg-green-500/10 text-green-600",
},
degraded: {
dotClass: "bg-yellow-500",
label: "Degraded",
badgeClass:
"border-yellow-200/30 bg-yellow-500/10 text-yellow-600",
},
offline: {
dotClass: "bg-red-500",
label: "Offline",
badgeClass: "border-red-200/30 bg-red-500/10 text-red-500",
},
};
function getProviderStatus(
provider: ProviderStatus
): "online" | "degraded" | "offline" {
if (provider.available) return "online";
if (provider.error) return "offline";
return "degraded";
}
export function ProviderStatus({ data, isLoading }: ProviderStatusProps) {
const providers = Object.entries(data?.providers || {});
if (isLoading && !data) {
return (
<div className="flex flex-col gap-2 rounded-lg border border-border bg-card px-4 py-3">
<div className="flex items-center justify-between">
<div className="h-3 w-32 animate-pulse rounded bg-muted" />
<div className="h-3 w-20 animate-pulse rounded bg-muted" />
</div>
<div className="flex flex-wrap gap-2">
{[1, 2, 3, 4].map((i) => (
<div
key={i}
className="h-6 w-28 animate-pulse rounded bg-muted"
/>
))}
</div>
</div>
);
}
if (providers.length === 0) {
return (
<div className="flex flex-col gap-2 rounded-lg border border-border bg-card px-4 py-3">
<span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground">
Translation API Providers
</span>
<span className="text-sm text-muted-foreground">
No provider data available
</span>
</div>
);
}
return (
<div className="flex flex-col gap-2 rounded-lg border border-border bg-card px-4 py-3">
<div className="flex items-center justify-between">
<span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground">
Translation API Providers
</span>
<span className="text-[10px] text-muted-foreground">
{providers.length} provider{providers.length !== 1 ? "s" : ""}
</span>
</div>
<div className="flex flex-wrap items-center gap-2">
{providers.map(([key, provider]) => {
const status = getProviderStatus(provider);
const config = STATUS_CONFIG[status];
const label = PROVIDER_LABELS[key] || provider.name || key;
return (
<Tooltip key={key}>
<TooltipTrigger asChild>
<Badge
variant="outline"
className={`cursor-default gap-1.5 px-2.5 py-1 text-xs font-medium ${config.badgeClass}`}
>
<span
className={`size-1.5 rounded-full ${config.dotClass}`}
/>
{label}
</Badge>
</TooltipTrigger>
<TooltipContent>
<div className="flex flex-col gap-0.5 text-xs">
<span className="font-medium">{config.label}</span>
{provider.latency_ms !== undefined && (
<span className="text-muted-foreground">
Latency: {provider.latency_ms}ms
</span>
)}
{provider.last_check && (
<span className="text-muted-foreground">
Last check:{" "}
{new Date(provider.last_check).toLocaleTimeString()}
</span>
)}
{provider.error && (
<span className="text-red-500">{provider.error}</span>
)}
</div>
</TooltipContent>
</Tooltip>
);
})}
</div>
</div>
);
}