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,115 @@
"use client";
import { Cpu } from "lucide-react";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import type { TranslationStatsData } from "./types";
interface ProviderBreakdownChartProps {
data: TranslationStatsData | null;
isLoading: boolean;
}
const providerLabels: Record<string, string> = {
google: "Google Translate",
deepl: "DeepL",
ollama: "Ollama (Local)",
openai: "OpenAI",
};
const providerColors: Record<string, string> = {
google: "bg-blue-500",
deepl: "bg-indigo-500",
ollama: "bg-green-500",
openai: "bg-purple-500",
};
export function ProviderBreakdownChart({ data, isLoading }: ProviderBreakdownChartProps) {
if (isLoading) {
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Cpu className="h-5 w-5" />
Répartition par Provider
</CardTitle>
<CardDescription>Chargement...</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
{[1, 2, 3, 4].map((i) => (
<div key={i} className="space-y-2">
<div className="h-4 w-20 animate-pulse rounded bg-muted" />
<div className="h-2 w-full animate-pulse rounded bg-muted" />
</div>
))}
</div>
</CardContent>
</Card>
);
}
if (!data?.provider_breakdown) {
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Cpu className="h-5 w-5" />
Répartition par Provider
</CardTitle>
<CardDescription>Aucune donnée disponible</CardDescription>
</CardHeader>
<CardContent>
<div className="flex items-center justify-center py-8 text-muted-foreground">
<p className="text-sm">Aucune donnée de provider</p>
</div>
</CardContent>
</Card>
);
}
const providers = Object.entries(data.provider_breakdown).filter(
([, value]) => value.count > 0
);
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Cpu className="h-5 w-5" />
Répartition par Provider
</CardTitle>
<CardDescription>
Distribution des traductions par fournisseur de service
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
{providers.map(([provider, value]) => (
<div key={provider} className="space-y-2">
<div className="flex items-center justify-between text-sm">
<span className="font-medium">
{providerLabels[provider] || provider}
</span>
<span className="text-muted-foreground">
{value.count} ({value.percentage.toFixed(1)}%)
</span>
</div>
<div className="relative h-2 w-full overflow-hidden rounded-full bg-secondary">
<div
className={`h-full ${providerColors[provider] || "bg-primary"} transition-all duration-500`}
style={{ width: `${value.percentage}%` }}
/>
</div>
</div>
))}
</div>
</CardContent>
</Card>
);
}