La saisie astreinte devient une liste d'événements (début, fin, description,
nombre illimité, fin antérieure au début = intervention à cheval sur minuit).
Ces heures ne comptent jamais dans la semaine : elles sont décomptées à part
par pas de 15 minutes, toute tranche entamée comptant en totalité, et rangées
dans des compteurs selon le jour et l'heure (Nuit ×1,5, Journée semaine ×1,
Samedi ×1,5, Dimanche/férié ×2 ; jours fériés français calculés
automatiquement, règles ajustables dans config.json via astreinte_facteurs).
Le détail par événement et les totaux pondérés s'affichent sous le bandeau de
la semaine, et les exports .ods gagnent les colonnes Astreinte brute et
pondérée. Le retour au bureau (fin du dernier événement + 11h de repos) est
désormais dérivé des événements.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
154 lines
6.9 KiB
HTML
154 lines
6.9 KiB
HTML
{% 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 }}">
|
||
|
||
<td class="col-jour">
|
||
<span class="jour-nom">{{ nom }}</span>
|
||
<span class="jour-date">{{ j.date[8:] }}/{{ j.date[5:7] }}</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>
|
||
{% if j.astreinte_qualifiee %}
|
||
<div id="as-block-{{ j.date }}" class="as-block" data-label="Astreinte">
|
||
<div class="as-events" id="as-events-{{ j.date }}">
|
||
{% 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 '' }}">
|
||
<span class="time-sep">→</span>
|
||
<input class="time-input" type="time" name="astreinte_fin"
|
||
data-date="{{ j.date }}" value="{{ ev.fin or '' }}">
|
||
<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>
|
||
{% else %}
|
||
<div class="as-event">
|
||
<input class="time-input" type="time" name="astreinte_debut"
|
||
data-date="{{ j.date }}" value="">
|
||
<span class="time-sep">→</span>
|
||
<input class="time-input" type="time" name="astreinte_fin"
|
||
data-date="{{ j.date }}" value="">
|
||
<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>
|
||
{% endfor %}
|
||
</div>
|
||
<button type="button" class="as-add" onclick="asAddEvent('{{ j.date }}')">+ intervention</button>
|
||
{% if j.retour_min is not none %}<span class="as-hint" title="11h de repos consécutif après la dernière activité">retour ≥ {{ j.retour }}</span>{% endif %}
|
||
{% if j.astreinte_min %}<span class="as-total" title="Compteur séparé, hors heures de semaine">astreinte : {{ j.astreinte_h }}</span>{% endif %}
|
||
</div>
|
||
{% else %}
|
||
<div id="as-block-{{ j.date }}"></div>
|
||
{% endif %}
|
||
</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-save">
|
||
<button class="btn-valider"
|
||
hx-post="/pointage/{{ j.date }}"
|
||
hx-swap="none"
|
||
hx-include="[data-date='{{ j.date }}']"
|
||
title="Enregistrer">✓</button>
|
||
</td>
|
||
|
||
<td class="col-conge" data-label="Congé">
|
||
<div id="cg-btn-{{ j.date }}">
|
||
<div class="conge-btns">
|
||
<button hx-post="/conge/{{ j.date }}/matin"
|
||
hx-swap="none"
|
||
class="btn-cg {% if 'matin' in j.conge %}on{% endif %}"
|
||
title="Congé matin">MA</button>
|
||
<button hx-post="/conge/{{ j.date }}/aprem"
|
||
hx-swap="none"
|
||
class="btn-cg {% if 'aprem' in j.conge %}on{% endif %}"
|
||
title="Congé après-midi">AM</button>
|
||
<button hx-post="/conge/{{ j.date }}/jour"
|
||
hx-swap="none"
|
||
class="btn-cg btn-jour {% if 'jour' in j.conge %}jour-on{% endif %}"
|
||
title="Journée entière">J</button>
|
||
<button hx-post="/astreinte/{{ j.date }}/toggle"
|
||
hx-swap="none"
|
||
class="btn-cg btn-as {% if j.astreinte %}as-on{% endif %}"
|
||
title="Jour d'astreinte">AS</button>
|
||
</div>
|
||
</div>
|
||
</td>
|
||
</tr>
|