{% extends 'base.html.twig' %} {# ══════════════════════════════════════════════════════════════════ Template — Planning mensuel ══════════════════════════════════════════════════════════════════ Affiche tous les employés actifs en lignes (3 sous-lignes chacun) et les jours du mois en colonnes, à la manière du Google Sheet. Pour chaque employé / chaque jour : - Ligne 1 : prix de la prestation (admins uniquement) - Ligne 2 : observation → Pointage.notes à la sauvegarde - Ligne 3 : site → Pointage.chantier à la sauvegarde Droits : - ROLE_USER : voit tout sauf le prix, lecture seule - ROLE_ADMIN : voit et modifie tout (prix, statut, observation, site) Variables attendues : users : User[] — employés actifs triés par nom jours : array[] — [{date, dateStr, dow, isWeekend, isFerie}] planning : array — [userId][dateStr] => PlanningJour|null year : int month : int isAdmin : bool statuts : StatutPointage[] ══════════════════════════════════════════════════════════════════ #} {% block title %}Planning — {{ month|mois_nom }} {{ year }}{% endblock %} {% block page_title %}Planning mensuel{% endblock %} {% set moisNoms = {1:'Janvier',2:'Fevrier',3:'Mars',4:'Avril',5:'Mai',6:'Juin', 7:'Juillet',8:'Aout',9:'Septembre',10:'Octobre',11:'Novembre',12:'Decembre'} %} {% set jourCourtsFr = {'1':'L','2':'M','3':'M','4':'J','5':'V','6':'S','7':'D'} %} {% block body %} {# ── Navigation mois ── #}
{% set prevMonth = month - 1 %}{% set prevYear = year %} {% if prevMonth < 1 %}{% set prevMonth = 12 %}{% set prevYear = year - 1 %}{% endif %} {% set nextMonth = month + 1 %}{% set nextYear = year %} {% if nextMonth > 12 %}{% set nextMonth = 1 %}{% set nextYear = year + 1 %}{% endif %} {% set navRoute = canEdit ? 'app_planning' : 'app_planning_view' %}
{{ moisNoms[month] }} {{ year }}
Exporter PDF
{# ── En-tête visible uniquement à l'impression ── #}
Planning — {{ moisNoms[month] }} {{ year }} Culture Controle — Imprimé le {{ "now"|date("d/m/Y") }}
{# ── Tableau planning ── #}
{# Colgroup : définit les largeurs de façon autoritaire pour table-layout:fixed #} {% for jour in jours %}{% endfor %} {# ── En-tête jours ── #} {# Ligne 0 : numéros de semaine ISO (cellules fusionnées sur les jours de la semaine) #} {% set weekGroups = [] %} {% set currentWeek = null %} {% set currentCount = 0 %} {% for jour in jours %} {% set w = jour.date|date('W') %} {% if w != currentWeek %} {% if currentWeek is not null %} {% set weekGroups = weekGroups|merge([{week: currentWeek, count: currentCount}]) %} {% endif %} {% set currentWeek = w %} {% set currentCount = 1 %} {% else %} {% set currentCount = currentCount + 1 %} {% endif %} {% endfor %} {% if currentWeek is not null %} {% set weekGroups = weekGroups|merge([{week: currentWeek, count: currentCount}]) %} {% endif %} {% for wg in weekGroups %} {% endfor %} {# Ligne 1 : noms courts des jours #} {% for jour in jours %} {% endfor %} {# Ligne 2 : numéros des jours #} {% for jour in jours %} {% endfor %} {# ── Corps — un bloc de 3 lignes par employé ── #} {% for user in users %} {# Calculer le statut par défaut de chaque jour pour cet employé #} {# ── Ligne 1 : Prix (admin) ── #} {% for jour in jours %} {% set pj = planning[user.id][jour.dateStr] ?? null %} {% set statutVal = pj ? pj.statut.value : (jour.isWeekend ? 'weekend' : (jour.isFerie ? 'ferie' : 'travaille')) %} {% set couleur = (pj and pj.couleur and statutVal == 'travaille') ? pj.couleur : null %} {% endfor %} {# ── Ligne 2 : Lieu/Site ── #} {% for jour in jours %} {% set pj = planning[user.id][jour.dateStr] ?? null %} {% set statutVal = pj ? pj.statut.value : (jour.isWeekend ? 'weekend' : (jour.isFerie ? 'ferie' : 'travaille')) %} {% set couleur = (pj and pj.couleur and statutVal == 'travaille') ? pj.couleur : null %} {% endfor %} {# ── Ligne 3 : Observation ── #} {% for jour in jours %} {% set pj = planning[user.id][jour.dateStr] ?? null %} {% set statutVal = pj ? pj.statut.value : (jour.isWeekend ? 'weekend' : (jour.isFerie ? 'ferie' : 'travaille')) %} {% set couleur = (pj and pj.couleur and statutVal == 'travaille') ? pj.couleur : null %} {% endfor %} {# Ligne séparateur entre employés #} {% else %} {% endfor %}
Employé S{{ wg.week }}
{{ jourCourtsFr[jour.dow] }}
{{ jour.date|date('d') }}
{{ user.nomComplet }}
{% if isAdmin %}Prix{% endif %} {% if canEdit %} {# Statut select — visible uniquement dans la ligne prix #} {# Texte du statut affiché uniquement à l'impression (masqué à l'écran) #} {% for s in statuts %}{% if s.value == statutVal %}{{ s.label }}{% endif %}{% endfor %}
{% elseif isAdmin %} {# Admin lecture seule : statut + prix #} {{ pj ? pj.statut.label : (jour.isWeekend ? 'Week-end' : (jour.isFerie ? 'Férié' : '')) }} {% if pj and pj.prix is not null %}{{ pj.prix }} €{% endif %} {% else %} {# Utilisateur : statut visible, prix masqué #} {{ pj ? pj.statut.label : (jour.isWeekend ? 'Week-end' : (jour.isFerie ? 'Férié' : '')) }} {% endif %}
Lieu {% if canEdit %} {{ pj ? (pj.site ?? '') : '' }} {% else %} {{ pj ? (pj.site ?? '') : '' }} {% endif %}
Obs {% if canEdit %} {{ pj ? (pj.observation ?? '') : '' }} {% else %} {{ pj ? (pj.observation ?? '') : '' }} {% endif %}
Aucun employé actif.
{# Bouton flottant sauvegarde #} {% if canEdit %} {% endif %} {% endblock %} {% block javascripts %} {% endblock %}