This commit is contained in:
PTA
2026-08-25 15:12:11 +02:00
parent 44730eefca
commit 1a67080268
25 changed files with 2646 additions and 231 deletions

View File

@@ -1,7 +1,8 @@
<?php
/**
* Administration : horaires de couverture attendus des lieux.
* Module JS : `coverage`.
* Administration : horaires de couverture attendus des lieux, et jetons d'accès
* des agents et des responsables de lieu.
* Modules JS : `coverage` et `accessTokens`.
*
* Partiel de contenu inclus par la vue de page homonyme. Les identifiants HTML
* posés ici sont les points d'ancrage du module JS : les renommer casse le
@@ -11,6 +12,13 @@
* page « Management ». Ne restent ici que les règles de couverture, qui ne
* décrivent ni une personne ni un lieu mais une EXIGENCE DE PRÉSENCE — le
* paramètre que contrôle l'onglet « Couverture ».
*
* V7.27 : s'y ajoute la distribution des JETONS DE TERRAIN. Le Service Enfance
* équipe ses agents et ses responsables de lieu sans passer par la DSI, mais
* RIEN AU-DELÀ : les comptes Service Enfance et DSI n'apparaissent pas ici et
* sont refusés par le serveur (AccessAccountController). Les classes `dsi-*`
* sont réutilisées telles quelles — elles ne portent qu'une mise en forme, et
* les deux écrans montrent la même chose : des comptes et des jetons.
*/
?>
<section id="assignment-view" class="app-view page-content">
@@ -43,4 +51,113 @@
<button id="save-coverage-rules" class="button button-primary" type="button" disabled>Enregistrer les horaires de couverture</button>
</div>
</section>
<!--
Jetons d'accès de terrain (V7.27).
Panneau des jetons fraîchement produits : c'est la SEULE occasion de
les lire, la base n'en conserve qu'une empreinte. Il reste ouvert
tant qu'il n'a pas été explicitement refermé, pour laisser le temps
de les recopier ou de les imprimer.
-->
<section id="access-token-panel" class="card dsi-token-panel" hidden>
<div class="section-heading">
<div>
<h2>Jetons à transmettre</h2>
<p class="section-subtitle">Ces jetons ne seront plus jamais affichés : la base n’en garde qu’une empreinte. Copiez-les, remettez-les à leurs titulaires, puis refermez ce panneau.</p>
</div>
<div class="button-group">
<button id="access-token-copy" class="button button-secondary" type="button">Tout copier</button>
<button id="access-token-close" class="button button-secondary" type="button">Fermer</button>
</div>
</div>
<div id="access-token-list" class="dsi-token-list"></div>
<div id="access-token-message" class="message" role="status" aria-live="polite"></div>
</section>
<section class="card">
<div class="section-heading">
<div>
<h2>Jetons d’accès des agents et des responsables</h2>
<p class="section-subtitle">Un compte par agent et par lieu d’affectation. Chacun se connecte avec son jeton : il n’y a pas de mot de passe pour ces deux rôles. Les comptes Service Enfance et DSI ne se gèrent pas ici — ils relèvent de la DSI.</p>
</div>
<button id="access-generate-missing" class="button button-secondary" type="button">
Générer les jetons manquants <span id="access-missing-count" class="nav-count-badge" hidden>0</span>
</button>
</div>
<form id="access-account-form" class="admin-form">
<div class="admin-form-grid">
<label class="field">
<span>Type de compte</span>
<select id="access-account-role" required>
<option value="AGENT">Agent</option>
<option value="RESPONSABLE_STRUCTURE">Responsable de structure</option>
</select>
</label>
<label class="field" id="access-account-agent-field">
<span>Agent titulaire</span>
<select id="access-account-agent"><option value="">Choisir un agent sans compte</option></select>
</label>
<label class="field" id="access-account-structure-field" hidden>
<span>Lieu titulaire</span>
<select id="access-account-structure"><option value="">Choisir un lieu sans compte</option></select>
</label>
<label class="field admin-field-wide">
<span>Commentaire (facultatif)</span>
<input id="access-account-comment" type="text" maxlength="255" placeholder="Ex. remplacement congé maternité, jusqu’en septembre">
</label>
</div>
<p id="access-account-hint" class="hint"></p>
<div class="admin-form-actions">
<div id="access-account-message" class="message" role="status" aria-live="polite"></div>
<button class="button button-primary" type="submit">Créer le compte et générer son jeton</button>
</div>
</form>
<div class="selection-grid overview-filters">
<label class="field">
<span>Type</span>
<select id="access-filter-role">
<option value="">Agents et responsables</option>
<option value="AGENT">Agents</option>
<option value="RESPONSABLE_STRUCTURE">Responsables de structure</option>
</select>
</label>
<label class="field">
<span>État</span>
<select id="access-filter-state">
<option value="">Tous</option>
<option value="1">Actifs</option>
<option value="0">Désactivés</option>
</select>
</label>
<label class="field">
<span>Rechercher</span>
<input id="access-filter-search" type="search" maxlength="80" placeholder="Nom, matricule ou début de jeton">
</label>
<div class="overview-filter-actions">
<button id="access-accounts-refresh" class="button button-secondary filter-button" type="button">Actualiser</button>
</div>
</div>
<div id="access-accounts-message" class="message" role="status" aria-live="polite"></div>
<div class="table-scroll">
<table class="planning-table dsi-accounts-table">
<thead>
<tr>
<th>Titulaire</th>
<th>Type</th>
<th>Jeton</th>
<th>Dernière connexion</th>
<th>État</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="access-accounts-body">
<tr><td colspan="6">Chargement des comptes…</td></tr>
</tbody>
</table>
</div>
</section>
</section>

