import React, { useState, useEffect } from 'react'; import { api } from '../stores/api'; import { useStore } from '../stores/store'; import PageHeader from '../components/PageHeader'; export default function GererMembres() { const { membre, groupe, estSysadmin, impersoner } = useStore(); const [membres, setMembres] = useState([]); const [loading, setLoading] = useState(true); const [detail, setDetail] = useState(null); const [confirmAction, setConfirmAction] = useState(null); const [msg, setMsg] = useState(''); const [code, setCode] = useState(null); const [expiration, setExpiration] = useState(null); const [inviteLoading, setInviteLoading] = useState(false); const [copied, setCopied] = useState(false); const [showCreate, setShowCreate] = useState(false); const [createLoading, setCreateLoading] = useState(false); const [createForm, setCreateForm] = useState({ prenom: '', nom: '', telephone: '', courriel: '', pin: '', date_abstinence: '', }); const charger = async () => { setLoading(true); try { const data = await api.get('/membres/'); setMembres(data); } catch {} setLoading(false); }; useEffect(() => { charger(); }, []); const genererInvitation = async () => { setInviteLoading(true); try { const data = await api.post('/invitations/'); setCode(data.code); setExpiration(new Date(data.expire_le).toLocaleString('fr-CA')); } catch (e) { alert(e.message); } setInviteLoading(false); }; const copierInvitation = () => { navigator.clipboard.writeText(code).then(() => { setCopied(true); setTimeout(() => setCopied(false), 2000); }); }; const partagerSMS = () => { const texte = `Rejoins ${groupe?.nom || 'le groupe'} sur l'app. Ton code d'invitation : ${code}`; window.open(`sms:?body=${encodeURIComponent(texte)}`); }; const desactiver = async (id) => { try { const res = await api.patch(`/membres/${id}/desactiver`); setMsg(res.message); setConfirmAction(null); setDetail(null); charger(); setTimeout(() => setMsg(''), 3000); } catch (e) { alert(e.message); } }; const reactiver = async (id) => { try { const res = await api.patch(`/membres/${id}/reactiver`); setMsg(res.message); setConfirmAction(null); setDetail(null); charger(); setTimeout(() => setMsg(''), 3000); } catch (e) { alert(e.message); } }; const droitOubli = async (id) => { try { const res = await api.request('DELETE', `/membres/${id}/oubli`); setMsg(res.message); setConfirmAction(null); setDetail(null); charger(); setTimeout(() => setMsg(''), 3000); } catch (e) { alert(e.message); } }; const agirComme = async (id) => { try { await impersoner(id); } catch (e) { alert(e.message); } }; const creerCompte = async () => { setCreateLoading(true); try { const payload = { ...createForm, nom: createForm.nom.trim() || null, date_abstinence: createForm.date_abstinence || null, }; const res = await api.post('/membres/', payload); setMsg(`Compte créé pour ${res.prenom}`); setShowCreate(false); setCreateForm({ prenom: '', nom: '', telephone: '', courriel: '', pin: '', date_abstinence: '' }); await charger(); setTimeout(() => setMsg(''), 3000); } catch (e) { alert(e.message); } setCreateLoading(false); }; const estAnonymise = (m) => Boolean(m?.anonymise || m?.courriel?.startsWith('supprime_')); const telephoneVisible = (m) => m?.telephone && m.telephone !== '000-000-0000'; const courrielVisible = (m) => m?.courriel && !m.courriel.startsWith('supprime_'); // Vue détail d'un membre if (detail) { const anonymise = estAnonymise(detail); const membreCourant = detail.id === membre?.id; const actionsAdministrativesPermises = !detail.is_sysadmin && !membreCourant; return (

{detail.prenom} {detail.nom}

{msg &&
{msg}
}

Prénom

{detail.prenom}

Nom

{detail.nom || '—'}

Téléphone

{telephoneVisible(detail) ? detail.telephone : '—'}

Courriel

{courrielVisible(detail) ? detail.courriel : '—'}

Date d'abstinence

{detail.date_abstinence || '—'}

Statut

{anonymise ? 'Anonymisé' : detail.actif ? 'Actif' : 'Inactif'}
{/* Contact rapide */}
{telephoneVisible(detail) && ( 📞 Appeler )} {courrielVisible(detail) && ( ✉️ Courriel )}
{/* Actions */} {estSysadmin && detail.id !== membre?.id && !anonymise && !confirmAction && ( )} {actionsAdministrativesPermises && detail.actif && !confirmAction && ( )} {actionsAdministrativesPermises && !detail.actif && !anonymise && !confirmAction && ( )} {actionsAdministrativesPermises && !anonymise && !confirmAction && ( )} {/* Confirmations */} {confirmAction === 'desactiver' && (

Désactiver {detail.prenom} ? Le membre ne pourra plus se connecter.

)} {confirmAction === 'reactiver' && (

Réactiver {detail.prenom} ? Le membre pourra de nouveau se connecter avec son identifiant et son PIN existants.

)} {confirmAction === 'oubli' && (

⚠️ Cette action est irréversible. Le prénom de {detail.prenom} demeurera pour préserver l'historique; le nom, le téléphone, l'identifiant, le PIN et la date d'abstinence seront effacés ou neutralisés.

)}
); } return (
{msg &&
{msg}
}

Inviter un membre

Code à usage unique, expiration automatique.

{code && (

Code d'invitation

{code}

Expire le {expiration}

)}
{showCreate && (
setCreateForm({ ...createForm, prenom: e.target.value })} className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue" /> setCreateForm({ ...createForm, nom: e.target.value })} className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue" />
setCreateForm({ ...createForm, telephone: e.target.value })} className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue" /> setCreateForm({ ...createForm, courriel: e.target.value })} className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue" />
setCreateForm({ ...createForm, pin: e.target.value.replace(/\D/g, '').slice(0, 4) })} className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue" /> setCreateForm({ ...createForm, date_abstinence: e.target.value })} className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue" />
)}
{loading ? (

Chargement...

) : ( membres.map((m) => ( )) )}
); } function Champ({ label, children }) { return ; }