pour prod
This commit is contained in:
356
app/Views/partials/administration.php
Normal file
356
app/Views/partials/administration.php
Normal file
@@ -0,0 +1,356 @@
|
||||
<section id="assignment-view" class="app-view page-content">
|
||||
<div class="admin-grid">
|
||||
<section class="card admin-card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Ajouter un lieu d’affectation</h2>
|
||||
<p class="section-subtitle">Chaque lieu possède son propre type : périscolaire ou extrascolaire.</p>
|
||||
</div>
|
||||
</div>
|
||||
<form id="create-structure-form" class="admin-form">
|
||||
<div class="admin-form-grid">
|
||||
<label class="field">
|
||||
<span>Code <strong>*</strong></span>
|
||||
<input id="new-structure-code" name="code" type="text" maxlength="50" placeholder="Ex. CRECHE_MATUSALEME" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Nom <strong>*</strong></span>
|
||||
<input id="new-structure-name" name="nom" type="text" maxlength="150" placeholder="Ex. Crèche Matusalème" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Type d’affectation <strong>*</strong></span>
|
||||
<select id="new-structure-type" name="type_affectation" required>
|
||||
<option value="PERISCOLAIRE">Périscolaire</option>
|
||||
<option value="EXTRASCOLAIRE">Extrascolaire</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field admin-field-wide">
|
||||
<span>Adresse</span>
|
||||
<input id="new-structure-address" name="adresse" type="text" maxlength="255" placeholder="Adresse du lieu">
|
||||
</label>
|
||||
</div>
|
||||
<div class="admin-form-actions">
|
||||
<div id="create-structure-message" class="message" role="status" aria-live="polite"></div>
|
||||
<button class="button button-primary" type="submit">Ajouter le lieu</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="card admin-card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Ajouter un agent</h2>
|
||||
<p class="section-subtitle">L’agent reçoit un lieu principal à sa création, mais peut être intégré aussi bien aux équipes périscolaires qu’extrascolaires et travailler ponctuellement sur d’autres lieux.</p>
|
||||
</div>
|
||||
</div>
|
||||
<form id="create-agent-form" class="admin-form">
|
||||
<div class="admin-form-grid">
|
||||
<label class="field">
|
||||
<span>Matricule <strong>*</strong></span>
|
||||
<input id="new-agent-matricule" name="matricule" type="text" maxlength="50" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Poste PTA <strong>*</strong></span>
|
||||
<select id="new-agent-post" name="id_poste" required>
|
||||
<option value="">Choisir un poste</option>
|
||||
<?php foreach ($posts as $post): ?>
|
||||
<option value="<?= (int) $post['id_poste'] ?>"><?= htmlspecialchars($post['libelle']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Type de contrat <strong>*</strong></span>
|
||||
<select id="new-agent-contract-type" required>
|
||||
<option value="PERMANENT">Permanent — soumis au PTA</option>
|
||||
<option value="TEMPORAIRE">Temporaire — hors périmètre PTA</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Lieu d’affectation principal <strong>*</strong></span>
|
||||
<select id="new-agent-structure" name="structure_id" required>
|
||||
<option value="">Choisir un lieu d’affectation</option>
|
||||
<?php foreach ($structures as $structure): ?>
|
||||
<option value="<?= (int) $structure['id_structure'] ?>">
|
||||
<?= htmlspecialchars($structure['nom']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Nom <strong>*</strong></span>
|
||||
<input id="new-agent-name" name="nom" type="text" maxlength="100" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Prénom <strong>*</strong></span>
|
||||
<input id="new-agent-firstname" name="prenom" type="text" maxlength="100" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>E-mail</span>
|
||||
<input id="new-agent-email" name="email" type="email" maxlength="255" placeholder="prenom.nom@exemple.fr">
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Téléphone</span>
|
||||
<input id="new-agent-phone" name="telephone" type="tel" maxlength="30" placeholder="Ex. 06 12 34 56 78">
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Qualification</span>
|
||||
<select id="new-agent-qualified" name="est_diplome">
|
||||
<option value="0">Non diplômé</option>
|
||||
<option value="1">Diplômé</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Diplôme</span>
|
||||
<input id="new-agent-diploma" name="diplome_libelle" type="text" maxlength="150" placeholder="Ex. BAFA, CAP AEPE…" disabled>
|
||||
</label>
|
||||
<label class="field admin-field-wide">
|
||||
<span>Adresse personnelle</span>
|
||||
<textarea id="new-agent-address" name="adresse" maxlength="255" rows="2" placeholder="Adresse de l’agent"></textarea>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Quotité de travail <strong>*</strong></span>
|
||||
<div class="input-suffix">
|
||||
<input id="new-agent-rate" name="quotite_travail" type="number" min="1" max="100" step="0.01" value="100" required>
|
||||
<span>%</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Date de début du contrat <strong>*</strong></span>
|
||||
<input id="new-agent-contract-start" name="date_debut_contrat" type="date" value="<?= date('Y-m-d') ?>" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Date de fin du contrat</span>
|
||||
<input id="new-agent-contract-end" name="date_fin_contrat" type="date">
|
||||
</label>
|
||||
<label class="check-field admin-field-wide">
|
||||
<input id="new-agent-training-planned" type="checkbox">
|
||||
<span>Une formation est déjà prévue dans la répartition annuelle : ne pas ajouter l’enveloppe complémentaire de 14 h</span>
|
||||
</label>
|
||||
<label class="field admin-field-wide">
|
||||
<span>Observations utiles à la construction du PTA</span>
|
||||
<textarea id="new-agent-pta-comment" maxlength="1000" rows="3" placeholder="Disponibilités particulières, organisation connue…"></textarea>
|
||||
</label>
|
||||
</div>
|
||||
<p class="hint">Le quota PTA est suivi sur l’année civile, du 1er janvier au 31 décembre. À 100 %, la référence est de 1 607 h. La date de début du contrat reste une information RH mais ne décale pas l’année de référence.</p>
|
||||
<div class="admin-form-actions">
|
||||
<div id="create-agent-message" class="message" role="status" aria-live="polite"></div>
|
||||
<button class="button button-primary" type="submit">Ajouter l’agent</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Paramètres des lieux d’affectation</h2>
|
||||
<p class="section-subtitle">Le type d’affectation est défini au niveau du lieu : par exemple « Crèche Matusalème — Périscolaire ».</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="structure-settings-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div class="table-scroll">
|
||||
<table class="planning-table assignment-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Lieu</th>
|
||||
<th>Code</th>
|
||||
<th>Type d’affectation</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="structure-settings-body">
|
||||
<?php foreach ($structures as $structure): ?>
|
||||
<tr data-structure-id="<?= (int) $structure['id_structure'] ?>">
|
||||
<td><strong><?= htmlspecialchars($structure['nom']) ?></strong></td>
|
||||
<td><?= htmlspecialchars($structure['code']) ?></td>
|
||||
<td>
|
||||
<select class="structure-type-select" aria-label="Type d’affectation de <?= htmlspecialchars($structure['nom']) ?>">
|
||||
<option value="PERISCOLAIRE" <?= ($structure['type_affectation'] ?? 'PERISCOLAIRE') === 'PERISCOLAIRE' ? 'selected' : '' ?>>Périscolaire</option>
|
||||
<option value="EXTRASCOLAIRE" <?= ($structure['type_affectation'] ?? '') === 'EXTRASCOLAIRE' ? 'selected' : '' ?>>Extrascolaire</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><button type="button" class="button button-secondary save-structure-type">Enregistrer</button></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card coverage-settings-card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Horaires de couverture des lieux</h2>
|
||||
<p class="section-subtitle">Définissez les périodes pendant lesquelles un nombre minimum d’agents doit être physiquement présent. Seules les affectations « Heure de travail » comptent comme présence.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="selection-grid overview-filters">
|
||||
<label class="field">
|
||||
<span>Lieu d’affectation</span>
|
||||
<select id="coverage-rules-structure">
|
||||
<option value="">Choisir un lieu d’affectation</option>
|
||||
<?php foreach ($structures as $structure): ?>
|
||||
<option value="<?= (int) $structure['id_structure'] ?>"><?= htmlspecialchars($structure['nom']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<div class="overview-filter-actions">
|
||||
<button id="load-coverage-rules" class="button button-secondary filter-button" type="button">Charger</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="coverage-rules-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div id="coverage-rules-editor" class="coverage-rules-editor">
|
||||
<div class="empty-state">Choisissez un lieu pour configurer les plages où une présence minimale est obligatoire.</div>
|
||||
</div>
|
||||
<div class="coverage-rules-actions">
|
||||
<button id="save-coverage-rules" class="button button-primary" type="button" disabled>Enregistrer les horaires de couverture</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div id="assignment-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div class="table-scroll">
|
||||
<table class="planning-table assignment-table agent-information-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Agent</th>
|
||||
<th>Matricule</th>
|
||||
<th>Poste</th>
|
||||
<th>Qualification</th>
|
||||
<th>Téléphone</th>
|
||||
<th>Début contrat</th>
|
||||
<th>Lieu principal</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="agent-assignment-body">
|
||||
<?php foreach ($agents as $agent): ?>
|
||||
<tr
|
||||
data-agent-id="<?= (int) $agent['id_agent'] ?>"
|
||||
data-email="<?= htmlspecialchars((string) ($agent['email'] ?? ''), ENT_QUOTES) ?>"
|
||||
data-telephone="<?= htmlspecialchars((string) ($agent['telephone'] ?? ''), ENT_QUOTES) ?>"
|
||||
data-adresse="<?= htmlspecialchars((string) ($agent['adresse'] ?? ''), ENT_QUOTES) ?>"
|
||||
data-est-diplome="<?= !empty($agent['est_diplome']) ? '1' : '0' ?>"
|
||||
data-diplome-libelle="<?= htmlspecialchars((string) ($agent['diplome_libelle'] ?? ''), ENT_QUOTES) ?>"
|
||||
data-date-debut-contrat="<?= htmlspecialchars((string) ($agent['date_debut_contrat'] ?? ''), ENT_QUOTES) ?>"
|
||||
data-date-fin-contrat="<?= htmlspecialchars((string) ($agent['date_fin_contrat'] ?? ''), ENT_QUOTES) ?>"
|
||||
data-id-poste="<?= (int) ($agent['id_poste'] ?? 0) ?>"
|
||||
data-type-contrat="<?= htmlspecialchars((string) ($agent['type_contrat'] ?? 'PERMANENT'), ENT_QUOTES) ?>"
|
||||
data-formation-repartition-annuelle="<?= !empty($agent['formation_repartition_annuelle']) ? '1' : '0' ?>"
|
||||
data-commentaire-pta="<?= htmlspecialchars((string) ($agent['commentaire_pta'] ?? ''), ENT_QUOTES) ?>"
|
||||
data-structure-id="<?= (int) ($agent['id_structure'] ?? 0) ?>"
|
||||
>
|
||||
<td><strong class="agent-row-name"><?= htmlspecialchars($agent['prenom'] . ' ' . $agent['nom']) ?></strong></td>
|
||||
<td><?= htmlspecialchars($agent['matricule']) ?></td>
|
||||
<td class="agent-row-post"><?= htmlspecialchars((string) (($agent['poste_libelle'] ?? '') ?: 'Non renseigné')) ?></td>
|
||||
<td class="agent-row-qualification">
|
||||
<?= !empty($agent['est_diplome'])
|
||||
? 'Diplômé' . (!empty($agent['diplome_libelle']) ? ' — ' . htmlspecialchars($agent['diplome_libelle']) : '')
|
||||
: 'Non diplômé' ?>
|
||||
</td>
|
||||
<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>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<div id="agent-profile-modal" class="modal-backdrop" hidden>
|
||||
<section class="modal-card" role="dialog" aria-modal="true" aria-labelledby="agent-profile-modal-title">
|
||||
<div class="section-heading modal-heading">
|
||||
<div>
|
||||
<h2 id="agent-profile-modal-title">Modifier les informations de l’agent</h2>
|
||||
<p id="agent-profile-modal-subtitle" class="section-subtitle"></p>
|
||||
</div>
|
||||
<button id="close-agent-profile-modal" type="button" class="button button-ghost modal-close" aria-label="Fermer">×</button>
|
||||
</div>
|
||||
<form id="agent-profile-form" class="admin-form">
|
||||
<input id="edit-agent-profile-id" type="hidden">
|
||||
<div class="admin-form-grid">
|
||||
<label class="field">
|
||||
<span>Poste PTA <strong>*</strong></span>
|
||||
<select id="edit-agent-profile-post" required>
|
||||
<option value="">Choisir un poste</option>
|
||||
<?php foreach ($posts as $post): ?>
|
||||
<option value="<?= (int) $post['id_poste'] ?>"><?= htmlspecialchars($post['libelle']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Type de contrat <strong>*</strong></span>
|
||||
<select id="edit-agent-profile-contract-type" required>
|
||||
<option value="PERMANENT">Permanent</option>
|
||||
<option value="TEMPORAIRE">Temporaire</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>E-mail</span>
|
||||
<input id="edit-agent-profile-email" type="email" maxlength="255">
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Téléphone</span>
|
||||
<input id="edit-agent-profile-phone" type="tel" maxlength="30" placeholder="Ex. 06 12 34 56 78">
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Qualification</span>
|
||||
<select id="edit-agent-profile-qualified">
|
||||
<option value="0">Non diplômé</option>
|
||||
<option value="1">Diplômé</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Diplôme</span>
|
||||
<input id="edit-agent-profile-diploma" type="text" maxlength="150" placeholder="Ex. BAFA, CAP AEPE…">
|
||||
</label>
|
||||
<label class="field admin-field-wide">
|
||||
<span>Adresse personnelle</span>
|
||||
<textarea id="edit-agent-profile-address" maxlength="255" rows="3"></textarea>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Date de début du contrat <strong>*</strong></span>
|
||||
<input id="edit-agent-profile-contract-start" type="date" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Date de fin du contrat</span>
|
||||
<input id="edit-agent-profile-contract-end" type="date">
|
||||
</label>
|
||||
<label class="check-field admin-field-wide">
|
||||
<input id="edit-agent-profile-training-planned" type="checkbox">
|
||||
<span>Formation déjà intégrée dans la répartition annuelle</span>
|
||||
</label>
|
||||
<label class="field admin-field-wide">
|
||||
<span>Observations PTA</span>
|
||||
<textarea id="edit-agent-profile-pta-comment" maxlength="1000" rows="3"></textarea>
|
||||
</label>
|
||||
<label class="field admin-field-wide">
|
||||
<span>Lieu d’affectation principal</span>
|
||||
<select id="edit-agent-profile-structure">
|
||||
<option value="">Sans lieu principal</option>
|
||||
<?php foreach ($structures as $structure): ?>
|
||||
<option value="<?= (int) $structure['id_structure'] ?>">
|
||||
<?= htmlspecialchars($structure['nom']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div id="agent-profile-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div class="admin-form-actions modal-actions">
|
||||
<button id="cancel-agent-profile" type="button" class="button button-secondary">Annuler</button>
|
||||
<button type="submit" class="button button-primary">Enregistrer les informations</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
136
app/Views/partials/agent_overview.php
Normal file
136
app/Views/partials/agent_overview.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<section id="agent-view" class="app-view page-content">
|
||||
<section class="card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2><?= ($accessProfile['role'] ?? '') === 'AGENT' ? 'Mon planning' : 'Vue individuelle d’un agent' ?></h2>
|
||||
<p class="section-subtitle"><?= ($accessProfile['role'] ?? '') === 'AGENT'
|
||||
? 'Consultation de votre planning mensuel et suivi de votre quota.'
|
||||
: (!empty($permissions['can_copy_full_week'])
|
||||
? 'Planning mensuel, modification directe des créneaux, duplication de semaines et suivi du quota annuel.'
|
||||
: 'Planning mensuel des agents du lieu, modification des créneaux du lieu et suivi du quota annuel.') ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="selection-grid overview-filters">
|
||||
<label class="field">
|
||||
<span>Agent</span>
|
||||
<select id="overview-agent">
|
||||
<option value="">Choisir un agent</option>
|
||||
<?php foreach ($agents as $agent): ?>
|
||||
<option value="<?= (int) $agent['id_agent'] ?>">
|
||||
<?= htmlspecialchars($agent['prenom'] . ' ' . $agent['nom'] . ' (' . $agent['matricule'] . ')') ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Mois</span>
|
||||
<input id="agent-overview-month" type="month" value="<?= htmlspecialchars((new DateTimeImmutable())->format('Y-m')) ?>">
|
||||
</label>
|
||||
<button id="load-agent-overview" class="button button-primary filter-button" type="button">Afficher le mois</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card overview-card">
|
||||
<div id="agent-overview-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div id="agent-overview-empty" class="empty-state">Choisissez un agent et un mois.</div>
|
||||
<div id="agent-overview-content" hidden></div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<?php if (!empty($permissions['can_edit_draft'])): ?>
|
||||
<div id="agent-entry-modal" class="modal-backdrop" hidden>
|
||||
<section class="modal-card" role="dialog" aria-modal="true" aria-labelledby="agent-entry-modal-title">
|
||||
<div class="section-heading modal-heading">
|
||||
<div>
|
||||
<h2 id="agent-entry-modal-title">Modifier un créneau</h2>
|
||||
<p class="section-subtitle">Modifiez directement le jour, le lieu, le motif ou les horaires. Un déplacement vers une autre semaine est autorisé.</p>
|
||||
</div>
|
||||
<button id="close-agent-entry-modal" type="button" class="button button-ghost modal-close" aria-label="Fermer">×</button>
|
||||
</div>
|
||||
|
||||
<form id="agent-entry-edit-form" class="admin-form">
|
||||
<input id="edit-agent-entry-id" type="hidden">
|
||||
<div class="admin-form-grid">
|
||||
<label class="field">
|
||||
<span>Jour</span>
|
||||
<input id="edit-agent-entry-date" type="date" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Lieu d’affectation</span>
|
||||
<select id="edit-agent-entry-structure" required>
|
||||
<?php foreach ($structures as $structure): ?>
|
||||
<option value="<?= (int) $structure['id_structure'] ?>"><?= htmlspecialchars($structure['nom']) ?> — <?= ($structure['type_affectation'] ?? 'PERISCOLAIRE') === 'EXTRASCOLAIRE' ? 'Extrascolaire' : 'Périscolaire' ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Motif</span>
|
||||
<select id="edit-agent-entry-motif" required>
|
||||
<?php foreach ($motifs as $motif): ?>
|
||||
<option value="<?= (int) $motif['id_motif'] ?>"><?= htmlspecialchars($motif['libelle']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<div class="field edit-time-range-field">
|
||||
<span>Horaires</span>
|
||||
<div class="edit-time-range">
|
||||
<input id="edit-agent-entry-start" type="time" step="900" required aria-label="Heure de début">
|
||||
<span>→</span>
|
||||
<input id="edit-agent-entry-end" type="time" step="900" required aria-label="Heure de fin">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="hint">Toute modification d’un planning validé le repasse automatiquement en brouillon afin qu’il soit contrôlé et validé à nouveau.</p>
|
||||
<div id="agent-entry-edit-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div class="admin-form-actions modal-actions agent-entry-modal-actions">
|
||||
<button id="delete-agent-entry-edit" type="button" class="button button-danger">Supprimer le créneau</button>
|
||||
<span class="modal-action-spacer" aria-hidden="true"></span>
|
||||
<button id="cancel-agent-entry-edit" type="button" class="button button-secondary">Annuler</button>
|
||||
<button id="save-agent-entry-edit" type="submit" class="button button-primary">Enregistrer la modification</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($permissions['can_copy_full_week'])): ?>
|
||||
<div id="agent-week-copy-modal" class="modal-backdrop" hidden>
|
||||
<section class="modal-card planning-entry-action-card" role="dialog" aria-modal="true" aria-labelledby="agent-week-copy-title">
|
||||
<div class="section-heading modal-heading">
|
||||
<div>
|
||||
<h2 id="agent-week-copy-title">Dupliquer une semaine</h2>
|
||||
<p id="agent-week-copy-summary" class="section-subtitle"></p>
|
||||
</div>
|
||||
<button id="close-agent-week-copy-modal" type="button" class="button button-ghost modal-close" aria-label="Fermer">×</button>
|
||||
</div>
|
||||
|
||||
<form id="agent-week-copy-form" class="admin-form">
|
||||
<input id="agent-week-copy-source" type="hidden">
|
||||
<label class="field">
|
||||
<span>Semaine cible</span>
|
||||
<input id="agent-week-copy-target" type="week" required>
|
||||
</label>
|
||||
|
||||
<fieldset class="entry-action-mode">
|
||||
<legend>Mode de duplication</legend>
|
||||
<label class="entry-action-option">
|
||||
<input type="radio" name="agent-week-copy-mode" value="merge" checked>
|
||||
<span><strong>Compléter</strong><small>Conserve les créneaux déjà présents. Refus en cas de chevauchement.</small></span>
|
||||
</label>
|
||||
<label class="entry-action-option">
|
||||
<input type="radio" name="agent-week-copy-mode" value="replace">
|
||||
<span><strong>Remplacer</strong><small>Efface les créneaux de la semaine cible avant la copie.</small></span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div id="agent-week-copy-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div class="admin-form-actions modal-actions">
|
||||
<button id="cancel-agent-week-copy" type="button" class="button button-secondary">Annuler</button>
|
||||
<button id="confirm-agent-week-copy" type="submit" class="button button-primary">Dupliquer la semaine</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
101
app/Views/partials/annual_overview.php
Normal file
101
app/Views/partials/annual_overview.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
$currentYear = (int) date('Y');
|
||||
?>
|
||||
<section class="page-content annual-overview-page">
|
||||
<section class="card annual-filter-card no-print">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Prévisionnel annuel de l’agent</h2>
|
||||
<p class="section-subtitle">Vue de contrôle de janvier à décembre, inspirée du tableau d’annualisation utilisé par le service.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="selection-grid overview-filters annual-filters">
|
||||
<label class="field">
|
||||
<span>Agent</span>
|
||||
<select id="annual-agent">
|
||||
<option value="">Choisir un agent</option>
|
||||
<?php foreach ($agents as $agent): ?>
|
||||
<option value="<?= (int) $agent['id_agent'] ?>">
|
||||
<?= htmlspecialchars($agent['prenom'] . ' ' . $agent['nom'] . ' — ' . ($agent['poste_libelle'] ?? 'Poste non renseigné')) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Année affichée</span>
|
||||
<input id="annual-year" type="number" min="2000" max="2100" value="<?= $currentYear ?>">
|
||||
</label>
|
||||
<div class="overview-filter-actions annual-filter-actions">
|
||||
<button id="load-annual" class="button button-primary" type="button">Afficher l’année</button>
|
||||
<button id="annual-print" class="button button-secondary" type="button" disabled>Imprimer</button>
|
||||
<button id="annual-fullscreen" class="button button-secondary" type="button" disabled>Plein écran</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="annual-message" class="message" role="status" aria-live="polite"></div>
|
||||
</section>
|
||||
|
||||
<section id="annual-content" class="annual-sheet" hidden>
|
||||
<header class="annual-sheet-header">
|
||||
<div class="annual-title-row">
|
||||
<span class="annual-direction">Direction Enfance</span>
|
||||
<h2 id="annual-title">ANNUALISATION</h2>
|
||||
<span id="annual-updated" class="annual-updated"></span>
|
||||
</div>
|
||||
<div class="annual-identity-grid">
|
||||
<div><span>Nom de l’agent</span><strong id="annual-agent-name">—</strong></div>
|
||||
<div><span>Matricule</span><strong id="annual-agent-number">—</strong></div>
|
||||
<div><span>Quotité de travail</span><strong id="annual-rate">—</strong></div>
|
||||
<div><span>Nombre d’heures</span><strong id="annual-target">—</strong></div>
|
||||
<div><span>Statut</span><strong id="annual-contract">—</strong></div>
|
||||
<div><span>Lieu principal</span><strong id="annual-location">—</strong></div>
|
||||
<div><span>Poste</span><strong id="annual-post">—</strong></div>
|
||||
<div><span>Reste à affecter</span><strong id="annual-remaining">—</strong></div>
|
||||
</div>
|
||||
<div id="annual-quota-periods" class="annual-quota-periods"></div>
|
||||
<div class="annual-toolbar no-print">
|
||||
<a id="annual-open-pta" class="button button-secondary" href="pta.php">Ouvrir le PTA détaillé</a>
|
||||
<a id="annual-open-month" class="button button-secondary" href="agents.php">Ouvrir la vue mensuelle</a>
|
||||
<p>Cliquer sur une journée pour ouvrir sa semaine dans l’écran de planning.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="annual-summary-strip">
|
||||
<article><span>Prévisionnel affiché</span><strong id="annual-calendar-total">0 h 00</strong></article>
|
||||
<article><span>Heures validées</span><strong id="annual-validated-total">0 h 00</strong></article>
|
||||
<article><span>Heures en brouillon</span><strong id="annual-draft-total">0 h 00</strong></article>
|
||||
<article><span>Période visualisée</span><strong id="annual-year-label">—</strong></article>
|
||||
</section>
|
||||
|
||||
<div class="annual-grid-scroll" tabindex="0" aria-label="Tableau annuel défilant horizontalement">
|
||||
<div id="annual-months" class="annual-months"></div>
|
||||
</div>
|
||||
|
||||
<footer class="annual-sheet-footer">
|
||||
<div id="annual-legend" class="annual-legend"></div>
|
||||
<div class="annual-abbreviations">
|
||||
<strong>Colonnes :</strong>
|
||||
<span><b>AP</b> Activité périscolaire</span>
|
||||
<span><b>PP</b> Préparation périscolaire</span>
|
||||
<span><b>AE</b> Activité extrascolaire</span>
|
||||
<span><b>PE</b> Préparation extrascolaire</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<section class="annual-validation-card no-print" aria-labelledby="annual-validation-title">
|
||||
<div class="annual-validation-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Service Enfance</p>
|
||||
<h3 id="annual-validation-title">Validation annuelle</h3>
|
||||
<p>Contrôler puis valider en une fois tous les plannings en brouillon de l’agent sur l’année affichée.</p>
|
||||
</div>
|
||||
<button id="annual-validate-year" class="button button-primary" type="button">
|
||||
Valider toutes les semaines de l’année
|
||||
</button>
|
||||
</div>
|
||||
<p class="annual-validation-note">
|
||||
En cas d’erreur, aucune semaine n’est validée. Les semaines à corriger peuvent être ouvertes dans un nouvel onglet afin de conserver cette vue annuelle ouverte.
|
||||
</p>
|
||||
<div id="annual-validation-result" class="annual-validation-result" aria-live="polite"></div>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
73
app/Views/partials/coverage_alerts.php
Normal file
73
app/Views/partials/coverage_alerts.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<section id="coverage-view" class="app-view page-content">
|
||||
<section class="card coverage-header-card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Contrôle de couverture des lieux</h2>
|
||||
<p class="section-subtitle">Repérez les plages où le nombre d’agents en « Heure de travail » est inférieur au minimum attendu.</p>
|
||||
</div>
|
||||
<button id="refresh-coverage-alerts" class="button button-secondary" type="button">Actualiser</button>
|
||||
</div>
|
||||
|
||||
<div class="selection-grid overview-filters coverage-filters">
|
||||
<label class="field">
|
||||
<span>Lieu d’affectation</span>
|
||||
<select id="coverage-structure-filter">
|
||||
<option value="">Tous les lieux</option>
|
||||
<?php foreach ($structures as $structure): ?>
|
||||
<option value="<?= (int) $structure['id_structure'] ?>"><?= htmlspecialchars($structure['nom']) ?> — <?= ($structure['type_affectation'] ?? 'PERISCOLAIRE') === 'EXTRASCOLAIRE' ? 'Extrascolaire' : 'Périscolaire' ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Semaine</span>
|
||||
<input id="coverage-week" type="week" value="<?= htmlspecialchars($currentWeek) ?>">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="coverage-summary" aria-live="polite">
|
||||
<article class="coverage-summary-card coverage-summary-danger">
|
||||
<span>Créneaux insuffisamment couverts</span>
|
||||
<strong id="coverage-gap-count">0</strong>
|
||||
<small>plage(s) à traiter</small>
|
||||
</article>
|
||||
<article class="coverage-summary-card">
|
||||
<span>Lieux concernés</span>
|
||||
<strong id="coverage-structure-count">0</strong>
|
||||
<small>avec un manque</small>
|
||||
</article>
|
||||
<article class="coverage-summary-card">
|
||||
<span>Temps non couvert</span>
|
||||
<strong id="coverage-gap-hours">0 h 00</strong>
|
||||
<small>durée cumulée</small>
|
||||
</article>
|
||||
<article class="coverage-summary-card">
|
||||
<span>Couvertures non configurées</span>
|
||||
<strong id="coverage-unconfigured-count">0</strong>
|
||||
<small>lieu(x)</small>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card coverage-list-card">
|
||||
<div id="coverage-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div id="coverage-loading" class="empty-state" hidden>Analyse de la couverture en cours…</div>
|
||||
<div id="coverage-empty" class="empty-state" hidden>Aucun manque de couverture détecté sur cette semaine.</div>
|
||||
<div id="coverage-content" class="coverage-table-wrap" hidden>
|
||||
<table class="coverage-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Lieu</th>
|
||||
<th>Jour</th>
|
||||
<th>Créneau</th>
|
||||
<th>Minimum attendu</th>
|
||||
<th>Planifié</th>
|
||||
<th>Manque</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="coverage-alerts-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="coverage-unconfigured" class="coverage-unconfigured" hidden></div>
|
||||
</section>
|
||||
</section>
|
||||
51
app/Views/partials/pending_validation.php
Normal file
51
app/Views/partials/pending_validation.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<section id="pending-validation-view" class="app-view page-content">
|
||||
<section class="card pending-validation-header-card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Plannings en attente de validation</h2>
|
||||
<p class="section-subtitle">Retrouvez tous les brouillons contenant des affectations. Ouvrez un planning pour le contrôler puis le valider directement dans l’écran de saisie.</p>
|
||||
</div>
|
||||
<button id="refresh-pending-validation" class="button button-secondary" type="button">Actualiser</button>
|
||||
</div>
|
||||
|
||||
<div class="pending-validation-summary" aria-live="polite">
|
||||
<article class="pending-summary-card">
|
||||
<span>À valider</span>
|
||||
<strong id="pending-validation-count">0</strong>
|
||||
<small>planning(s)</small>
|
||||
</article>
|
||||
<article class="pending-summary-card">
|
||||
<span>Volume en attente</span>
|
||||
<strong id="pending-validation-hours">0 h 00</strong>
|
||||
<small>toutes affectations</small>
|
||||
</article>
|
||||
<article class="pending-summary-card">
|
||||
<span>Heures décomptées</span>
|
||||
<strong id="pending-validation-counted-hours">0 h 00</strong>
|
||||
<small>impact sur les quotas</small>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card pending-validation-list-card">
|
||||
<div id="pending-validation-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div id="pending-validation-loading" class="empty-state" hidden>Chargement des plannings à valider…</div>
|
||||
<div id="pending-validation-empty" class="empty-state" hidden>Aucun planning n’est actuellement en attente de validation.</div>
|
||||
<div id="pending-validation-content" class="pending-validation-table-wrap" hidden>
|
||||
<table class="pending-validation-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Agent</th>
|
||||
<th>Lieu d’affectation</th>
|
||||
<th>Semaine</th>
|
||||
<th>Créneaux</th>
|
||||
<th>Volume</th>
|
||||
<th>Dernière modification</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="pending-validation-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
330
app/Views/partials/planning_editor.php
Normal file
330
app/Views/partials/planning_editor.php
Normal file
@@ -0,0 +1,330 @@
|
||||
<section id="editor-view" class="app-view page-content">
|
||||
<?php if (($accessProfile['role'] ?? '') === 'RESPONSABLE_STRUCTURE'): ?>
|
||||
<div class="message message-info role-page-notice">
|
||||
Vous pouvez saisir et corriger les horaires et motifs de votre lieu. Les modifications sont enregistrées en <strong>brouillon</strong> ; seul le Service Enfance peut les valider.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<section class="card selection-card">
|
||||
<h2>1. Sélection du planning</h2>
|
||||
<div class="selection-grid">
|
||||
<label class="field">
|
||||
<span>Lieu d’affectation <strong>*</strong></span>
|
||||
<select id="structure" required>
|
||||
<option value="">Choisir un lieu d’affectation</option>
|
||||
<?php foreach ($structures as $structure): ?>
|
||||
<option value="<?= (int) $structure['id_structure'] ?>">
|
||||
<?= htmlspecialchars($structure['nom']) ?> — <?= ($structure['type_affectation'] ?? 'PERISCOLAIRE') === 'EXTRASCOLAIRE' ? 'Extrascolaire' : 'Périscolaire' ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label class="field">
|
||||
<span>Agent <strong>*</strong></span>
|
||||
<select id="agent" required disabled>
|
||||
<option value="">Choisir d’abord un lieu d’affectation</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label class="field">
|
||||
<span>Semaine <strong>*</strong></span>
|
||||
<input id="week" type="week" value="<?= htmlspecialchars($currentWeek) ?>" required disabled>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="quota-strip" id="editor-quota" hidden>
|
||||
<article class="quota-card">
|
||||
<span>Quotité</span>
|
||||
<strong id="quota-rate">100 %</strong>
|
||||
</article>
|
||||
<article class="quota-card">
|
||||
<span>Quota de la période</span>
|
||||
<strong id="quota-target">1 607 h 00</strong>
|
||||
<small id="quota-period">Année civile</small>
|
||||
</article>
|
||||
<article class="quota-card">
|
||||
<span>Déjà affecté</span>
|
||||
<strong id="quota-used">0 h 00</strong>
|
||||
<small id="quota-used-detail">Validé + brouillon</small>
|
||||
</article>
|
||||
<article class="quota-card quota-card-emphasis">
|
||||
<span>Reste à affecter</span>
|
||||
<strong id="quota-remaining">1 607 h 00</strong>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="card" id="entry-card" aria-disabled="true">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>2. Saisir ou modifier les affectations</h2>
|
||||
<p class="section-subtitle">Chaque plage horaire possède son propre motif et sa propre règle de décompte du quota annuel.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="weekly-entry-toolbar">
|
||||
<p class="weekly-entry-help">Les horaires déjà enregistrés sont rechargés automatiquement. Modifiez-les directement, puis appliquez les horaires avant d’enregistrer.</p>
|
||||
</div>
|
||||
|
||||
<div class="weekly-entry-scroll">
|
||||
<table class="weekly-entry-table" aria-label="Affectations du lundi au vendredi">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Jour</th>
|
||||
<th>Affectations et plages horaires</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="weekly-entry-body">
|
||||
<tr>
|
||||
<td colspan="2" class="weekly-entry-placeholder">Sélectionnez d’abord un lieu d’affectation, un agent et une semaine.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="weekly-entry-actions">
|
||||
<button id="add-entry" class="button button-primary button-add" type="button" disabled>
|
||||
Appliquer les horaires renseignés
|
||||
</button>
|
||||
</div>
|
||||
<p class="hint">Chaque plage peut avoir un motif différent : par exemple Travail le matin puis Formation l’après-midi. Les heures sont saisies par pas de 15 minutes. Les créneaux déjà affectés à l’agent dans un autre lieu apparaissent dans le planning global et bloquent toute nouvelle saisie qui les chevaucherait.</p>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>3. Planning global de l’agent</h2>
|
||||
<p id="week-label" class="section-subtitle">Toutes les affectations de l’agent sur la semaine, quel que soit le lieu d’affectation. Cliquez sur un créneau pour le déplacer ou le dupliquer, ou glissez-le directement vers un autre jour.</p>
|
||||
</div>
|
||||
<div class="planning-summary-actions">
|
||||
<div class="totals">
|
||||
<span>Total semaine décompté</span>
|
||||
<strong id="work-total">0 h 00</strong>
|
||||
</div>
|
||||
<?php if (!empty($permissions['can_use_templates'])): ?>
|
||||
<button id="save-week-template" class="button button-secondary" type="button" disabled>
|
||||
Enregistrer comme semaine type
|
||||
</button>
|
||||
<button id="apply-week-template" class="button button-secondary" type="button" disabled>
|
||||
Importer une semaine type
|
||||
</button>
|
||||
<button id="apply-week-template-period" class="button button-secondary" type="button" disabled>
|
||||
Appliquer sur une période
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<button id="open-agent-pdf" class="button button-secondary button-pdf" type="button" disabled>
|
||||
Voir le PDF de l’agent (7 semaines)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="empty-state" class="empty-state">Aucune affectation pour le moment.</div>
|
||||
<div id="planning-board" class="planning-board" hidden></div>
|
||||
</section>
|
||||
|
||||
<section class="actions-bar">
|
||||
<div id="message" class="message" role="status" aria-live="polite"></div>
|
||||
<div class="action-buttons">
|
||||
<?php if (!empty($permissions['can_edit_draft'])): ?>
|
||||
<button id="modify-planning" class="button button-warning" type="button" hidden>Modifier le planning</button>
|
||||
<button id="save-draft" class="button button-secondary" type="button" disabled>Enregistrer le brouillon</button>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($permissions['can_validate'])): ?>
|
||||
<button id="validate-planning" class="button button-success" type="button" disabled>Valider le planning</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
<div id="planning-entry-action-modal" class="modal-backdrop" hidden>
|
||||
<section class="modal-card planning-entry-action-card" role="dialog" aria-modal="true" aria-labelledby="planning-entry-action-title">
|
||||
<div class="section-heading modal-heading">
|
||||
<div>
|
||||
<h2 id="planning-entry-action-title">Déplacer ou dupliquer un créneau</h2>
|
||||
<p id="planning-entry-action-summary" class="section-subtitle"></p>
|
||||
</div>
|
||||
<button id="close-planning-entry-action-modal" type="button" class="button button-ghost modal-close" aria-label="Fermer">×</button>
|
||||
</div>
|
||||
|
||||
<form id="planning-entry-action-form" class="admin-form">
|
||||
<fieldset class="entry-action-mode">
|
||||
<legend>Action à effectuer</legend>
|
||||
<label class="entry-action-option">
|
||||
<input type="radio" name="planning-entry-action" value="move" checked>
|
||||
<span><strong>Déplacer</strong><small>Le créneau change de jour.</small></span>
|
||||
</label>
|
||||
<label class="entry-action-option">
|
||||
<input type="radio" name="planning-entry-action" value="duplicate">
|
||||
<span><strong>Dupliquer</strong><small>Le créneau d’origine est conservé.</small></span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<label class="field">
|
||||
<span>Jour cible</span>
|
||||
<select id="planning-entry-target-date" required></select>
|
||||
</label>
|
||||
|
||||
<p class="hint">Astuce : vous pouvez aussi glisser-déposer directement un créneau vers un autre jour. Maintenez <strong>Ctrl</strong> (ou <strong>⌘</strong> sur Mac) pendant le dépôt pour le dupliquer.</p>
|
||||
<div id="planning-entry-action-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div class="admin-form-actions modal-actions">
|
||||
<button id="cancel-planning-entry-action" type="button" class="button button-secondary">Annuler</button>
|
||||
<button id="confirm-planning-entry-action" type="submit" class="button button-primary">Appliquer</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="save-week-template-modal" class="modal-backdrop" hidden>
|
||||
<section class="modal-card week-template-modal-card" role="dialog" aria-modal="true" aria-labelledby="save-week-template-title">
|
||||
<div class="section-heading modal-heading">
|
||||
<div>
|
||||
<h2 id="save-week-template-title">Enregistrer une semaine type</h2>
|
||||
<p class="section-subtitle">Le modèle mémorisera toutes les affectations de l’agent sur la semaine, tous lieux confondus.</p>
|
||||
</div>
|
||||
<button id="close-save-week-template-modal" type="button" class="button button-ghost modal-close" aria-label="Fermer">×</button>
|
||||
</div>
|
||||
|
||||
<form id="save-week-template-form" class="admin-form">
|
||||
<label class="field">
|
||||
<span>Nom de la semaine type <strong>*</strong></span>
|
||||
<input id="week-template-name" type="text" maxlength="120" placeholder="Ex. Semaine scolaire classique" required>
|
||||
</label>
|
||||
<div class="week-template-context" id="save-week-template-context"></div>
|
||||
<div id="save-week-template-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div class="admin-form-actions modal-actions">
|
||||
<button id="cancel-save-week-template" type="button" class="button button-secondary">Annuler</button>
|
||||
<button type="submit" class="button button-primary">Enregistrer le modèle</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="apply-week-template-modal" class="modal-backdrop" hidden>
|
||||
<section class="modal-card week-template-modal-card" role="dialog" aria-modal="true" aria-labelledby="apply-week-template-title">
|
||||
<div class="section-heading modal-heading">
|
||||
<div>
|
||||
<h2 id="apply-week-template-title">Importer une semaine type</h2>
|
||||
<p class="section-subtitle">Le modèle sera appliqué à la semaine actuellement sélectionnée pour cet agent.</p>
|
||||
</div>
|
||||
<button id="close-apply-week-template-modal" type="button" class="button button-ghost modal-close" aria-label="Fermer">×</button>
|
||||
</div>
|
||||
|
||||
<form id="apply-week-template-form" class="admin-form">
|
||||
<label class="field">
|
||||
<span>Semaine type <strong>*</strong></span>
|
||||
<select id="week-template-select" required>
|
||||
<option value="">Chargement...</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<div id="week-template-details" class="week-template-details"></div>
|
||||
|
||||
<fieldset class="entry-action-mode week-template-mode">
|
||||
<legend>Mode d’import</legend>
|
||||
<label class="entry-action-option">
|
||||
<input type="radio" name="week-template-mode" value="merge" checked>
|
||||
<span><strong>Compléter la semaine</strong><small>Conserve les affectations existantes. L’import est refusé en cas de chevauchement.</small></span>
|
||||
</label>
|
||||
<label class="entry-action-option">
|
||||
<input type="radio" name="week-template-mode" value="replace">
|
||||
<span><strong>Remplacer la semaine</strong><small>Supprime les affectations existantes de l’agent sur cette semaine avant d’appliquer le modèle.</small></span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div class="week-template-danger" id="week-template-replace-warning" hidden>
|
||||
Le mode « Remplacer » efface les affectations actuelles de l’agent sur la semaine sélectionnée, tous lieux confondus.
|
||||
</div>
|
||||
|
||||
<div id="apply-week-template-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div class="admin-form-actions modal-actions week-template-modal-actions">
|
||||
<button id="delete-week-template" type="button" class="button button-danger" disabled>Supprimer ce modèle</button>
|
||||
<span class="modal-action-spacer"></span>
|
||||
<button id="cancel-apply-week-template" type="button" class="button button-secondary">Annuler</button>
|
||||
<button type="submit" class="button button-primary">Importer le modèle</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="apply-week-template-period-modal" class="modal-backdrop" hidden>
|
||||
<section class="modal-card week-template-period-modal-card" role="dialog" aria-modal="true" aria-labelledby="apply-week-template-period-title">
|
||||
<div class="section-heading modal-heading">
|
||||
<div>
|
||||
<h2 id="apply-week-template-period-title">Appliquer une semaine type sur une période</h2>
|
||||
<p class="section-subtitle">Les périodes de vacances déjà validées dans PTA sont prises en compte avant toute création de planning.</p>
|
||||
</div>
|
||||
<button id="close-apply-week-template-period-modal" type="button" class="button button-ghost modal-close" aria-label="Fermer">×</button>
|
||||
</div>
|
||||
|
||||
<form id="apply-week-template-period-form" class="admin-form">
|
||||
<div class="week-template-period-grid">
|
||||
<label class="field">
|
||||
<span>Semaine type <strong>*</strong></span>
|
||||
<select id="week-template-period-select" required>
|
||||
<option value="">Chargement...</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Date de début <strong>*</strong></span>
|
||||
<input id="week-template-period-start" type="date" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Date de fin <strong>*</strong></span>
|
||||
<input id="week-template-period-end" type="date" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<fieldset class="entry-action-mode week-template-mode">
|
||||
<legend>Périodes à appliquer</legend>
|
||||
<label class="entry-action-option">
|
||||
<input type="radio" name="week-template-period-filter" value="all" checked>
|
||||
<span><strong>Toutes les semaines</strong><small>Répète la semaine type sur toutes les dates de la période, qu’elles soient scolaires ou pendant les vacances.</small></span>
|
||||
</label>
|
||||
<label class="entry-action-option">
|
||||
<input type="radio" name="week-template-period-filter" value="school">
|
||||
<span><strong>Uniquement les périodes scolaires</strong><small>Applique le modèle uniquement aux jours situés hors des vacances enregistrées dans PTA.</small></span>
|
||||
</label>
|
||||
<label class="entry-action-option">
|
||||
<input type="radio" name="week-template-period-filter" value="extra">
|
||||
<span><strong>Uniquement les périodes extrascolaires</strong><small>Applique le modèle uniquement aux jours compris dans les vacances scolaires enregistrées dans PTA.</small></span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div class="week-template-period-rule-note">
|
||||
<strong>Calendrier :</strong>
|
||||
le caractère scolaire ou extrascolaire d’une date est déterminé à partir des périodes de vacances validées dans PTA.
|
||||
Le choix ci-dessus pilote l’application du modèle ; il n’est pas déduit du lieu d’affectation.
|
||||
</div>
|
||||
|
||||
<fieldset class="entry-action-mode week-template-mode">
|
||||
<legend>Mode d’application</legend>
|
||||
<label class="entry-action-option">
|
||||
<input type="radio" name="week-template-period-mode" value="merge" checked>
|
||||
<span><strong>Compléter les plannings</strong><small>Conserve les affectations déjà existantes. L’application est bloquée si un chevauchement est détecté.</small></span>
|
||||
</label>
|
||||
<label class="entry-action-option">
|
||||
<input type="radio" name="week-template-period-mode" value="replace">
|
||||
<span><strong>Remplacer les jours concernés</strong><small>Supprime les affectations existantes uniquement sur les dates où le modèle doit réellement s’appliquer, puis recrée le planning.</small></span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div class="week-template-danger" id="week-template-period-replace-warning" hidden>
|
||||
Les journées exclues par le filtre de calendrier ne seront pas effacées. Seules les dates sur lesquelles le modèle crée au moins un créneau seront remplacées.
|
||||
</div>
|
||||
|
||||
<div class="week-template-period-preview-actions">
|
||||
<button id="preview-week-template-period" type="button" class="button button-secondary">Prévisualiser l’application</button>
|
||||
</div>
|
||||
|
||||
<div id="week-template-period-preview" class="week-template-period-preview" hidden></div>
|
||||
<div id="apply-week-template-period-message" class="message" role="status" aria-live="polite"></div>
|
||||
|
||||
<div class="admin-form-actions modal-actions">
|
||||
<button id="cancel-apply-week-template-period" type="button" class="button button-secondary">Annuler</button>
|
||||
<button id="confirm-apply-week-template-period" type="submit" class="button button-primary" disabled>Appliquer sur la période</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
133
app/Views/partials/pta.php
Normal file
133
app/Views/partials/pta.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<section class="page-content pta-page">
|
||||
<section class="card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>PTA annuel de l’agent</h2>
|
||||
<p class="section-subtitle">Synthèse de l’année civile, répartition des 1 607 heures proratisées et contrôles métier. Un même agent peut intervenir en périscolaire et en extrascolaire.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="selection-grid overview-filters">
|
||||
<label class="field">
|
||||
<span>Agent soumis au PTA</span>
|
||||
<select id="pta-agent">
|
||||
<option value="">Choisir un agent</option>
|
||||
<?php foreach ($agents as $agent): ?>
|
||||
<option value="<?= (int) $agent['id_agent'] ?>">
|
||||
<?= htmlspecialchars($agent['prenom'] . ' ' . $agent['nom'] . ' — ' . ($agent['poste_libelle'] ?? 'Poste non renseigné')) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Date de référence</span>
|
||||
<input id="pta-reference-date" type="date" value="<?= htmlspecialchars(date('Y-m-d')) ?>">
|
||||
</label>
|
||||
<div class="overview-filter-actions">
|
||||
<button id="load-pta" type="button" class="button button-primary filter-button">Afficher le PTA</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="pta-message" class="message" role="status" aria-live="polite"></div>
|
||||
</section>
|
||||
|
||||
<section id="pta-content" hidden>
|
||||
<section class="card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2 id="pta-agent-name">Synthèse</h2>
|
||||
<p id="pta-agent-meta" class="section-subtitle"></p>
|
||||
</div>
|
||||
<div class="button-group">
|
||||
<a id="pta-open-planning" class="button button-secondary" href="planning.php">Ouvrir le planning</a>
|
||||
<a id="pta-open-agent-view" class="button button-secondary" href="agents.php">Vue mensuelle</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="pta-summary-cards" class="summary-grid"></div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Répartition du temps</h2>
|
||||
<p class="section-subtitle">Les congés annuels et les JNT restent visibles, même lorsqu’ils ne décomptent pas le quota.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-scroll">
|
||||
<table class="planning-table">
|
||||
<thead><tr><th>Catégorie</th><th>Durée</th><th>Jours concernés</th></tr></thead>
|
||||
<tbody id="pta-category-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Contrôles du PTA</h2>
|
||||
<p class="section-subtitle">Les alertes signalent les incohérences à contrôler ; elles ne remplacent pas la validation RH ou réglementaire.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="pta-controls" class="control-list"></div>
|
||||
</section>
|
||||
|
||||
<div class="admin-grid">
|
||||
<section class="card admin-card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Contraintes prioritaires</h2>
|
||||
<p class="section-subtitle">Préconisation médicale ou temps partiel thérapeutique applicable sur une période.</p>
|
||||
</div>
|
||||
</div>
|
||||
<form id="pta-constraint-form" class="admin-form">
|
||||
<div class="admin-form-grid">
|
||||
<label class="field">
|
||||
<span>Type</span>
|
||||
<select id="pta-constraint-type" required>
|
||||
<option value="MEDICALE">Préconisation médicale</option>
|
||||
<option value="TEMPS_PARTIEL_THERAPEUTIQUE">Temps partiel thérapeutique</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field"><span>Début</span><input id="pta-constraint-start" type="date" required></label>
|
||||
<label class="field"><span>Fin</span><input id="pta-constraint-end" type="date"></label>
|
||||
<label class="field"><span>Quotité temporaire (%)</span><input id="pta-constraint-rate" type="number" min="1" max="100" step="0.01"></label>
|
||||
<label class="field"><span>Maximum par jour (h)</span><input id="pta-constraint-day-max" type="number" min="0.25" step="0.25"></label>
|
||||
<label class="field"><span>Maximum par semaine (h)</span><input id="pta-constraint-week-max" type="number" min="0.25" step="0.25"></label>
|
||||
<label class="check-field"><input id="pta-forbid-morning" type="checkbox"> <span>Interdit le matin</span></label>
|
||||
<label class="check-field"><input id="pta-forbid-midday" type="checkbox"> <span>Interdit le midi</span></label>
|
||||
<label class="check-field"><input id="pta-forbid-evening" type="checkbox"> <span>Interdit le soir</span></label>
|
||||
<label class="field admin-field-wide"><span>Commentaire prioritaire</span><textarea id="pta-constraint-comment" rows="3" maxlength="1000" required></textarea></label>
|
||||
</div>
|
||||
<div class="admin-form-actions"><button class="button button-primary" type="submit">Enregistrer la contrainte</button></div>
|
||||
</form>
|
||||
<div id="pta-constraint-list" class="stack-list"></div>
|
||||
</section>
|
||||
|
||||
<section class="card admin-card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Préférences et interdictions de lieu</h2>
|
||||
<p class="section-subtitle">Ces informations orientent la composition des équipes après les contraintes prioritaires.</p>
|
||||
</div>
|
||||
</div>
|
||||
<form id="pta-wish-form" class="admin-form">
|
||||
<div class="admin-form-grid">
|
||||
<label class="field">
|
||||
<span>Lieu</span>
|
||||
<select id="pta-wish-structure" required>
|
||||
<option value="">Choisir un lieu</option>
|
||||
<?php foreach ($structures as $structure): ?>
|
||||
<option value="<?= (int) $structure['id_structure'] ?>"><?= htmlspecialchars($structure['nom']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field"><span>Choix</span><select id="pta-wish-type"><option value="PREFERENCE">Préférence</option><option value="INTERDICTION">Interdiction</option></select></label>
|
||||
<label class="field"><span>Priorité</span><input id="pta-wish-priority" type="number" min="1" max="5" value="1"></label>
|
||||
<label class="field"><span>Distance domicile-lieu (km)</span><input id="pta-wish-distance" type="number" min="0" step="0.1"></label>
|
||||
<label class="field admin-field-wide"><span>Commentaire</span><textarea id="pta-wish-comment" rows="3" maxlength="500"></textarea></label>
|
||||
</div>
|
||||
<div class="admin-form-actions"><button class="button button-primary" type="submit">Enregistrer le choix</button></div>
|
||||
</form>
|
||||
<div id="pta-wish-list" class="stack-list"></div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
35
app/Views/partials/structure_overview.php
Normal file
35
app/Views/partials/structure_overview.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<section id="structure-view" class="app-view page-content">
|
||||
<section class="card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2><?= ($accessProfile['role'] ?? '') === 'AGENT' ? 'Planning de mon lieu d’affectation' : 'Vue d’ensemble d’un lieu d’affectation' ?></h2>
|
||||
<p class="section-subtitle">Les agents rattachés par défaut à ce lieu et ceux qui y sont effectivement planifiés sur la semaine. Cette vue est en lecture seule.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="selection-grid overview-filters">
|
||||
<label class="field">
|
||||
<span>Lieu d’affectation</span>
|
||||
<select id="overview-structure">
|
||||
<option value="">Choisir un lieu d’affectation</option>
|
||||
<?php foreach ($structures as $structure): ?>
|
||||
<option value="<?= (int) $structure['id_structure'] ?>"><?= htmlspecialchars($structure['nom']) ?> — <?= ($structure['type_affectation'] ?? 'PERISCOLAIRE') === 'EXTRASCOLAIRE' ? 'Extrascolaire' : 'Périscolaire' ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Semaine</span>
|
||||
<input id="overview-week" type="week" value="<?= htmlspecialchars($currentWeek) ?>">
|
||||
</label>
|
||||
<div class="overview-filter-actions">
|
||||
<button id="load-structure-overview" class="button button-primary filter-button" type="button">Afficher</button>
|
||||
<button id="open-structure-pdf" class="button button-secondary filter-button button-pdf" type="button" disabled>Voir le PDF du lieu</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card overview-card">
|
||||
<div id="structure-overview-empty" class="empty-state">Choisissez un lieu d’affectation et une semaine.</div>
|
||||
<div id="structure-overview-content" hidden></div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
54
app/Views/partials/teams.php
Normal file
54
app/Views/partials/teams.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<section class="page-content team-page">
|
||||
<section class="card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Élaborer les équipes</h2>
|
||||
<p class="section-subtitle">Équipes périscolaires, mercredis scolaires et périodes extrascolaires, avec contrôle de l’effectif et de la qualification. Un même agent peut appartenir à plusieurs types d’équipes au cours de l’année.</p>
|
||||
</div>
|
||||
</div>
|
||||
<form id="team-create-form" class="admin-form">
|
||||
<div class="admin-form-grid">
|
||||
<label class="field"><span>Nom de l’équipe</span><input id="team-label" type="text" maxlength="180" required placeholder="Ex. Vacances d’hiver — Équipe Matusalème"></label>
|
||||
<label class="field"><span>Type</span><select id="team-type" required><option value="MERCREDI_PERISCOLAIRE">Mercredi périscolaire</option><option value="EXTRASCOLAIRE">Extrascolaire</option><option value="PERISCOLAIRE_SEMAINE">Périscolaire semaine</option></select></label>
|
||||
<label class="field"><span>Lieu</span><select id="team-structure" required><option value="">Choisir un lieu</option><?php foreach ($structures as $structure): ?><option value="<?= (int) $structure['id_structure'] ?>"><?= htmlspecialchars($structure['nom']) ?></option><?php endforeach; ?></select></label>
|
||||
<label class="field"><span>Date de début</span><input id="team-start" type="date" required></label>
|
||||
<label class="field"><span>Date de fin</span><input id="team-end" type="date" required></label>
|
||||
<label class="field"><span>Enfants de moins de 6 ans</span><input id="team-under-six" type="number" min="0" value="0"></label>
|
||||
<label class="field"><span>Enfants de 6 ans et plus</span><input id="team-over-six" type="number" min="0" value="0"></label>
|
||||
<label class="field"><span>Ratio moins de 6 ans (1 pour)</span><input id="team-ratio-under-six" type="number" min="1" value="8"></label>
|
||||
<label class="field"><span>Ratio 6 ans et plus (1 pour)</span><input id="team-ratio-over-six" type="number" min="1" value="12"></label>
|
||||
<label class="field"><span>Minimum d’agents</span><input id="team-min-agents" type="number" min="1" value="1"></label>
|
||||
<label class="field"><span>Diplômés minimum (%)</span><input id="team-qualified-rate" type="number" min="0" max="100" step="0.01" value="50"></label>
|
||||
<label class="field admin-field-wide"><span>Commentaire</span><textarea id="team-comment" rows="3" maxlength="1000"></textarea></label>
|
||||
</div>
|
||||
<div class="admin-form-actions">
|
||||
<div id="team-create-message" class="message" role="status" aria-live="polite"></div>
|
||||
<button class="button button-primary" type="submit">Créer l’équipe</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Équipes enregistrées</h2>
|
||||
<p class="section-subtitle">Les seuils d’encadrement et de qualification sont paramétrables pour chaque équipe avant validation.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="selection-grid overview-filters">
|
||||
<label class="field"><span>Du</span><input id="team-filter-start" type="date"></label>
|
||||
<label class="field"><span>Au</span><input id="team-filter-end" type="date"></label>
|
||||
<div class="overview-filter-actions"><button id="load-teams" class="button button-secondary filter-button" type="button">Actualiser</button></div>
|
||||
</div>
|
||||
<div id="team-list-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div id="team-list" class="team-list"><div class="empty-state">Chargez les équipes pour commencer.</div></div>
|
||||
</section>
|
||||
|
||||
<template id="team-agent-options">
|
||||
<?php foreach ($agents as $agent): ?>
|
||||
<option value="<?= (int) $agent['id_agent'] ?>">
|
||||
<?= htmlspecialchars($agent['prenom'] . ' ' . $agent['nom'] . ' — ' . ($agent['poste_libelle'] ?? 'Poste non renseigné') . (!empty($agent['est_diplome']) ? ' — diplômé' : ' — non diplômé')) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</template>
|
||||
</section>
|
||||
144
app/Views/partials/vacation_calendar.php
Normal file
144
app/Views/partials/vacation_calendar.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
$currentYear = (int) date('Y');
|
||||
$currentMonth = (int) date('n');
|
||||
$schoolYearStart = $currentMonth >= 8 ? $currentYear : $currentYear - 1;
|
||||
$defaultSchoolYear = $schoolYearStart . '-' . ($schoolYearStart + 1);
|
||||
$defaultCalendarYear = $currentYear;
|
||||
?>
|
||||
<section id="vacation-view" class="app-view page-content">
|
||||
<section class="card vacation-import-card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Vacances scolaires</h2>
|
||||
<p class="section-subtitle">Consultez toutes les vacances d’une année civile complète, de janvier à décembre. PTA agrège les deux années scolaires concernées, accepte les périodes publiées pour les élèves ou pour tous les publics, puis vous laisse contrôler et enregistrer vous-même les dates souhaitées.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vacation-api-note">
|
||||
<strong>Principe :</strong> une journée comprise dans une période de vacances enregistrée est considérée comme <strong>extrascolaire</strong>. En dehors de ces périodes, elle est considérée comme <strong>périscolaire</strong>.
|
||||
</div>
|
||||
|
||||
<div class="selection-grid vacation-filters">
|
||||
<label class="field">
|
||||
<span>Académie</span>
|
||||
<input id="vacation-academy" type="text" maxlength="100" value="Orléans-Tours" placeholder="Ex. Orléans-Tours" list="vacation-academies" autocomplete="off">
|
||||
<datalist id="vacation-academies">
|
||||
<option value="Aix-Marseille"><option value="Amiens"><option value="Besançon"><option value="Bordeaux">
|
||||
<option value="Clermont-Ferrand"><option value="Créteil"><option value="Dijon"><option value="Grenoble">
|
||||
<option value="Lille"><option value="Limoges"><option value="Lyon"><option value="Montpellier">
|
||||
<option value="Nancy-Metz"><option value="Nantes"><option value="Nice"><option value="Normandie">
|
||||
<option value="Orléans-Tours"><option value="Paris"><option value="Poitiers"><option value="Reims">
|
||||
<option value="Rennes"><option value="Strasbourg"><option value="Toulouse"><option value="Versailles">
|
||||
</datalist>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Année civile</span>
|
||||
<input id="vacation-calendar-year" type="number" min="2000" max="2100" value="<?= (int) $defaultCalendarYear ?>" placeholder="2026">
|
||||
</label>
|
||||
<div class="overview-filter-actions">
|
||||
<button id="preview-vacations" type="button" class="button button-secondary filter-button">Consulter les dates proposées</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="vacation-preview-message" class="message" role="status" aria-live="polite"></div>
|
||||
|
||||
<div id="vacation-preview-panel" class="vacation-preview-panel" hidden>
|
||||
<div class="section-heading compact-heading">
|
||||
<div>
|
||||
<h3>Dates proposées par l’API</h3>
|
||||
<p class="section-subtitle">Toutes les périodes de l’année civile sont proposées, y compris celles rattachées à deux années scolaires différentes. Cochez uniquement celles que vous souhaitez conserver ; les dates restent modifiables avant l’enregistrement.</p>
|
||||
</div>
|
||||
<label class="vacation-select-all">
|
||||
<input id="vacation-select-all" type="checkbox">
|
||||
Tout sélectionner
|
||||
</label>
|
||||
</div>
|
||||
<div class="table-scroll">
|
||||
<table class="planning-table vacation-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Importer</th>
|
||||
<th>Période</th>
|
||||
<th>Début</th>
|
||||
<th>Fin</th>
|
||||
<th>Zone / académie</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="vacation-preview-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="admin-form-actions">
|
||||
<button id="save-selected-vacations" type="button" class="button button-primary">Enregistrer les périodes sélectionnées</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card vacation-manual-card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Ajouter une période manuellement</h2>
|
||||
<p class="section-subtitle">Utilisez ce formulaire pour corriger le calendrier ou ajouter une période qui n’apparaît pas dans l’API.</p>
|
||||
</div>
|
||||
</div>
|
||||
<form id="manual-vacation-form" class="admin-form">
|
||||
<div class="admin-form-grid">
|
||||
<label class="field">
|
||||
<span>Libellé <strong>*</strong></span>
|
||||
<input id="manual-vacation-label" type="text" maxlength="150" placeholder="Ex. Vacances de la Toussaint" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Année scolaire <strong>*</strong></span>
|
||||
<input id="manual-vacation-school-year" type="text" maxlength="9" value="<?= htmlspecialchars($defaultSchoolYear) ?>" pattern="\d{4}-\d{4}" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Date de début <strong>*</strong></span>
|
||||
<input id="manual-vacation-start" type="date" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Dernier jour de vacances <strong>*</strong></span>
|
||||
<input id="manual-vacation-end" type="date" required>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Académie</span>
|
||||
<input id="manual-vacation-academy" type="text" maxlength="100" value="Orléans-Tours">
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Zone</span>
|
||||
<input id="manual-vacation-zone" type="text" maxlength="50" placeholder="Ex. Zone B">
|
||||
</label>
|
||||
</div>
|
||||
<div class="admin-form-actions">
|
||||
<div id="manual-vacation-message" class="message" role="status" aria-live="polite"></div>
|
||||
<button type="submit" class="button button-primary">Ajouter la période</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>Périodes enregistrées</h2>
|
||||
<p class="section-subtitle">Ces périodes sont celles réellement utilisées par PTA pour distinguer périscolaire et extrascolaire.</p>
|
||||
</div>
|
||||
<button id="refresh-vacations" type="button" class="button button-secondary">Actualiser</button>
|
||||
</div>
|
||||
<div id="vacation-saved-message" class="message" role="status" aria-live="polite"></div>
|
||||
<div class="table-scroll">
|
||||
<table class="planning-table vacation-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Période</th>
|
||||
<th>Dates</th>
|
||||
<th>Année scolaire</th>
|
||||
<th>Académie / zone</th>
|
||||
<th>Source</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="vacation-saved-body">
|
||||
<tr><td colspan="6"><div class="empty-state">Chargement des périodes enregistrées…</div></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
Reference in New Issue
Block a user