"use client"; import { useEffect, useState, Suspense } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { useTranslationStore } from "@/lib/store"; import { motion } from "framer-motion"; import { Users, Activity, Settings, FileText, TrendingUp, Server, Key, LogOut, RefreshCw, Search, ChevronRight, Shield, Zap, Globe, DollarSign } from "lucide-react"; interface DashboardData { translations_today: number; translations_total: number; active_users: number; popular_languages: { [key: string]: number }; average_processing_time: number; cache_hit_rate: number; openrouter_usage?: { total_cost: number; requests_count: number; models_used: { [key: string]: number }; }; } interface User { id: string; email: string; username: string; plan: string; translations_count: number; is_active: boolean; created_at: string; last_login?: string; } interface AdminSettings { default_provider: string; openrouter_enabled: boolean; google_enabled: boolean; max_file_size_mb: number; rate_limit_per_minute: number; cache_enabled: boolean; } function AdminContent() { const router = useRouter(); const searchParams = useSearchParams(); const { adminToken } = useTranslationStore(); const [activeTab, setActiveTab] = useState<"overview" | "users" | "config" | "settings">("overview"); const [dashboardData, setDashboardData] = useState(null); const [users, setUsers] = useState([]); const [settings, setSettings] = useState({ default_provider: "google", openrouter_enabled: true, google_enabled: true, max_file_size_mb: 10, rate_limit_per_minute: 60, cache_enabled: true }); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [searchQuery, setSearchQuery] = useState(""); const [refreshing, setRefreshing] = useState(false); const API_BASE = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000"; useEffect(() => { const tab = searchParams.get("tab"); if (tab && ["overview", "users", "config", "settings"].includes(tab)) { setActiveTab(tab as any); } }, [searchParams]); useEffect(() => { if (!adminToken) { router.push("/admin/login"); return; } fetchDashboardData(); }, [adminToken]); useEffect(() => { if (activeTab === "users" && users.length === 0) { fetchUsers(); } }, [activeTab]); const fetchDashboardData = async () => { try { setLoading(true); const response = await fetch(`${API_BASE}/admin/dashboard`, { headers: { Authorization: `Bearer ${adminToken}` } }); if (!response.ok) throw new Error("Failed to fetch dashboard data"); const data = await response.json(); setDashboardData(data); } catch (err) { setError("Erreur de chargement des données"); console.error(err); } finally { setLoading(false); } }; const fetchUsers = async () => { try { const response = await fetch(`${API_BASE}/admin/users`, { headers: { Authorization: `Bearer ${adminToken}` } }); if (!response.ok) throw new Error("Failed to fetch users"); const data = await response.json(); setUsers(data.users || []); } catch (err) { console.error("Error fetching users:", err); } }; const refreshData = async () => { setRefreshing(true); await fetchDashboardData(); if (activeTab === "users") { await fetchUsers(); } setRefreshing(false); }; const handleLogout = () => { useTranslationStore.getState().setAdminToken(null); router.push("/admin/login"); }; const filteredUsers = users.filter(user => user.email?.toLowerCase().includes(searchQuery.toLowerCase()) || user.username?.toLowerCase().includes(searchQuery.toLowerCase()) ); if (loading) { return (
Chargement...
); } return (
{/* Header */}

Administration

{/* Tab Navigation */}
{[ { id: "overview", label: "Vue d'ensemble", icon: Activity }, { id: "users", label: "Utilisateurs", icon: Users }, { id: "config", label: "Configuration", icon: Server }, { id: "settings", label: "Paramètres", icon: Settings } ].map((tab) => ( ))}
{/* Overview Tab */} {activeTab === "overview" && dashboardData && ( {/* Stats Grid */}
{/* OpenRouter Usage */} {dashboardData.openrouter_usage && (

Utilisation OpenRouter

Coût Total

${dashboardData.openrouter_usage.total_cost?.toFixed(4) ?? '0.0000'}

Requêtes

{dashboardData.openrouter_usage.requests_count ?? 0}

Temps Moyen

{(dashboardData.average_processing_time ?? 0).toFixed(2)}s

)} {/* Popular Languages */}

Langues Populaires

{Object.entries(dashboardData.popular_languages || {}).slice(0, 8).map(([lang, count]) => (

{count}

{lang}

))}
)} {/* Users Tab */} {activeTab === "users" && ( {/* Search */}
setSearchQuery(e.target.value)} className="w-full pl-10 pr-4 py-3 bg-black/30 border border-white/10 rounded-xl text-white placeholder:text-gray-500 focus:outline-none focus:border-purple-500" />
{filteredUsers.length} utilisateur(s)
{/* Users Table */}
{filteredUsers.map((user) => ( ))} {filteredUsers.length === 0 && ( )}
Utilisateur Plan Traductions Statut Inscrit le

{user.username || 'N/A'}

{user.email}

{user.plan || 'free'} {user.translations_count ?? 0} {user.is_active ? 'Actif' : 'Inactif'} {user.created_at ? new Date(user.created_at).toLocaleDateString('fr-FR') : 'N/A'}
Aucun utilisateur trouvé
)} {/* Config Tab */} {activeTab === "config" && ( {/* Translation Providers */}

Fournisseurs de Traduction

{/* Google Translate */}

Google Translate

API officielle Google Cloud

{/* OpenRouter */}

OpenRouter

Modèles IA avancés (GPT-4, Claude, etc.)

{/* API Keys */}

Clés API

{/* Default Provider */}

Fournisseur par Défaut

)} {/* Settings Tab */} {activeTab === "settings" && ( {/* Limits */}

Limites

setSettings({ ...settings, max_file_size_mb: parseInt(e.target.value) || 10 })} className="w-full px-4 py-3 bg-black/30 border border-white/10 rounded-xl text-white focus:outline-none focus:border-purple-500" />
setSettings({ ...settings, rate_limit_per_minute: parseInt(e.target.value) || 60 })} className="w-full px-4 py-3 bg-black/30 border border-white/10 rounded-xl text-white focus:outline-none focus:border-purple-500" />
{/* Cache */}

Cache

Cache des traductions

Améliore les performances et réduit les coûts

{/* Save Button */}
)}
); } function StatCard({ title, value, icon: Icon, color }: { title: string; value: string | number; icon: any; color: string }) { const colorClasses = { purple: 'bg-purple-500/20 text-purple-400', blue: 'bg-blue-500/20 text-blue-400', green: 'bg-green-500/20 text-green-400', yellow: 'bg-yellow-500/20 text-yellow-400' }; return (

{value}

{title}

); } export default function AdminPage() { return (
Chargement...
}>
); }