View File

@@ -155,6 +155,8 @@ $sommaire = [
<li><strong>Adresse personnelle</strong> : facultative et purement informative. Dès trois caractères saisis, une liste d’adresses officielles est proposée sous le champ (source : Base Adresse Nationale) — cliquez sur la bonne, ou continuez à écrire librement si l’adresse n’y figure pas.</li>
<li><strong>Observations utiles à la construction du PTA</strong> : disponibilités particulières, organisation connue… Ces notes se retrouvent sur l’écran « PTA détaillé ».</li>
<li>Cliquez sur <strong>Ajouter l’agent</strong>.</li>
<li>Pour <strong>couper l’accès</strong> d’un agent (départ, arrêt long) sans supprimer sa fiche : bouton <strong>Couper l’accès</strong> sur sa ligne, à côté de Modifier. Son jeton reste valable et resservira tel quel au rétablissement. L’agent <strong>disparaît alors des listes d’affectation</strong> — saisie des plannings et composition des équipes — mais reste consultable, et ses créneaux déjà saisis sont conservés.</li>
<li>Enfin, donnez-lui son <strong>jeton d’accès</strong> : onglet <strong>Administration</strong>, encadré « Jetons d’accès des agents et des responsables ». Le jeton n’est affiché <em>qu’une seule fois</em> — recopiez-le avant de refermer le panneau. Perdu, il ne se retrouve pas : il se régénère depuis le même écran, et l’ancien cesse alors de fonctionner. Les comptes Service Enfance et DSI, eux, restent gérés par la DSI.</li>
</ol>
<p class="hint"><strong>Dates de contrat :</strong> elles bornent la planification. Aucune affectation — pas même un congé — ne peut être posée avant la date de début ou après la date de fin. Un contrat sans date de fin est considéré comme à durée indéterminée. Raccourcir un contrat est refusé tant qu’il reste des affectations au-delà : supprimez-les d’abord.</p>
<p class="hint">Pour corriger une fiche existante, utilisez le tableau « Informations des agents » du même onglet : le bouton <strong>Modifier</strong> ouvre la fiche complète, nom, prénom et lieu principal compris. Seuls le <strong>matricule</strong> et la <strong>quotité de travail</strong> restent hors d’atteinte : le premier sert de clé avec les outils RH, la seconde détermine le quota déjà consommé de l’année.</p>

View File

@@ -20,6 +20,11 @@
* champ + `[data-address-suggestions]` + `[data-address-status]` — mais aucun
* identifiant n'est connu du module.
*
* V7.28 : chaque ligne d'agent porte, à côté de « Modifier », un bouton
* d'activation de son COMPTE D'ACCÈS (module `agentAccess`). Son libellé et son
* état sont posés par le JS après appel de l'API — le HTML servi ne dit rien des
* comptes, comme sur l'écran DSI.
*
* Même principe pour l'e-mail et le téléphone : `data-format="email|phone"` sur
* le champ et un `[data-format-status]` frère suffisent au module `fieldFormat`
* à contrôler la saisie. Ce contrôle ne fait que PRÉVENIR : c'est
@@ -140,7 +145,7 @@
<div class="section-heading">
<div>
<h2>Informations des agents</h2>
<p class="section-subtitle">Consultez la qualification, les coordonnées et le lieu principal de chaque agent. Le bouton Modifier ouvre la fiche complète.</p>
<p class="section-subtitle">Consultez la qualification, les coordonnées et le lieu principal de chaque agent. Le bouton Modifier ouvre la fiche complète ; le second bouton coupe ou rétablit l’accès de l’agent à l’application, sans toucher à son jeton.</p>
</div>
</div>
<div id="assignment-message" class="message" role="status" aria-live="polite"></div>
@@ -188,7 +193,15 @@
<td class="agent-row-phone"><?= htmlspecialchars((string) (($agent['telephone'] ?? '') ?: 'Non renseigné')) ?></td>
<td class="agent-row-contract-start"><?= htmlspecialchars((string) (($agent['date_debut_contrat'] ?? '') ?: 'Non renseignée')) ?></td>
<td class="agent-row-structure"><?= htmlspecialchars((string) (($agent['structure_nom'] ?? '') ?: 'Sans lieu principal')) ?></td>
<td><button type="button" class="button button-secondary edit-agent-profile">Modifier</button></td>
<td class="agent-row-actions">
<button type="button" class="button button-secondary edit-agent-profile">Modifier</button>
<!--
État du compte d'accès rempli par le module `agentAccess`
après appel de l'API : le HTML servi ne porte aucune
information sur les comptes, comme sur l'écran DSI.
-->
<button type="button" class="button button-secondary agent-access-toggle" disabled>Compte d’accès…</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>