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 (
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'}Désactiver {detail.prenom} ? Le membre ne pourra plus se connecter.
Réactiver {detail.prenom} ? Le membre pourra de nouveau se connecter avec son identifiant et son PIN existants.
⚠️ 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.
Code à usage unique, expiration automatique.
Code d'invitation
{code}
Expire le {expiration}
Chargement...
) : ( membres.map((m) => ( )) )}