/** * Compte d'accès depuis la fiche des agents (`PTA.modules.agentAccess`), * écran manage_agents.php — V7.28. * * Pose sur chaque ligne du tableau des agents un bouton qui COUPE ou RÉTABLIT * l'accès de l'agent à l'application. C'est le geste courant — un départ, un * arrêt long, un retour — là où l'écran Administration porte la distribution des * jetons elle-même. * * CE QUE LE BOUTON NE FAIT PAS : il ne touche ni au jeton (désactiver puis * réactiver rend le MÊME jeton valable), ni à la fiche de l'agent, qui reste * planifiable. Il ne crée pas non plus de compte : un agent qui n'en a pas * encore l'obtient depuis Administration, seul écran qui sache afficher un jeton * fraîchement produit. * * Il réutilise les endpoints de la délégation V7.27 (api/acces_comptes.php et * api/acces_compte_statut.php) : mêmes gardes serveur, même liste blanche de * rôles, même journalisation. Rien de neuf côté droits. * * L'état des comptes N'EST PAS rendu par PHP mais chargé par ce module : le HTML * servi ne porte ainsi aucune information sur les comptes, comme sur l'écran * DSI. */ (() => { 'use strict'; const PTA = window.PTA; if (!PTA) return; const { apiJson } = PTA.utils; const corps = () => document.querySelector('#agent-assignment-body'); /** Comptes d'accès des agents, indexés par identifiant d'agent. */ let comptesParAgent = new Map(); let chargement = false; function message(texte, type = 'info') { const boite = document.querySelector('#assignment-message'); if (!boite) return; boite.className = texte ? `message message-${type}` : 'message'; boite.textContent = texte; } /** * Met un bouton de ligne à l'état du compte correspondant. * * Trois états, et un seul est actionnable : * - compte actif → « Couper l'accès » ; * - compte coupé → « Rétablir l'accès » ; * - aucun compte → bouton inerte, qui dit où en créer un. */ function decorerLigne(ligne) { const bouton = ligne.querySelector('.agent-access-toggle'); if (!bouton) return; const agentId = Number(ligne.dataset.agentId); const compte = comptesParAgent.get(agentId); if (!compte) { bouton.disabled = true; bouton.textContent = 'Sans compte d’accès'; bouton.title = 'Cet agent n’a pas encore de jeton. Créez son compte depuis l’onglet Administration, section « Jetons d’accès ».'; delete bouton.dataset.compteId; delete bouton.dataset.actif; return; } bouton.disabled = false; bouton.dataset.compteId = String(compte.id_compte); bouton.dataset.actif = compte.actif ? '1' : '0'; bouton.textContent = compte.actif ? 'Couper l’accès' : 'Rétablir l’accès'; bouton.title = compte.actif ? 'Désactive le compte : l’agent ne pourra plus se connecter. Son jeton reste valable et resservira au rétablissement.' : 'Réactive le compte : l’agent pourra de nouveau se connecter avec le jeton qu’il détient déjà.'; bouton.classList.toggle('button-danger', compte.actif); bouton.classList.toggle('button-secondary', !compte.actif); } /** Applique l'état chargé à toutes les lignes présentes. */ function decorerToutesLesLignes() { corps()?.querySelectorAll('tr[data-agent-id]').forEach(decorerLigne); } /** * Recharge l'état des comptes agents. * * L'échec est SILENCIEUX sur le tableau : les boutons restent inertes avec * leur libellé d'attente, et la page des agents continue de fonctionner. Une * commodité ne doit pas empêcher de consulter ou de modifier une fiche. */ async function refresh() { if (!corps() || chargement) return; chargement = true; try { const donnees = await apiJson('api/acces_comptes.php?role=AGENT'); comptesParAgent = new Map( (donnees.comptes || []) .filter((compte) => compte.id_agent !== null) .map((compte) => [Number(compte.id_agent), compte]) ); decorerToutesLesLignes(); } catch (erreur) { message(`État des comptes d’accès indisponible : ${erreur.message}`, 'warning'); } finally { chargement = false; } } /** Coupe ou rétablit l'accès de l'agent d'une ligne. */ async function basculer(evenement) { const bouton = evenement.target.closest('.agent-access-toggle'); if (!bouton || bouton.disabled) return; const ligne = bouton.closest('tr[data-agent-id]'); const compteId = Number(bouton.dataset.compteId); const actif = bouton.dataset.actif === '1'; const titulaire = ligne?.querySelector('.agent-row-name')?.textContent?.trim() || 'cet agent'; if (actif && !window.confirm(`Couper l’accès de ${titulaire} ? Il ne pourra plus se connecter, et sa session en cours se refermera à sa prochaine action. Son jeton reste valable pour un rétablissement.`)) { return; } bouton.disabled = true; try { const donnees = await apiJson('api/acces_compte_statut.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ csrf_token: window.PTA_CONFIG.csrfToken, compte_id: compteId, action: actif ? 'DESACTIVER' : 'ACTIVER', }), }); message(donnees.message, 'success'); await refresh(); } catch (erreur) { message(erreur.message, 'error'); bouton.disabled = false; } } function init() { // Le module ne sert que sur l'écran des agents : ailleurs, il se retire. if (!corps()) return; corps().addEventListener('click', basculer); refresh(); } PTA.modules.agentAccess = { init, refresh }; })();