import React, { useEffect, useState } from 'react'; import { useStore } from '../stores/store'; import { api } from '../stores/api'; const DOMAINES = [ ['', 'Tous les domaines'], ['propositions', 'Gouvernance'], ['pv_reunions', 'Procès-verbaux'], ['collectes', 'Collectes'], ['depenses', 'Dépenses'], ['envois_contributions', 'Contributions'], ['reserves', 'Réserves'], ['operations_bancaires', 'Opérations bancaires'], ['mouvements_reserves', 'Virements réserves'], ['litterature', 'Littérature'], ['reunions', 'Rencontres'], ['destinataires_contributions', 'Destinataires'], ]; export default function JournalActions() { const { setPage } = useStore(); const [actions, setActions] = useState([]); const [historique, setHistorique] = useState([]); const [membres, setMembres] = useState([]); const [tab, setTab] = useState('historique'); const [filtres, setFiltres] = useState({ date_debut: '', date_fin: '', membre_id: '', table_cible: '', action: '', q: '' }); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const historiqueQuery = (source = filtres) => { const params = new URLSearchParams({ limite: '100' }); Object.entries(source).forEach(([key, value]) => { if (value) params.set(key, value); }); return `/journal/historique?${params.toString()}`; }; const charger = async (sourceFiltres = filtres) => { setLoading(true); setError(''); try { const [hist, acts, mbrs] = await Promise.all([ api.get(historiqueQuery(sourceFiltres)), api.get('/journal/actions?limite=100'), api.get('/membres/actifs'), ]); setHistorique(hist); setActions(acts); setMembres(mbrs); } catch (e) { setError(e.message); } finally { setLoading(false); } }; useEffect(() => { charger(); }, []); const formatDate = (value) => new Date(value).toLocaleString('fr-CA', { dateStyle: 'medium', timeStyle: 'short', }); const formatValeur = (value) => { if (value === null || value === undefined || value === '') return '—'; if (typeof value === 'boolean') return value ? 'oui' : 'non'; if (Array.isArray(value)) return `${value.length} élément(s)`; if (typeof value === 'object') return JSON.stringify(value); return String(value); }; const changements = (avant = {}, apres = {}) => { const cles = [...new Set([...Object.keys(avant || {}), ...Object.keys(apres || {})])]; return cles .map((cle) => [cle, avant?.[cle], apres?.[cle]]) .filter(([, a, b]) => JSON.stringify(a) !== JSON.stringify(b)); }; const updateFiltre = (key, value) => setFiltres((f) => ({ ...f, [key]: value })); const resetFiltres = () => { const vides = { date_debut: '', date_fin: '', membre_id: '', table_cible: '', action: '', q: '' }; setFiltres(vides); charger(vides); }; const actionsDisponibles = [...new Set(historique.map((item) => item.action))].sort(); return (

Journal

Changements enregistrés

{tab === 'historique' && (
updateFiltre('q', e.target.value)} placeholder="Rechercher dans les raisons" className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue text-sm" />
updateFiltre('date_debut', e.target.value)} className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue text-sm" /> updateFiltre('date_fin', e.target.value)} className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue text-sm" />
)} {loading &&

Chargement...

} {error &&
{error}
} {!loading && tab === 'historique' && historique.length === 0 && (

Aucun changement journalisé.

)} {!loading && tab === 'technique' && actions.length === 0 && (

Aucune action technique journalisée.

)} {tab === 'historique' && historique.map((item) => (

{item.raison}

{formatDate(item.cree_le)} · {item.membre_prenom || item.membre_id || 'Membre inconnu'}

{item.action}
{item.apres && changements(item.avant, item.apres).length > 0 && (
{changements(item.avant, item.apres).map(([cle, avant, apres]) => (
{cle} {formatValeur(avant)} → {formatValeur(apres)}
))}
)} {item.avant && !item.apres && (
{Object.entries(item.avant).map(([cle, valeur]) => (

{cle}: {formatValeur(valeur)}

))}
)}

Objet: {item.table_cible} · {item.objet_id}

))} {tab === 'technique' && actions.map((action) => (

{action.methode} {action.chemin}

{formatDate(action.cree_le)}

{action.statut_http}

Membre: {action.membre_id}

{action.admin_id &&

Admin: {action.admin_id}

} {action.adresse_ip &&

IP: {action.adresse_ip}

} {action.details?.impersonification && (

Action faite en impersonification

)}
))}
); }