Files
dynasqy/frontend/src/components/AdminLogs.jsx
T
2026-08-23 09:04:47 +00:00

92 lines
3.7 KiB
React

import { useState, useEffect } from 'react'
import { useAuth } from '../context/AuthContext'
const ACTION_LABELS = {
connexion: 'Connexion',
changement_mot_de_passe: 'Changement mot de passe',
recommandation_ajout: 'Recommandation ajoutée',
recommandation_modification: 'Recommandation modifiée',
recommandation_suppression: 'Recommandation supprimée',
invite_ajout: 'Invité ajouté',
invite_modification: 'Invité modifié',
invite_suppression: 'Invité supprimé',
invite_email_envoye: 'Email invitation envoyé',
candidature_demarrage: 'Candidature démarrée',
candidature_refus: 'Candidature refusée',
absence_ajout: 'Absence ajoutée',
absence_suppression: 'Absence supprimée',
}
export default function AdminLogs() {
const { authFetch } = useAuth()
const [logs, setLogs] = useState([])
const [page, setPage] = useState(1)
const [pages, setPages] = useState(1)
const [loading, setLoading] = useState(true)
const load = async (p) => {
setLoading(true)
setPage(p)
try {
const r = await authFetch(`/api/activity-logs?page=${p}&limit=50`)
if (r.ok) { const d = await r.json(); setLogs(d.logs); setPages(d.pages) }
} catch {} finally { setLoading(false) }
}
useEffect(() => { load(1) }, [])
return (
<div className="space-y-4">
<h2 className="text-xl font-bold text-gray-800">Journal d'activité</h2>
{loading ? (
<p className="text-center text-gray-400 py-8">Chargement...</p>
) : logs.length === 0 ? (
<p className="text-center text-gray-400 py-8">Aucune activité enregistrée</p>
) : (
<div className="bg-white rounded-xl shadow-sm overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="bg-gray-50 text-left text-xs text-gray-500 uppercase">
<th className="px-4 py-3">Date</th>
<th className="px-4 py-3">Utilisateur</th>
<th className="px-4 py-3">Action</th>
<th className="px-4 py-3">Détails</th>
</tr>
</thead>
<tbody className="divide-y">
{logs.map((log) => (
<tr key={log.id} className="hover:bg-gray-50">
<td className="px-4 py-2.5 text-gray-500 whitespace-nowrap">
{new Date(log.created_at).toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' })}
</td>
<td className="px-4 py-2.5 whitespace-nowrap font-medium">{log.user_prenom} {log.user_nom}</td>
<td className="px-4 py-2.5 whitespace-nowrap">
<span className="bg-blue-100 text-blue-800 text-xs font-medium px-2 py-0.5 rounded">
{ACTION_LABELS[log.action] || log.action}
</span>
</td>
<td className="px-4 py-2.5 text-gray-600 max-w-xs truncate">
{log.details ? (() => { try { return JSON.stringify(JSON.parse(log.details), null, 1).replace(/[{}"]/g, '').replace(/,/g, ', ').trim() } catch { return log.details } })() : '-'}
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
{pages > 1 && (
<div className="flex justify-center gap-2">
{Array.from({ length: pages }, (_, i) => i + 1).map((p) => (
<button key={p} onClick={() => load(p)}
className={`w-8 h-8 rounded-lg text-sm font-medium ${p === page ? 'bg-blue-900 text-white' : 'bg-white text-gray-600 border hover:bg-gray-50'}`}>
{p}
</button>
))}
</div>
)}
</div>
)
}