"use client"; import { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; import { Label } from "@/components/ui/label"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "@/components/ui/alert-dialog"; import { Database, Trash2, RotateCcw, Save, Clock } from "lucide-react"; import { formatDistanceToNow } from "date-fns"; import { fr } from "date-fns/locale/fr"; import { toast } from "sonner"; interface Backup { id: string; filename: string; size: number; createdAt: Date; } interface BackupSettings { enabled: boolean; frequency: "hourly" | "daily" | "weekly" | "monthly"; lastBackup?: string; nextBackup?: string; } export function BackupCard() { const [backups, setBackups] = useState([]); const [settings, setSettings] = useState({ enabled: true, frequency: "hourly", }); const [loading, setLoading] = useState(true); const [creating, setCreating] = useState(false); const [restoring, setRestoring] = useState(null); const loadData = async () => { try { const [backupsRes, settingsRes] = await Promise.all([ fetch("/api/backups"), fetch("/api/backups/settings"), ]); const backupsData = await backupsRes.json(); const settingsData = await settingsRes.json(); if (backupsData.success) { setBackups( backupsData.data.map( (b: { id: string; filename: string; size: number; createdAt: string; }) => ({ ...b, createdAt: new Date(b.createdAt), }), ), ); } if (settingsData.success) { setSettings(settingsData.data); } } catch (error) { console.error("Error loading backup data:", error); toast.error("Erreur lors du chargement des données"); } finally { setLoading(false); } }; useEffect(() => { loadData(); }, []); const handleCreateBackup = async () => { setCreating(true); try { const response = await fetch("/api/backups", { method: "POST", }); const data = await response.json(); if (data.success) { if (data.data.skipped) { toast.info( "Aucun changement détecté. La dernière sauvegarde a été mise à jour.", ); } else { toast.success("Sauvegarde créée avec succès"); } await loadData(); } else { toast.error(data.error || "Erreur lors de la création"); } } catch (error) { console.error("Error creating backup:", error); toast.error("Erreur lors de la création de la sauvegarde"); } finally { setCreating(false); } }; const handleDeleteBackup = async (id: string) => { try { const response = await fetch(`/api/backups/${id}`, { method: "DELETE", }); const data = await response.json(); if (data.success) { toast.success("Sauvegarde supprimée"); await loadData(); } else { toast.error(data.error || "Erreur lors de la suppression"); } } catch (error) { console.error("Error deleting backup:", error); toast.error("Erreur lors de la suppression"); } }; const handleRestoreBackup = async (id: string) => { setRestoring(id); try { const response = await fetch(`/api/backups/${id}/restore`, { method: "POST", }); const data = await response.json(); if (data.success) { toast.success( "Sauvegarde restaurée avec succès. Rechargement de la page...", ); setTimeout(() => { window.location.reload(); }, 2000); } else { toast.error(data.error || "Erreur lors de la restauration"); } } catch (error) { console.error("Error restoring backup:", error); toast.error("Erreur lors de la restauration"); } finally { setRestoring(null); } }; const handleSettingsChange = async (updates: Partial) => { const newSettings = { ...settings, ...updates }; setSettings(newSettings); try { const response = await fetch("/api/backups/settings", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(updates), }); const data = await response.json(); if (data.success) { setSettings(data.data); toast.success("Paramètres mis à jour"); } else { toast.error("Erreur lors de la mise à jour"); await loadData(); // Revert on error } } catch (error) { console.error("Error updating settings:", error); toast.error("Erreur lors de la mise à jour"); await loadData(); // Revert on error } }; const formatFileSize = (bytes: number): string => { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`; return `${(bytes / (1024 * 1024)).toFixed(2)} MB`; }; if (loading) { return ( Sauvegardes automatiques

Chargement...

); } return ( Sauvegardes automatiques Configurez les sauvegardes périodiques de votre base de données {/* Settings */}

Activez les sauvegardes périodiques

handleSettingsChange({ enabled: checked }) } />
{settings.enabled && (
)} {settings.enabled && settings.lastBackup && (
Dernière sauvegarde:{" "} {formatDistanceToNow(new Date(settings.lastBackup), { addSuffix: true, locale: fr, })}
)} {settings.enabled && settings.nextBackup && (
Prochaine sauvegarde:{" "} {formatDistanceToNow(new Date(settings.nextBackup), { addSuffix: true, locale: fr, })}
)}
{/* Manual backup */}
{/* Backups list */} {backups.length > 0 && (
Date Taille Actions {backups.map((backup) => (
{backup.createdAt.toLocaleDateString("fr-FR", { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit", })} {formatDistanceToNow(backup.createdAt, { addSuffix: true, locale: fr, })}
{formatFileSize(backup.size)}
Restaurer cette sauvegarde ? Cette action va remplacer votre base de données actuelle par cette sauvegarde. Une sauvegarde de sécurité sera créée avant la restauration. Annuler handleRestoreBackup(backup.id)} > Restaurer Supprimer cette sauvegarde ? Cette action est irréversible. La sauvegarde sera définitivement supprimée. Annuler handleDeleteBackup(backup.id)} > Supprimer
))}
)} {backups.length === 0 && (
Aucune sauvegarde pour le moment
)}
); }