import { useState } from "react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Switch } from "@/components/ui/switch"; import { Label } from "@/components/ui/label"; import { useToast } from "@/hooks/use-toast"; import { useAuthUnified } from "@/hooks/useAuthUnified"; import { apiRequest } from "@/lib/queryClient"; import { hasPermission } from "@/lib/permissions"; import { Download, Trash2, Database, Clock, User, FileText, AlertTriangle, CheckCircle, Loader2, Settings } from "lucide-react"; import { format } from "date-fns"; import { fr } from "date-fns/locale"; interface BackupFile { id: string; filename: string; description: string | null; size: number; createdAt: string; createdBy: string; tablesCount: number; status: string; backupType: string; } interface UtilitiesConfig { id?: number; salesAnalysisUrl?: string | null; automaticBackupsEnabled?: boolean; createdAt?: Date; updatedAt?: Date; } export default function BackupManager() { const { user } = useAuthUnified(); const { toast } = useToast(); const queryClient = useQueryClient(); const [deletingBackup, setDeletingBackup] = useState(null); // Check permissions - Seulement les admins peuvent gérer les sauvegardes const canManageBackups = hasPermission(user?.role || '', 'backups', 'manage'); // Fetch backup list const { data: backups = [], isLoading, error } = useQuery({ queryKey: ['/api/backups'], queryFn: () => apiRequest('/api/backups'), enabled: canManageBackups, refetchInterval: 30000, // Refresh every 30 seconds }); // Fetch utilities configuration const { data: config } = useQuery({ queryKey: ['/api/utilities'], enabled: canManageBackups, }); // Toggle automatic backups const toggleAutomaticBackupsMutation = useMutation({ mutationFn: (enabled: boolean) => apiRequest('/api/utilities', 'POST', { automaticBackupsEnabled: enabled }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/api/utilities'] }); toast({ title: "Configuration mise à jour", description: config?.automaticBackupsEnabled ? "Sauvegardes automatiques désactivées" : "Sauvegardes automatiques activées", }); }, onError: (error: any) => { toast({ title: "Erreur", description: error.message || "Impossible de mettre à jour la configuration", variant: "destructive", }); }, }); // Create manual backup const createBackupMutation = useMutation({ mutationFn: () => apiRequest('/api/backups', 'POST'), onSuccess: () => { toast({ title: "Succès", description: "Sauvegarde manuelle créée avec succès", }); queryClient.invalidateQueries({ queryKey: ['/api/backups'] }); }, onError: (error: any) => { toast({ title: "Erreur", description: error.message || "Impossible de créer la sauvegarde", variant: "destructive", }); }, }); // Delete backup const deleteBackupMutation = useMutation({ mutationFn: (filename: string) => apiRequest(`/api/backups/${filename}`, 'DELETE'), onSuccess: () => { toast({ title: "Succès", description: "Sauvegarde supprimée avec succès", }); queryClient.invalidateQueries({ queryKey: ['/api/backups'] }); setDeletingBackup(null); }, onError: (error: any) => { toast({ title: "Erreur", description: error.message || "Impossible de supprimer la sauvegarde", variant: "destructive", }); setDeletingBackup(null); }, }); const handleDownload = (filename: string) => { // Create download link const link = document.createElement('a'); link.href = `/api/backups/${filename}/download`; link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; const handleDelete = (filename: string) => { setDeletingBackup(filename); deleteBackupMutation.mutate(filename); }; const formatFileSize = (bytes: number): string => { const sizes = ['Bytes', 'KB', 'MB', 'GB']; if (bytes === 0) return '0 Bytes'; const i = Math.floor(Math.log(bytes) / Math.log(1024)); return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i]; }; const getTypeIcon = (type: string) => { return type === 'automatic' ? : ; }; const getTypeBadge = (type: string) => { return type === 'automatic' ? Automatique : Manuelle; }; const getStatusBadge = (status: string) => { switch (status) { case 'completed': return Terminé; case 'creating': return En cours; case 'failed': return Échec; default: return {status}; } }; if (!canManageBackups) { return (
Accès refusé Vous n'avez pas les permissions nécessaires pour accéder à la gestion des sauvegardes.
); } return (
{/* Header */}

Gestion des Sauvegardes

Sauvegarde automatique quotidienne à 2h00 - Maximum 10 fichiers conservés

{/* Content */}
{/* Configuration des backups automatiques */} Configuration des Sauvegardes Automatiques Activez ou désactivez les sauvegardes automatiques quotidiennes à 2h00

{config?.automaticBackupsEnabled === false ? "Les sauvegardes automatiques sont actuellement désactivées" : "Les sauvegardes automatiques sont actives"}

toggleAutomaticBackupsMutation.mutate(checked)} disabled={toggleAutomaticBackupsMutation.isPending} data-testid="switch-automatic-backups" />
{/* Status Cards */}
Total Sauvegardes
{backups.length}

Maximum 10 fichiers

Dernière Sauvegarde
{backups.length > 0 ? ( format(new Date(backups[0].createdAt), 'dd/MM', { locale: fr }) ) : '-'}

{backups.length > 0 ? ( format(new Date(backups[0].createdAt), 'HH:mm', { locale: fr }) ) : 'Aucune sauvegarde'}

Statut Système {config?.automaticBackupsEnabled !== false ? ( ) : ( )}
{config?.automaticBackupsEnabled !== false ? 'Actif' : 'Désactivé'}

{config?.automaticBackupsEnabled !== false ? 'Sauvegarde automatique 2h00' : 'Backups automatiques désactivés'}

{/* Backup List */} Liste des Sauvegardes Gestion des fichiers de sauvegarde de la base de données PostgreSQL {isLoading ? (
) : error ? (
Erreur lors du chargement des sauvegardes
) : backups.length === 0 ? (
Aucune sauvegarde disponible
) : (
{backups.map((backup: BackupFile) => (
{getTypeIcon(backup.backupType)}
{backup.filename}
{backup.description || 'Sauvegarde de base de données'}
{format(new Date(backup.createdAt), 'dd/MM/yyyy à HH:mm', { locale: fr })} {formatFileSize(backup.size)} {backup.tablesCount} tables {getTypeBadge(backup.backupType)} {getStatusBadge(backup.status)}
))}
)}
); }