Répartit les préconisations de rattrapage sur les demi-journées restantes de la semaine

Au lieu de reporter tout le manque horaire sur la sortie du jour courant, le calcul
distribue désormais le retard à parts égales sur chaque demi-journée non traitée
(aujourd'hui et jours à venir), avec un plafond de sécurité si le rattrapage dépasse
minuit. La table affiche une cible par demi-journée (matin/après-midi) et le bandeau
de soldes indique le reste à faire et le nombre de demi-journées restantes.
This commit is contained in:
Antoine
2026-07-17 23:02:07 +02:00
parent c2d7d0e3ac
commit e6b5173018
7 changed files with 138 additions and 99 deletions

View File

@ -69,18 +69,10 @@
<td class="col-cible">
<span id="calc-{{ j.date }}-cible">
{%- if not j.is_complete -%}
{%- if j.entree_cible -%}
{%- if 'aprem' in j.conge -%}
<span class="cible-num">{{ j.entree_cible }}→{{ plages.matin_fin }}</span>
{%- else -%}
<span class="cible-num">{{ j.entree_cible }}→{{ plages.aprem_fin }}</span>
{%- endif -%}
{%- elif j.sortie_cible -%}
<span class="cible-num">{{ j.sortie_cible }}</span>
{%- else -%}
<span class="delta-zero"></span>
{%- endif %}
{%- if j.cible_matin or j.cible_aprem -%}
{%- if j.cible_matin -%}<span class="cible-num">M {{ 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 }}</span>{%- endif -%}
{%- else -%}
<span class="delta-zero"></span>
{%- endif %}

View File

@ -15,4 +15,19 @@
</div>
</div>
</div>
{% if result.slots_restants > 0 %}
<div class="reste-info">
{% if result.extra_min > 0 %}
Reste à faire : <strong>{{ result.reste }}</strong>
sur {{ result.slots_restants }} demi-journée{{ 's' if result.slots_restants > 1 else '' }} restante{{ 's' if result.slots_restants > 1 else '' }}
— à rattraper : <strong class="reste-extra">+{{ result.extra }}</strong> (~+{{ result.moyenne_extra }} chacune)
{% elif result.reste_min > 0 %}
Reste à faire : <strong>{{ result.reste }}</strong>
sur {{ result.slots_restants }} demi-journée{{ 's' if result.slots_restants > 1 else '' }} restante{{ 's' if result.slots_restants > 1 else '' }}
— le rythme habituel suffit, rien à rattraper.
{% else %}
Vous êtes à jour ou en avance — rien à rattraper cette semaine.
{% endif %}
</div>
{% endif %}
</div>

View File

@ -162,6 +162,16 @@
.solde-num.neg { color: var(--neg); }
.solde-num.neutral { color: var(--text); }
.reste-info {
padding: .6rem 1.25rem;
border-top: 1px solid var(--rule);
background: var(--ground);
font-size: 12px;
color: var(--muted);
}
.reste-info strong { color: var(--text); font-family: var(--mono); font-weight: 500; }
.reste-info strong.reste-extra { color: var(--neg); }
/* ── Table ── */
.table-section { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table {

View File

@ -218,12 +218,15 @@
}
function getCible() {
var el = document.querySelector('#calc-' + todayStr() + '-cible .cible-num');
if (!el) return null;
var txt = el.textContent.trim();
// Formats: "17:13" ou "16:15→17:00" — on veut l'heure de DÉPART (dernière)
var time = txt.indexOf('→') >= 0 ? txt.split('→').pop().trim() : txt;
return /^\d{2}:\d{2}$/.test(time) ? time : null;
var wrap = document.getElementById('calc-' + todayStr() + '-cible');
if (!wrap) return null;
var nums = wrap.querySelectorAll('.cible-num');
if (!nums.length) return null;
// Plusieurs cibles possibles (matin + après-midi) : on alerte sur la dernière,
// qui correspond au départ effectif de la journée.
var txt = nums[nums.length - 1].textContent.trim();
var m = txt.match(/(\d{2}:\d{2})$/);
return m ? m[1] : null;
}
function nowMin() {