import { useState } from "react"; import { trpc } from "@/lib/trpc"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Badge } from "@/components/ui/badge"; import { Upload, Download, FileSpreadsheet, CheckCircle2, XCircle, AlertTriangle, Loader2 } from "lucide-react"; import { toast } from "sonner"; export default function AdminImportExcel() { const [file, setFile] = useState(null); const [preview, setPreview] = useState(null); const [importing, setImporting] = useState(false); const previewMutation = trpc.formations.previewExcel.useMutation(); const importMutation = trpc.formations.importExcel.useMutation(); const handleFileChange = async (e: React.ChangeEvent) => { const selectedFile = e.target.files?.[0]; if (!selectedFile) return; if (!selectedFile.name.endsWith('.xlsx') && !selectedFile.name.endsWith('.xls')) { toast.error("Format de fichier invalide. Veuillez sélectionner un fichier Excel (.xlsx ou .xls)"); return; } setFile(selectedFile); setPreview(null); // Lire le fichier et générer la prévisualisation const reader = new FileReader(); reader.onload = async (event) => { try { const base64 = event.target?.result as string; const fileBase64 = base64.split(',')[1]; // Enlever le préfixe data:...;base64, const result = await previewMutation.mutateAsync({ fileBase64 }); setPreview(result); if (result.validation.errors.length > 0) { toast.error(`${result.validation.errors.length} erreur(s) détectée(s) dans le fichier`); } else { toast.success("Fichier valide ! Vous pouvez procéder à l'import."); } } catch (error: any) { toast.error(`Erreur lors de la lecture du fichier: ${error.message}`); } }; reader.readAsDataURL(selectedFile); }; const handleImport = async () => { if (!file) return; setImporting(true); try { const reader = new FileReader(); reader.onload = async (event) => { try { const base64 = event.target?.result as string; const fileBase64 = base64.split(',')[1]; const result = await importMutation.mutateAsync({ fileBase64 }); if (result.success) { toast.success( `Import réussi ! ${result.formationsCreated} formation(s) et ${result.sequencesCreated} séquence(s) créée(s).` ); setFile(null); setPreview(null); // Réinitialiser l'input file const fileInput = document.getElementById('file-input') as HTMLInputElement; if (fileInput) fileInput.value = ''; } else { toast.error(`Import échoué: ${result.errors.join(', ')}`); } setImporting(false); } catch (error: any) { toast.error(`Erreur lors de l'import: ${error.message}`); setImporting(false); } }; reader.readAsDataURL(file); } catch (error: any) { toast.error(`Erreur: ${error.message}`); setImporting(false); } }; const handleDownloadTemplate = () => { // Télécharger le template depuis /public const link = document.createElement('a'); link.href = '/template_import_formations.xlsx'; link.download = 'template_import_formations.xlsx'; link.click(); toast.success("Template téléchargé !"); }; return (

Import Excel - Formations et Séquences

Importez plusieurs formations et séquences en une seule fois à partir d'un fichier Excel

{/* Instructions */} Instructions Suivez ces étapes pour importer vos données
1

Téléchargez le template Excel

Le template contient deux feuilles : "Formations" et "Séquences" avec des exemples

2

Remplissez le fichier Excel

Suivez les instructions dans le fichier. Les colonnes obligatoires sont marquées.

3

Importez le fichier

Sélectionnez votre fichier ci-dessous. Une prévisualisation s'affichera avant l'import.

{/* Upload */} Sélectionner un fichier Excel
{file && (
{file.name}
)}
{/* Prévisualisation */} {preview && (
{/* Erreurs et Avertissements */} {preview.validation.errors.length > 0 && (

Erreurs détectées :

    {preview.validation.errors.map((error: string, index: number) => (
  • {error}
  • ))}
)} {preview.validation.warnings.length > 0 && (

Avertissements :

    {preview.validation.warnings.map((warning: string, index: number) => (
  • {warning}
  • ))}
)} {/* Formations */} Formations ({preview.formations.length})
{preview.formations.map((formation: any, index: number) => (

{formation.nom}

{formation.description}

{formation.publicCible}
))}
{/* Séquences */} Séquences ({preview.sequences.length})
{preview.sequences.map((sequence: any, index: number) => (

{sequence.nom}

Formation: {sequence.formationNom}

{sequence.statut}
Lieu: {sequence.lieu}
Capacité: {sequence.capaciteMax}
Public: {sequence.publicCible}
Dates: {sequence.dates.length}
))}
{/* Bouton d'import */}
)}
); }