Files
pointeuse-optimisator/app/templates/_ligne.html
Jacquin Antoine 3d38abd853 Astreinte : préférence personnelle et retour aligné sur les quarts d'horloge
- La gestion des astreintes devient un réglage par compte (Réglages →
  « Gestion des astreintes », actif par défaut) : désactivée, le bouton AS,
  les interventions, forfaits, repos de 11h, récapitulatif, ratios, stats
  et exports n'en parlent plus — sans rien supprimer, réactiver retrouve tout
- L'heure de retour au bureau tombe désormais toujours sur un quart d'heure
  d'horloge fixe (:00, :15, :30, :45), arrondie au supérieur après les 11h
  de repos (ex. fin comptée 23:54 → retour 11:00)
- Corrigé : enregistrer ses plages horaires écrasait le forfait d'astreinte

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
2026-09-09 20:48:59 +02:00

192 lines
9.9 KiB
HTML
Raw 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.

{% set matin_cg = 'matin' in j.conge or 'jour' in j.conge %}
{% set aprem_cg = 'aprem' in j.conge or 'jour' in j.conge %}
{% set matin_requis = not matin_cg and j.du_min > 0 and j.matin_nominal_min > 0 %}
{% set aprem_requis = not aprem_cg and j.du_min > 0 and j.aprem_nominal_min > 0 %}
{% set borne_matin = [plages.matin_debut, j.retour or plages.matin_debut] | max %}
{% set borne_aprem = [plages.aprem_debut, j.retour or plages.aprem_debut] | max %}
{% set matin_warn = matin_requis and (
(j.matin_entree and j.matin_entree > borne_matin) or
(j.matin_sortie and j.matin_sortie < plages.matin_fin)
) %}
{% set aprem_warn = aprem_requis and (
(j.aprem_entree and j.aprem_entree > borne_aprem) or
(j.aprem_sortie and j.aprem_sortie < plages.aprem_fin)
) %}
<tr id="row-{{ j.date }}"{% if nom in ['Samedi', 'Dimanche'] or j.ferie %} class="we"{% endif %}>
<td class="col-jour">
<span class="jour-nom">{{ nom }}</span>
<span class="jour-date">{{ j.date[8:] }}/{{ j.date[5:7] }}</span>
{% if j.ferie %}<span class="ferie-badge" title="Jour férié : dû 0, astreinte comptée 0h00 → 0h00">férié</span>{% endif %}
<!-- Auto-enregistrement : la sauvegarde se déclenche à la validation d'un
champ du jour (voir script de semaine.html), ce témoin en suit l'état. -->
<span class="autosave" id="save-{{ j.date }}" data-date="{{ j.date }}"
hx-post="/pointage/{{ j.date }}" hx-swap="none"
hx-include="[data-date='{{ j.date }}']" hx-trigger="save-day"></span>
</td>
<td class="c-matin">
<div id="cg-matin-{{ j.date }}" data-label="Matin" class="td-fill{% if matin_cg %} cg{% elif matin_warn %} warn{% endif %}">
<div class="time-pair">
<input class="time-input" type="time" name="matin_entree"
data-date="{{ j.date }}" value="{{ j.matin_entree or '' }}">
<span class="time-sep">→</span>
<input class="time-input" type="time" name="matin_sortie"
data-date="{{ j.date }}" value="{{ j.matin_sortie or '' }}">
</div>
</div>
</td>
<td class="c-aprem">
<div id="cg-aprem-{{ j.date }}" data-label="Après-midi" class="td-fill{% if aprem_cg %} cg{% elif aprem_warn %} warn{% endif %}">
<div class="time-pair">
<input class="time-input" type="time" name="aprem_entree"
data-date="{{ j.date }}" value="{{ j.aprem_entree or '' }}">
<span class="time-sep">→</span>
<input class="time-input" type="time" name="aprem_sortie"
data-date="{{ j.date }}" value="{{ j.aprem_sortie or '' }}">
</div>
</div>
</td>
<td class="col-calc" data-label="Travaillé">
<span id="calc-{{ j.date }}-trav">
<span class="calc-num">{{ j.travaille if j.travaille_min else '—' }}</span>
</span>
</td>
<td class="col-calc" data-label="Δ jour">
<span id="calc-{{ j.date }}-delta">
<span class="{% if j.travaille_min and j.delta_min > 0 %}delta-pos{% elif j.travaille_min and j.delta_min < 0 %}delta-neg{% else %}delta-zero{% endif %}">
{%- if j.travaille_min -%}
{% if j.delta_min > 0 %}+{% endif %}{{ j.delta }}
{%- else %}—{%- endif %}
</span>
</span>
</td>
<td class="col-cumul" data-label="Δ sem.">
<span id="calc-{{ j.date }}-cumul">
{%- if j.cumul_visible -%}
<span class="{% if j.delta_cumul_min > 0 %}delta-pos{% elif j.delta_cumul_min < 0 %}delta-neg{% else %}delta-zero{% endif %}">
{% if j.delta_cumul_min > 0 %}+{% elif j.delta_cumul_min < 0 %}-{% endif %}{{ j.delta_cumul if j.delta_cumul_min != 0 else '0h00' }}
</span>
{%- else -%}
<span class="delta-zero">—</span>
{%- endif %}
</span>
</td>
<td class="col-cible" data-label="Cible">
<span id="calc-{{ j.date }}-cible">
{%- if j.cible_matin or j.cible_aprem -%}
{%- if j.cible_matin -%}<span class="cible-num">M {{ j.cible_matin_entree }} → {{ j.cible_matin }}</span>{%- endif -%}
{%- if j.cible_matin and j.cible_aprem %} {% endif -%}
{%- if j.cible_aprem -%}<span class="cible-num">A {{ j.cible_aprem_entree }} → {{ j.cible_aprem }}</span>{%- endif -%}
{%- else -%}
<span class="delta-zero">—</span>
{%- endif %}
</span>
</td>
<td class="col-conge" data-label="Congé">
<div id="cg-btn-{{ j.date }}" class="cg-cell">
<details class="cg-menu">
<summary class="cg-trigger" title="Congés, jour férié, astreinte">
<span class="cg-state">
{%- if 'jour' in j.conge %}<span class="cg-chip st-jour">J</span>{% endif -%}
{%- if 'matin' in j.conge %}<span class="cg-chip st-ma">MA</span>{% endif -%}
{%- if 'aprem' in j.conge %}<span class="cg-chip st-am">AM</span>{% endif -%}
{%- if j.ferie %}<span class="cg-chip st-ferie">F</span>{% endif -%}
{%- if plages.astreinte_active and j.astreinte %}<span class="cg-chip st-as">AS</span>{% endif -%}
{%- if not (j.conge or j.ferie or (plages.astreinte_active and j.astreinte)) %}<span class="cg-none">—</span>{% endif -%}
</span>
<span class="cg-caret">▾</span>
</summary>
<div class="cg-pop">
<button hx-post="/conge/{{ j.date }}/matin" hx-swap="none"
class="cg-opt{% if 'matin' in j.conge %} on{% endif %}">
<span class="cg-opt-chip ma">MA</span> Congé matin
</button>
<button hx-post="/conge/{{ j.date }}/aprem" hx-swap="none"
class="cg-opt{% if 'aprem' in j.conge %} on{% endif %}">
<span class="cg-opt-chip am">AM</span> Congé après-midi
</button>
<button hx-post="/conge/{{ j.date }}/jour" hx-swap="none"
class="cg-opt{% if 'jour' in j.conge %} on{% endif %}">
<span class="cg-opt-chip jour">J</span> Journée entière
</button>
<div class="cg-opt-sep"></div>
<button hx-post="/ferie/{{ j.date }}/toggle" hx-swap="none"
class="cg-opt{% if j.ferie %} on{% endif %}"
title="Jour férié : dû 0, astreinte comptée 0h00 → 0h00">
<span class="cg-opt-chip ferie">F</span> Jour férié
</button>
{% if plages.astreinte_active %}
<button hx-post="/astreinte/{{ j.date }}/toggle" hx-swap="none"
class="cg-opt{% if j.astreinte %} on{% endif %}"
title="Jour d'astreinte (18h → 18h, ou 0h → 0h sam/dim/férié)">
<span class="cg-opt-chip as">AS</span> Jour d'astreinte
</button>
{% endif %}
</div>
</details>
</div>
</td>
</tr>
{% if j.astreinte_qualifiee %}
{% set nb_as = (j.astreinte_events or []) | length %}
<tr class="as-row{% if nom in ['Samedi', 'Dimanche'] %} we{% endif %}">
<td colspan="8">
<div id="as-block-{{ j.date }}" class="as-block" data-date="{{ j.date }}" data-label="Astreinte">
<div class="as-head">
<button type="button" class="as-toggle" data-date="{{ j.date }}" aria-expanded="false"
onclick="asToggle(this)">
<span class="as-caret">▸</span> {{ nb_as }} intervention{{ 's' if nb_as != 1 else '' }}
</button>
{% if j.retour_min is not none %}<span class="as-hint" title="11h de repos consécutif après la dernière activité (durée arrondie au quart d'heure supérieur), retour arrondi au quart d'horloge supérieur : :00, :15, :30 ou :45">retour ≥ {{ j.retour }}</span>{% endif %}
{% if j.forfait_min %}<span class="as-hint" title="Forfait du jour AS déclaré (Réglages) : suivi dans le récapitulatif d'astreinte, hors heures travaillées">forfait {{ j.forfait_h }}</span>{% endif %}
{% if j.astreinte_min %}<span class="as-total" title="Durée réelle des interventions arrondie au quart d'heure supérieur (2, 5 ou 12 min → 15 ; 22 ou 28 → 30), même sans tomber sur un quart d'heure de l'horloge — compteur séparé, hors heures de semaine">astreinte : {{ j.astreinte_h }}</span>{% endif %}
</div>
<div class="as-body">
<div class="as-grid" id="as-events-{{ j.date }}">
<span class="as-th">Début</span><span class="as-th">Fin</span><span class="as-th">Description</span>
{% for ev in j.astreinte_events or [] %}
<div class="as-event">
<input class="time-input" type="time" name="astreinte_debut"
data-date="{{ j.date }}" value="{{ ev.debut or '' }}">
<input class="time-input" type="time" name="astreinte_fin"
data-date="{{ j.date }}" value="{{ ev.fin or '' }}">
<div class="as-desc-cell">
<input type="text" class="as-desc" name="astreinte_desc"
data-date="{{ j.date }}" maxlength="200" placeholder="description"
value="{{ ev.desc or '' }}">
<button type="button" class="as-del" title="Supprimer"
onclick="this.closest('.as-event').remove()">×</button>
</div>
</div>
{% else %}
<div class="as-event">
<input class="time-input" type="time" name="astreinte_debut"
data-date="{{ j.date }}" value="">
<input class="time-input" type="time" name="astreinte_fin"
data-date="{{ j.date }}" value="">
<div class="as-desc-cell">
<input type="text" class="as-desc" name="astreinte_desc"
data-date="{{ j.date }}" maxlength="200" placeholder="description" value="">
<button type="button" class="as-del" title="Supprimer"
onclick="this.closest('.as-event').remove()">×</button>
</div>
</div>
{% endfor %}
</div>
<button type="button" class="as-add" onclick="asAddEvent('{{ j.date }}')">+ intervention</button>
</div>
</div>
</td>
</tr>
{% else %}
<tr class="as-row{% if nom in ['Samedi', 'Dimanche'] %} we{% endif %}"><td colspan="8"><div id="as-block-{{ j.date }}" class="as-block"></div></td></tr>
{% endif %}