Files
pta/app/Views/layouts/header.php
PTA 3cdbd43c13 Guide d'utilisation accessible depuis toute la navigation
Les écrans expliquaient chacun leur propre action, mais rien ne racontait
l'enchaînement : un nouvel utilisateur ne pouvait pas deviner qu'un lieu
doit exister avant un agent, ni qu'un planning se saisit en brouillon
avant d'être validé. La page « faq » déroule ce parcours complet, du
paramétrage des lieux au suivi annuel, et répond aux questions qui
reviennent (chevauchements, quota dépassé, planning validé à corriger).

Son bouton d'accès est ancré à droite de la barre de navigation plutôt
que rangé dans un groupe d'intention : le guide n'est pas une étape du
travail, c'est un secours permanent. Il est donc volontairement absent de
$navigation — c'est aussi ce qui l'empêche d'être repêché par le filet
« Autres » et d'apparaître deux fois. La barre défilant horizontalement
quand les onglets débordent, le bloc est en position sticky pour rester
atteignable.

La page reste soumise à la règle V7.8 : le droit vient de
acces_role_page, ouvert aux trois rôles. Sans la migration, ni bouton ni
page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 16:16:45 +02:00

133 lines
5.9 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/** @var string $pageTitle */
/** @var string $pageSubtitle */
/** @var string $activePage */
/** @var array $allowedPages */
/** @var array $accessProfile */
/** @var string $csrfToken */
$isAgent = ($accessProfile['role'] ?? '') === 'AGENT';
$navigation = [
'dashboard' => ['dashboard.php', 'Tableau de bord'],
'planning' => ['planning.php', 'Saisie'],
'pending' => ['pending.php', 'À valider'],
'coverage' => ['coverage.php', 'Couverture'],
'structures' => ['structures.php', 'Par lieu'],
'agents' => ['agents.php', $isAgent ? 'Mon planning' : 'Par agent'],
'annual' => ['annual.php', 'Vue annuelle'],
'pta' => ['pta.php', 'PTA détaillé'],
'teams' => ['teams.php', 'Équipes'],
'vacations' => ['vacations.php', 'Vacances'],
'administration' => ['administration.php', 'Administration'],
];
/**
* Les onze onglets du Service Enfance étaient alignés à plat, sans hiérarchie :
* rien ne distinguait une tâche quotidienne d'un référentiel modifié deux fois
* par an. Ils sont désormais regroupés par intention. Les rôles qui n'ont que
* quelques pages gardent une barre simple, sans titres de groupe.
*/
$navigationGroups = [
'Piloter' => ['dashboard', 'pending', 'coverage'],
'Planifier' => ['planning', 'teams'],
'Consulter' => ['agents', 'structures', 'annual', 'pta'],
'Paramétrer' => ['vacations', 'administration'],
];
$visibleGroups = [];
$grouped = [];
foreach ($navigationGroups as $groupLabel => $keys) {
$visibleKeys = array_values(array_filter(
$keys,
static fn (string $key): bool => in_array($key, $allowedPages, true) && isset($navigation[$key])
));
if ($visibleKeys !== []) {
$visibleGroups[$groupLabel] = $visibleKeys;
$grouped = array_merge($grouped, $visibleKeys);
}
}
// Filet de sécurité : une page autorisée en base mais oubliée dans les groupes
// ci-dessus reste accessible plutôt que de disparaître de la navigation.
$ungrouped = array_values(array_filter(
$allowedPages,
static fn (string $key): bool => isset($navigation[$key]) && !in_array($key, $grouped, true)
));
if ($ungrouped !== []) {
$visibleGroups['Autres'] = $ungrouped;
}
$visiblePageCount = count($grouped) + count($ungrouped);
$showGroupLabels = $visiblePageCount > 4;
/**
* Le guide n'appartient à aucun groupe d'intention : ce n'est pas une étape du
* travail mais un secours permanent. Il est volontairement absent de
* $navigation — il ne doit apparaître qu'une seule fois, ancré à droite de la
* barre, et jamais repêché par le filet « Autres ».
*/
$showHelpTab = in_array('faq', $allowedPages, true);
?>
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?= htmlspecialchars($pageTitle) ?> — PTA</title>
<link rel="stylesheet" href="assets/style.css?v=7.14">
</head>
<body>
<main class="app-shell">
<header class="page-header">
<div class="page-header-identity">
<p class="eyebrow">PTA</p>
<h1><?= htmlspecialchars($pageTitle) ?></h1>
<p class="subtitle"><?= htmlspecialchars($pageSubtitle ?? '') ?></p>
</div>
<div class="header-actions">
<?php if ($activePage === 'planning'): ?>
<div id="planning-status" class="status-badge status-neutral">Nouveau planning</div>
<?php endif; ?>
<div class="access-profile-badge">
<span><?= htmlspecialchars((string) ($accessProfile['role_label'] ?? '')) ?></span>
<strong><?= htmlspecialchars((string) ($accessProfile['label'] ?? '')) ?></strong>
<?php if (!empty($accessProfile['structure_name']) && $isAgent): ?>
<small><?= htmlspecialchars((string) $accessProfile['structure_name']) ?></small>
<?php endif; ?>
</div>
<a class="button button-ghost switch-role-link" href="role.php?action=reset&amp;csrf_token=<?= htmlspecialchars(urlencode($csrfToken), ENT_QUOTES) ?>">Changer de rôle</a>
</div>
</header>
<?php if (!empty($_GET['access_denied'])): ?>
<div class="message message-warning role-access-warning">Cette page n’est pas disponible avec votre rôle actuel.</div>
<?php endif; ?>
<nav class="view-tabs<?= $showGroupLabels ? ' view-tabs-grouped' : '' ?>" aria-label="Navigation principale">
<?php foreach ($visibleGroups as $groupLabel => $keys): ?>
<div class="view-tab-group" role="group"<?= $showGroupLabels ? ' aria-label="' . htmlspecialchars($groupLabel, ENT_QUOTES) . '"' : '' ?>>
<?php if ($showGroupLabels): ?>
<span class="view-tab-group-label"><?= htmlspecialchars($groupLabel) ?></span>
<?php endif; ?>
<div class="view-tab-group-items">
<?php foreach ($keys as $key): ?>
<?php [$href, $label] = $navigation[$key]; ?>
<a class="view-tab<?= $activePage === $key ? ' is-active' : '' ?>" href="<?= htmlspecialchars($href) ?>"<?= $activePage === $key ? ' aria-current="page"' : '' ?>>
<?= htmlspecialchars($label) ?>
<?php if ($key === 'pending'): ?><span id="pending-validation-tab-badge" class="nav-count-badge" hidden>0</span><?php endif; ?>
</a>
<?php endforeach; ?>
</div>
</div>
<?php endforeach; ?>
<?php if ($showHelpTab): ?>
<div class="view-tab-help">
<a class="view-tab view-tab-faq<?= $activePage === 'faq' ? ' is-active' : '' ?>" href="faq.php"<?= $activePage === 'faq' ? ' aria-current="page"' : '' ?>>
<span class="view-tab-faq-mark" aria-hidden="true">?</span>
FAQ
</a>
</div>
<?php endif; ?>
</nav>