"use client"; import React from "react"; import { useQuery } from "@tanstack/react-query"; import { useTranslationStore } from "@/lib/store"; import { API_BASE } from "@/lib/config"; import type { StatsPeriod, TranslationStatsResponse } from "./types"; const TIMEOUT_MS = 15000; export const REFETCH_INTERVAL_MS = 30000; export const QUERY_KEY = (period: StatsPeriod) => ["admin", "stats", "translations", period]; async function fetchTranslationStats( adminToken: string | null | undefined, period: StatsPeriod ): Promise { if (!adminToken) { throw new Error("AUTH_REQUIRED"); } const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS); try { const response = await fetch( `${API_BASE}/api/v1/admin/stats/translations?period=${period}`, { headers: { Authorization: `Bearer ${adminToken}`, }, signal: controller.signal, } ); clearTimeout(timeoutId); if (!response.ok) { if (response.status === 401) { throw new Error("UNAUTHORIZED"); } if (response.status === 404) { throw new Error("ENDPOINT_NOT_FOUND"); } throw new Error(`HTTP_ERROR_${response.status}`); } return await response.json(); } catch (err) { clearTimeout(timeoutId); throw err; } } function getMockData(period: StatsPeriod): TranslationStatsResponse { const baseCount = period === "today" ? 42 : period === "week" ? 287 : 1156; const lastPeriodCount = period === "today" ? 38 : period === "week" ? 254 : 1023; return { data: { period, total_translations: baseCount, total_translations_last_period: lastPeriodCount, error_rate: 2.3, error_count: Math.floor(baseCount * 0.023), success_count: Math.floor(baseCount * 0.977), top_users: [ { user_id: "user_1", email: "sarah.chen@acme.com", translation_count: 15 }, { user_id: "user_2", email: "marc.dubois@example.fr", translation_count: 12 }, { user_id: "user_3", email: "anna.mueller@corp.de", translation_count: 8 }, { user_id: "user_4", email: "john.smith@company.uk", translation_count: 6 }, { user_id: "user_5", email: "lisa.wong@startup.io", translation_count: 5 }, { user_id: "user_6", email: "pierre.leroux@mail.fr", translation_count: 4 }, { user_id: "user_7", email: "emma.johnson@tech.us", translation_count: 3 }, { user_id: "user_8", email: "klaus.weber@firm.de", translation_count: 2 }, { user_id: "user_9", email: "sofia.garcia@empresa.es", translation_count: 2 }, { user_id: "user_10", email: "yuki.tanaka@office.jp", translation_count: 1 }, ], provider_breakdown: { google: { count: Math.floor(baseCount * 0.476), percentage: 47.6 }, ollama: { count: Math.floor(baseCount * 0.119), percentage: 11.9 }, openai: { count: Math.floor(baseCount * 0.048), percentage: 4.8 }, }, format_breakdown: { xlsx: { count: Math.floor(baseCount * 0.595), percentage: 59.5 }, docx: { count: Math.floor(baseCount * 0.286), percentage: 28.6 }, pptx: { count: Math.floor(baseCount * 0.119), percentage: 11.9 }, }, }, meta: { generated_at: new Date().toISOString(), }, }; } export function useTranslationStats(period: StatsPeriod = "today") { const { settings } = useTranslationStore(); const [isMockData, setIsMockData] = React.useState(false); const { data, isLoading, error, refetch } = useQuery({ queryKey: QUERY_KEY(period), queryFn: async () => { try { const result = await fetchTranslationStats(settings.adminToken, period); setIsMockData(false); return result; } catch (err) { if ((err as Error).message === "ENDPOINT_NOT_FOUND") { setIsMockData(true); return getMockData(period); } throw err; } }, enabled: !!settings.adminToken, refetchInterval: REFETCH_INTERVAL_MS, staleTime: 10000, retry: 1, }); const getErrorMessage = (err: Error | null): string | null => { if (!err) return null; const errorMap: Record = { AUTH_REQUIRED: "Veuillez vous connecter pour accéder aux statistiques", UNAUTHORIZED: "Session expirée. Veuillez vous reconnecter.", HTTP_ERROR_403: "Accès refusé. Droits administrateur requis.", HTTP_ERROR_500: "Erreur serveur. Veuillez réessayer plus tard.", }; const code = err.message; if (errorMap[code]) { return errorMap[code]; } if (err.name === "AbortError") { return "Le serveur met trop de temps à répondre."; } if (err.message.includes("fetch") || err.message.includes("network")) { return "Impossible de se connecter au serveur."; } return "Une erreur inattendue s'est produite."; }; const errorMessage = error ? getErrorMessage(error as Error) : null; return { data: data?.data ?? null, isLoading, error: errorMessage, refetch, queryKey: QUERY_KEY(period), isMockData, }; }