import { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Calendar, ArrowLeft, Search, CheckCircle, XCircle, Edit, Trash2, ClipboardList } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { toast } from "sonner"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; interface HistoriqueAction { Id: number; collaborateur: string; realisePar: string; Action: string; Details: string; DateAction: string; AdresseIP: string; DemandeCongeId: number; } const Historique = () => { const navigate = useNavigate(); const [historique, setHistorique] = useState([]); const [recherche, setRecherche] = useState(""); const [filtreAction, setFiltreAction] = useState("all"); const [dateDebut, setDateDebut] = useState(""); const [dateFin, setDateFin] = useState(""); const [loading, setLoading] = useState(false); useEffect(() => { chargerHistorique(); }, [filtreAction, dateDebut, dateFin]); const chargerHistorique = async () => { setLoading(true); try { const token = localStorage.getItem('token'); const params = new URLSearchParams(); if (dateDebut) params.append('dateDebut', dateDebut); if (dateFin) params.append('dateFin', dateFin); if (filtreAction !== 'all') params.append('action', filtreAction); const response = await fetch( `/api/historique?${params.toString()}`, { headers: { 'Authorization': `Bearer ${token}` } } ); // ⭐ VÉRIFICATION if (!response.ok) { throw new Error(`Erreur ${response.status}`); } const data = await response.json(); // ⭐ SÉCURITÉ : Vérifier que c'est un tableau if (Array.isArray(data)) { setHistorique(data); } else { console.error('❌ Format historique invalide:', data); setHistorique([]); } } catch (error) { console.error('❌ Erreur chargement historique:', error); toast.error("Erreur lors du chargement de l'historique"); setHistorique([]); // ⭐ Toujours mettre un tableau vide en cas d'erreur } finally { setLoading(false); } }; // ⭐ SÉCURITÉ : Vérifier que historique est un tableau avant filter const historiqueFiltré = Array.isArray(historique) ? historique.filter(h => { const matchRecherche = h.collaborateur?.toLowerCase().includes(recherche.toLowerCase()) || h.realisePar?.toLowerCase().includes(recherche.toLowerCase()) || h.Details?.toLowerCase().includes(recherche.toLowerCase()); return matchRecherche; }) : []; const getActionIcon = (action: string) => { if (action.includes('Validation')) return ; if (action.includes('Refus')) return ; if (action.includes('Modification')) return ; if (action.includes('Suppression')) return ; return ; }; const getActionBadge = (action: string) => { if (action.includes('Validation')) { return {action} ; } if (action.includes('Refus')) { return {action} ; } if (action.includes('Modification')) { return {action} ; } return {action}; }; const formatDateTime = (dateString: string) => { return new Date(dateString).toLocaleString('fr-FR', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }); }; const exporterHistorique = () => { if (historiqueFiltré.length === 0) { toast.error("Aucune donnée à exporter"); return; } const headers = ['Date et heure', 'Collaborateur concerné', 'Action réalisée par', 'Action', 'Détails', 'Demande ID']; const csvContent = [ headers.join(';'), ...historiqueFiltré.map(row => [ formatDateTime(row.DateAction), row.collaborateur, row.realisePar, row.Action, row.Details, row.DemandeCongeId || '' ].join(';')) ].join('\n'); const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = `historique_actions_${new Date().toISOString().split('T')[0]}.csv`; link.click(); toast.success("Export réussi"); }; return (

Historique des actions

setRecherche(e.target.value)} className="pl-10" />
setDateDebut(e.target.value)} placeholder="Date début" /> setDateFin(e.target.value)} placeholder="Date fin" />

Total actions

{historiqueFiltré.length}

Validations

{historique.filter(h => h.Action.includes('Validation')).length}

Refus

{historique.filter(h => h.Action.includes('Refus')).length}

Modifications

{historique.filter(h => h.Action.includes('Modification')).length}

Journal des actions Traçabilité complète de toutes les actions effectuées {loading ? (

Chargement...

) : historiqueFiltré.length > 0 ? (
Date et heure Collaborateur concerné Action réalisée par Action Détails Demande {historiqueFiltré.map((action) => ( {formatDateTime(action.DateAction)} {action.collaborateur} {action.realisePar || '-'}
{getActionIcon(action.Action)} {getActionBadge(action.Action)}

{action.Details}

{action.DemandeCongeId ? ( ) : ( - )}
))}
) : (

Aucune action trouvée

)}
); }; export default Historique;