import { useState } from "react";
import { trpc } from "@/lib/trpc";
import DashboardLayout from "@/components/DashboardLayout";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Badge } from "@/components/ui/badge";
import { toast } from "sonner";
import { Eye, Send, Upload, Trash2, FileText } from "lucide-react";
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog";
// Composant de dialogue d'upload d'attestation
function UploadAttestationDialog({
open,
onOpenChange,
inscriptionId,
onSuccess,
}: {
open: boolean;
onOpenChange: (open: boolean) => void;
inscriptionId: number | null;
onSuccess: () => void;
}) {
const [uploading, setUploading] = useState(false);
const [uploadProgress, setUploadProgress] = useState(0);
const [fileData, setFileData] = useState<{
nomFichier: string;
urlFichier: string;
s3Key: string;
typeFichier: string;
tailleFichier: number;
} | null>(null);
const uploadMutation = trpc.gestionAttestations.uploadDocument.useMutation({
onSuccess: () => {
onSuccess();
setFileData(null);
},
onError: (error) => {
toast.error(`Erreur lors de l'upload : ${error.message}`);
setUploading(false);
},
});
const handleUpload = () => {
if (!fileData || !inscriptionId) return;
setUploading(true);
uploadMutation.mutate({
inscriptionId,
documentUrl: fileData.urlFichier,
documentS3Key: fileData.s3Key,
});
};
return (
);
}
export default function AdminGestionAttestations() {
const [selectedFormationId, setSelectedFormationId] = useState(null);
const [modeAttestation, setModeAttestation] = useState<"auto" | "manuel">("auto");
const [modeEnvoi, setModeEnvoi] = useState<"auto" | "manuel">("manuel");
const [uploadDialogOpen, setUploadDialogOpen] = useState(false);
const [selectedInscriptionId, setSelectedInscriptionId] = useState(null);
const [previewUrl, setPreviewUrl] = useState(null);
const [previewDialogOpen, setPreviewDialogOpen] = useState(false);
const [filtreStatut, setFiltreStatut] = useState<"toutes" | "terminees" | "a_venir">("toutes");
// Récupérer la liste des formations
const { data: formations, isLoading: loadingFormations } = trpc.formations.list.useQuery();
// Récupérer la configuration de la formation sélectionnée
const { data: formationConfig, refetch: refetchConfig } = trpc.gestionAttestations.getFormationConfig.useQuery(
{ formationId: selectedFormationId! },
{ enabled: !!selectedFormationId }
);
// Récupérer les apprenants avec leur statut d'attestation
const { data: apprenants, isLoading: loadingApprenants, refetch: refetchApprenants } =
trpc.gestionAttestations.getApprenantsWithStatus.useQuery(
{ formationId: selectedFormationId! },
{ enabled: !!selectedFormationId }
);
// Mutation pour mettre à jour la configuration
const updateConfigMutation = trpc.gestionAttestations.updateFormationConfig.useMutation({
onSuccess: () => {
toast.success("Configuration enregistrée avec succès");
refetchConfig();
},
onError: (error) => {
toast.error(`Erreur : ${error.message}`);
},
});
// Mutation pour envoyer une attestation
const sendAttestationMutation = trpc.gestionAttestations.sendAttestation.useMutation({
onSuccess: () => {
toast.success("Attestation envoyée avec succès");
refetchApprenants();
},
onError: (error) => {
toast.error(`Erreur lors de l'envoi : ${error.message}`);
},
});
// Mutation pour supprimer un document
const deleteDocumentMutation = trpc.gestionAttestations.deleteDocument.useMutation({
onSuccess: () => {
toast.success("Document supprimé avec succès");
refetchApprenants();
},
onError: (error) => {
toast.error(`Erreur lors de la suppression : ${error.message}`);
},
});
// Mutation pour envoyer toutes les attestations
const sendAllMutation = trpc.gestionAttestations.sendAllAttestations.useMutation({
onSuccess: (result) => {
toast.success(`${result.succes} attestation(s) envoyée(s) avec succès${result.echecs > 0 ? `, ${result.echecs} échec(s)` : ''}`);
refetchApprenants();
},
onError: (error) => {
toast.error(`Erreur lors de l'envoi en masse : ${error.message}`);
},
});
// Charger la configuration quand une formation est sélectionnée
const handleFormationChange = (formationId: string) => {
const id = parseInt(formationId);
setSelectedFormationId(id);
// Charger la configuration existante
const config = formations?.find(f => f.id === id);
if (config) {
setModeAttestation((config as any).modeAttestation || "auto");
setModeEnvoi((config as any).modeEnvoi || "manuel");
}
};
// Enregistrer la configuration
const handleSaveConfig = () => {
if (!selectedFormationId) return;
updateConfigMutation.mutate({
formationId: selectedFormationId,
modeAttestation,
modeEnvoi,
});
};
// Prévisualiser un document
const handlePreview = (url: string) => {
setPreviewUrl(url);
setPreviewDialogOpen(true);
};
// Envoyer une attestation
const handleSendAttestation = (apprenant: any) => {
const pdfUrl = apprenant.attestation?.documentUrl || apprenant.attestation?.urlPdf;
if (!pdfUrl) {
toast.error("Aucune attestation disponible pour cet apprenant");
return;
}
sendAttestationMutation.mutate({
attestationId: apprenant.attestation.id,
sequenceId: apprenant.sequence.id,
apprenantId: apprenant.apprenant.id,
apprenantEmail: apprenant.apprenant.email,
apprenantNom: apprenant.apprenant.nom,
apprenantPrenom: apprenant.apprenant.prenom,
formationNom: formations?.find(f => f.id === selectedFormationId)?.nom || "",
pdfUrl: pdfUrl,
});
};
// Supprimer un document
const handleDeleteDocument = (attestationId: number) => {
if (confirm("Êtes-vous sûr de vouloir supprimer ce document ?")) {
deleteDocumentMutation.mutate({ attestationId });
}
};
// Envoyer toutes les attestations
const handleSendAll = () => {
if (!selectedFormationId) return;
// Compter le nombre d'attestations prêtes à envoyer
const attestationsReady = apprenants?.filter(item => {
const hasDocument = item.attestation && (item.attestation.urlPdf || item.attestation.documentUrl);
return hasDocument;
}).length || 0;
if (attestationsReady === 0) {
toast.error("Aucune attestation prête à envoyer");
return;
}
if (confirm(`Êtes-vous sûr de vouloir envoyer ${attestationsReady} attestation(s) ?`)) {
sendAllMutation.mutate({ formationId: selectedFormationId });
}
};
// Ouvrir le dialogue d'upload
const handleOpenUpload = (inscriptionId: number) => {
setSelectedInscriptionId(inscriptionId);
setUploadDialogOpen(true);
};
return (
Gestion des attestations de formation
Configurez le mode de génération et d'envoi des attestations pour chaque formation
{/* Sélection de la formation */}
Sélectionner une formation
Choisissez la formation pour laquelle vous souhaitez gérer les attestations
{/* Filtre par statut */}
{selectedFormationId && (
Filtrer les séquences
Afficher uniquement les séquences terminées ou à venir
setFiltreStatut(value)}>
)}
{/* Configuration */}
{selectedFormationId && (
Configuration de la formation
Définissez comment les attestations seront générées et envoyées
{/* Mode de génération */}
setModeAttestation(value)}>
{/* Mode d'envoi */}
setModeEnvoi(value)}>
)}
{/* Liste des apprenants */}
{selectedFormationId && (
Apprenants inscrits
Gérez les attestations pour chaque apprenant inscrit à cette formation