From 8a7b5b6644d1412cf6ea1a0b4de92382252c2be0 Mon Sep 17 00:00:00 2001 From: "fefe.clochette" Date: Thu, 3 Sep 2026 16:15:53 +0200 Subject: [PATCH] fix css --- family-calendar.php | 19 +- includes/lang/ca.php | 7 + includes/lang/en.php | 7 + includes/lang/fr.php | 7 + modules/family-calendar/family-calendar.css | 103 +++++-- modules/family-calendar/family-calendar.js | 313 +++++++++++++++----- 6 files changed, 337 insertions(+), 119 deletions(-) diff --git a/family-calendar.php b/family-calendar.php index 5f22102..34683b7 100644 --- a/family-calendar.php +++ b/family-calendar.php @@ -85,7 +85,7 @@ $pageCss = "/modules/family-calendar/family-calendar.css"; require __DIR__ . '/header.php'; ?> -
+
@@ -422,7 +422,7 @@ require __DIR__ . '/header.php'; $parent): - $parentClass = ($index % 2 === 0) ? 'col-alex' : 'col-laia'; // Couleurs alternées + $parentClass = ($index % 2 === 0) ? 'col-p1' : 'col-p2'; $pLeaves = $leaveMatrix[$parent['id']] ?? []; $colspan = count($pLeaves) * 2; ?> @@ -433,7 +433,7 @@ require __DIR__ . '/header.php'; $parent): - $parentClass = ($index % 2 === 0) ? 'col-alex' : 'col-laia'; + $parentClass = ($index % 2 === 0) ? 'col-p1' : 'col-p2'; $pLeaves = $leaveMatrix[$parent['id']] ?? []; ?> @@ -443,7 +443,7 @@ require __DIR__ . '/header.php'; $parent): - $parentClass = ($index % 2 === 0) ? 'col-alex' : 'col-laia'; + $parentClass = ($index % 2 === 0) ? 'col-p1' : 'col-p2'; $pLeaves = $leaveMatrix[$parent['id']] ?? []; ?> @@ -482,16 +482,17 @@ require __DIR__ . '/header.php';
- $type): + foreach ($hLeaves as $type): ?>
-
+
- + $mode): diff --git a/includes/lang/ca.php b/includes/lang/ca.php index d3042c8..b05eaf4 100644 --- a/includes/lang/ca.php +++ b/includes/lang/ca.php @@ -351,6 +351,13 @@ return [ 'fc_full_year' => 'Any sencer', 'fc_custom_period' => 'Període específic...', 'fc_worked_days' => 'Treballats (Est.)', + 'fc_presence' => 'Presència', + 'fc_working_days' => 'Feiners', + 'fc_absences' => 'Abs.', + 'fc_recap_title' => 'Resum', + 'fc_worked_est' => 'Treballats (Est.)', + 'fc_invalid_dates' => 'Selecciona dates vàlides.', + 'fc_no_leaves_taken' => 'Cap permís sol·licitat.', // --- CALENDARI : PARÀMETRES (MEMBRES I VISUALITZACIÓ) --- 'fc_tab_display' => '🖥️ Visualització', diff --git a/includes/lang/en.php b/includes/lang/en.php index 9e0632a..338572a 100644 --- a/includes/lang/en.php +++ b/includes/lang/en.php @@ -352,6 +352,13 @@ return [ 'fc_full_year' => 'Full year', 'fc_custom_period' => 'Custom period...', 'fc_worked_days' => 'Worked (Est.)', + 'fc_presence' => 'Presence', + 'fc_working_days' => 'Working days', + 'fc_absences' => 'Abs.', + 'fc_recap_title' => 'Summary', + 'fc_worked_est' => 'Worked (Est.)', + 'fc_invalid_dates' => 'Please select valid dates.', + 'fc_no_leaves_taken' => 'No leave taken.', // --- CALENDAR: SETTINGS (MEMBERS & DISPLAY) --- 'fc_tab_display' => '🖥️ Display', diff --git a/includes/lang/fr.php b/includes/lang/fr.php index 5a199e5..116c170 100644 --- a/includes/lang/fr.php +++ b/includes/lang/fr.php @@ -356,6 +356,13 @@ return [ 'fc_full_year' => 'Année complète', 'fc_custom_period' => 'Période spécifique...', 'fc_worked_days' => 'Travaillés (Est.)', + 'fc_presence' => 'Présence', + 'fc_working_days' => 'J. Ouvrés', + 'fc_absences' => 'Abs.', + 'fc_recap_title' => 'Récapitulatif', + 'fc_worked_est' => 'Travaillés (Est.)', + 'fc_invalid_dates' => 'Sélectionnez des dates valides.', + 'fc_no_leaves_taken' => 'Aucun congé posé.', // --- CALENDRIER : PARAMÈTRES (MEMBRES & AFFICHAGE) --- 'fc_tab_display' => '🖥️ Affichage', diff --git a/modules/family-calendar/family-calendar.css b/modules/family-calendar/family-calendar.css index 31e232a..733dc23 100644 --- a/modules/family-calendar/family-calendar.css +++ b/modules/family-calendar/family-calendar.css @@ -10,15 +10,26 @@ #f1f5f9 8px, #f1f5f9 16px ); - --c-off-carole: #fef3c7; - --c-extra-off: #fee2e2; - --c-selected: #dbeafe; - /* Thèmes Parents (Sync Budget) */ - --bg-alex: #ecfeff; - --text-alex: #0891b2; - --bg-laia: #fffbeb; - --text-laia: #d97706; + /* Palette dynamique pour les congés intervenants */ + --fc-palette-0: #fef3c7; + --fc-palette-text-0: #b45309; + --fc-palette-1: #fee2e2; + --fc-palette-text-1: #b91c1c; + --fc-palette-2: #dbeafe; + --fc-palette-text-2: #1d4ed8; + --fc-palette-3: #dcfce7; + --fc-palette-text-3: #15803d; + --fc-palette-4: #f3e8ff; + --fc-palette-text-4: #7e22ce; + --fc-palette-5: #ffedd5; + --fc-palette-text-5: #c2410c; + --fc-palette-6: #ccfbf1; + --fc-palette-text-6: #0f766e; + --fc-palette-7: #fce7f3; + --fc-palette-text-7: #be185d; + + --c-selected: #dbeafe; /* Rappel des variables Global Design System pour cohérence */ --pf-primary: #3b82f6; @@ -301,11 +312,30 @@ background: var(--c-public-holiday) !important; font-weight: 700; } -.fc-day--off-carole { - background: var(--c-off-carole) !important; + +.fc-bg-palette-0 { + background: var(--fc-palette-0) !important; } -.fc-day--extra-off-carole { - background: var(--c-extra-off) !important; +.fc-bg-palette-1 { + background: var(--fc-palette-1) !important; +} +.fc-bg-palette-2 { + background: var(--fc-palette-2) !important; +} +.fc-bg-palette-3 { + background: var(--fc-palette-3) !important; +} +.fc-bg-palette-4 { + background: var(--fc-palette-4) !important; +} +.fc-bg-palette-5 { + background: var(--fc-palette-5) !important; +} +.fc-bg-palette-6 { + background: var(--fc-palette-6) !important; +} +.fc-bg-palette-7 { + background: var(--fc-palette-7) !important; } .fc-day--selected { @@ -314,8 +344,14 @@ z-index: 5; } -.fc-day--off-carole.fc-day--school-holiday, -.fc-day--extra-off-carole.fc-day--school-holiday, +.fc-bg-palette-0.fc-day--school-holiday, +.fc-bg-palette-1.fc-day--school-holiday, +.fc-bg-palette-2.fc-day--school-holiday, +.fc-bg-palette-3.fc-day--school-holiday, +.fc-bg-palette-4.fc-day--school-holiday, +.fc-bg-palette-5.fc-day--school-holiday, +.fc-bg-palette-6.fc-day--school-holiday, +.fc-bg-palette-7.fc-day--school-holiday, .fc-day--centre.fc-day--school-holiday, .fc-day--avis.fc-day--school-holiday { box-shadow: inset 0 -8px 0 0 var(--c-school-holiday) !important; @@ -409,15 +445,23 @@ z-index: 20; } -.col-alex.header-group, -.col-alex-sub { - background: var(--bg-alex) !important; - color: var(--text-alex) !important; +.col-p1.header-group, +.col-p1-sub { + background: color-mix( + in srgb, + var(--p1-main, #0891b2) 8%, + #ffffff + ) !important; + color: color-mix(in srgb, var(--p1-main, #0891b2) 85%, #000000) !important; } -.col-laia.header-group, -.col-laia-sub { - background: var(--bg-laia) !important; - color: var(--text-laia) !important; +.col-p2.header-group, +.col-p2-sub { + background: color-mix( + in srgb, + var(--p2-main, #f59e0b) 8%, + #ffffff + ) !important; + color: color-mix(in srgb, var(--p2-main, #f59e0b) 85%, #000000) !important; } #planningTable tbody td { @@ -448,10 +492,10 @@ td.col-day { } th.col-total, td.col-total, -th.col-alex-sub, -td.col-alex-sub, -th.col-laia-sub, -td.col-laia-sub { +th.col-p1-sub, +td.col-p1-sub, +th.col-p2-sub, +td.col-p2-sub { width: 32px !important; min-width: 32px !important; max-width: 32px !important; @@ -594,12 +638,7 @@ td.col-laia-sub { .fc-legend-public-holiday { background: var(--c-public-holiday); } -.fc-legend-off-carole { - background: var(--c-off-carole); -} -.fc-legend-extra-off-carole { - background: var(--c-extra-off); -} + .fc-legend-centre::after { content: "🏫"; } diff --git a/modules/family-calendar/family-calendar.js b/modules/family-calendar/family-calendar.js index ee6d3dc..ba02891 100644 --- a/modules/family-calendar/family-calendar.js +++ b/modules/family-calendar/family-calendar.js @@ -682,6 +682,8 @@ document.addEventListener("DOMContentLoaded", () => { this.leaves = []; this.weeks = []; + this.helperColorMap = {}; + this.parents = []; this.kids = []; this.helpers = []; @@ -729,6 +731,17 @@ document.addEventListener("DOMContentLoaded", () => { this.careModes = res.data.foyer.care_modes || []; this.leaveMatrix = res.data.leaves || {}; + let colorCounter = 0; + this.helpers.forEach((h) => { + const hLeaves = + this.leaveMatrix[h.id] || this.leaveMatrix[Number(h.id)] || []; + hLeaves.forEach((lt) => { + const typeName = typeof lt === "object" ? lt.type : lt; + this.helperColorMap[`${h.id}_${typeName}`] = colorCounter % 8; + colorCounter++; + }); + }); + const settings = res.data.calendar_settings || {}; if (settings.calendar_default_view) { this.viewMode = settings.calendar_default_view; @@ -902,14 +915,11 @@ document.addEventListener("DOMContentLoaded", () => { const helperEvents = [...this.leaves, ...this.events] .filter((e) => { const eDate = e.leave_date || e.date; - const eType = e.leave_type || e.type; - const isOldOff = - eType === "HELPER_OFF" || - eType === "HELPER_EXTRA" || - eType.includes("OFF"); + const eType = String(e.leave_type || e.type).toUpperCase(); + const isOldEvent = eType.includes("OFF") || eType.includes("EXTRA"); - if (e.person_id != h.id) return false; - if (!e.leave_date && !isOldOff) return false; + if (parseInt(e.person_id) !== parseInt(h.id)) return false; + if (!e.leave_date && !isOldEvent) return false; // Ignore les événements standards sauf l'historique if (isCustom && !hasValidDates) return false; return eDate >= startDateStr && eDate <= endDateStr; @@ -929,12 +939,11 @@ document.addEventListener("DOMContentLoaded", () => { let totalLeavesTaken = 0; helperEvents.forEach((e) => { - let mappedType = - e.type === "HELPER_OFF" - ? "OFF" - : e.type === "HELPER_EXTRA" - ? "EXTRA" - : e.type; + const rawType = String(e.type).toUpperCase(); + let mappedType = e.type; + if (rawType.includes("EXTRA")) mappedType = "EXTRA"; + else if (rawType.includes("OFF")) mappedType = "OFF"; + if (totals[mappedType] === undefined) totals[mappedType] = 0; totals[mappedType] += e.duration; totalLeavesTaken += e.duration; @@ -967,22 +976,22 @@ document.addEventListener("DOMContentLoaded", () => { const isCustomDisplay = isCustom ? "flex" : "none"; const isYearDisplay = isCustom ? "none" : "block"; - // --- GÉNÉRATION DU HTML (Design Ultra-Compact + Micro Pilules) --- + // --- GÉNÉRATION DU HTML (Design Ultra-Compact + Micro Pilules + Flexbox Corrigé) --- let cardHtml = `
-
+
📅 ${h.name} - Récapitulatif + ${window.I18N?.fc_recap_title || "Récapitulatif"}
- Travaillés (Est.) + ${window.I18N?.fc_worked_est || "Travaillés (Est.)"} ${hasValidDates ? workedDays : "-"} j
@@ -990,7 +999,7 @@ document.addEventListener("DOMContentLoaded", () => {
`; if (!hasValidDates && isCustom) { - cardHtml += `
Sélectionnez des dates valides.
`; + cardHtml += `
${window.I18N?.fc_invalid_dates || "Sélectionnez des dates valides."}
`; } else { let hasLeaves = false; for (const [t, val] of Object.entries(totals)) { @@ -1001,22 +1010,31 @@ document.addEventListener("DOMContentLoaded", () => { ) ) { hasLeaves = true; - let label = - t === "HELPER_OFF" ? "Off" : t === "HELPER_EXTRA" ? "Extra" : t; + const rawT = String(t).toUpperCase(); + let label = t; + if (rawT.includes("EXTRA")) + label = window.I18N?.btn_extra || "Extra"; + else if (rawT.includes("OFF")) + label = window.I18N?.btn_off || "Off"; + + // 🎨 INJECTION DYNAMIQUE DE LA COULEUR CSS (La même que le calendrier !) + const colorIndex = this.helperColorMap[`${h.id}_${t}`] ?? 0; + const borderColor = `var(--fc-palette-text-${colorIndex})`; + cardHtml += ` -
+
${label} ${val}j
`; } } if (!hasLeaves) - cardHtml += `
Aucun congé posé.
`; + cardHtml += `
${window.I18N?.fc_no_leaves_taken || "Aucun congé posé."}
`; } cardHtml += `
-
+
@@ -1260,15 +1278,28 @@ document.addEventListener("DOMContentLoaded", () => { const dur = parseFloat(e.duration) || 1; - if (e.type === "CHILD_SICK") + if (e.type === "CHILD_SICK") { w.totals["sick_" + e.person_id] = (w.totals["sick_" + e.person_id] || 0) + dur; - if (e.type === "HELPER_OFF") - w.totals["off_" + e.person_id] = - (w.totals["off_" + e.person_id] || 0) + dur; - if (e.type === "HELPER_EXTRA") - w.totals["extra_" + e.person_id] = - (w.totals["extra_" + e.person_id] || 0) + dur; + } else { + const rawType = String(e.type).toUpperCase(); + const isOldHelperEvent = + rawType.includes("OFF") || rawType.includes("EXTRA"); + + if (isOldHelperEvent) { + const pId = this.helpers.some( + (h) => parseInt(h.id) === parseInt(e.person_id), + ) + ? e.person_id + : this.helpers[0]?.id || 0; + let mappedType = e.type; + if (rawType.includes("EXTRA")) mappedType = "EXTRA"; + else if (rawType.includes("OFF")) mappedType = "OFF"; + + w.totals[`leave_${pId}_${mappedType}`] = + (w.totals[`leave_${pId}_${mappedType}`] || 0) + dur; + } + } // Modes de garde dynamiques if (upperCareModes.includes(e.type)) { @@ -1448,8 +1479,7 @@ document.addEventListener("DOMContentLoaded", () => { this.planningBody.innerHTML = ""; if (!this.weeks || this.weeks.length === 0) { - this.planningBody.innerHTML = - "Aucune donnée pour cette année scolaire."; + this.planningBody.innerHTML = `${window.I18N?.["fc_no_data"] || "Aucune donnée pour cette année scolaire."}`; return; } @@ -1466,33 +1496,39 @@ document.addEventListener("DOMContentLoaded", () => { const upperCareModes = (this.careModes || []).map((m) => String(m).toUpperCase(), ); + const helperIds = (this.helpers || []).map((h) => parseInt(h.id)); this.weeks.forEach((w, idx) => { const tr = document.createElement("tr"); tr.setAttribute("data-month", w.monthKey); - if (idx === 0 || this.weeks[idx - 1].monthKey !== w.monthKey) + if (idx === 0 || this.weeks[idx - 1].monthKey !== w.monthKey) { tr.classList.add("fc-month-first-week-row"); + } if ( idx === this.weeks.length - 1 || this.weeks[idx + 1].monthKey !== w.monthKey - ) + ) { tr.classList.add("fc-month-last-week-row"); - - if (!processedMonths[w.monthKey]) { - processedMonths[w.monthKey] = true; - const td = document.createElement("td"); - td.className = "col-month col-sticky-mois"; - td.innerHTML = `${w.monthName || ""}`; - td.rowSpan = monthSpans[w.monthKey]; - tr.appendChild(td); } + // 1. Colonne Sticky MOIS + if (!processedMonths[w.monthKey]) { + processedMonths[w.monthKey] = true; + const tdMonth = document.createElement("td"); + tdMonth.className = "col-month col-sticky-mois rotated-text"; + tdMonth.innerHTML = `${w.monthName || ""}`; + tdMonth.rowSpan = monthSpans[w.monthKey]; + tr.appendChild(tdMonth); + } + + // 2. Colonne Sticky SEMAINE const tdW = document.createElement("td"); - tdW.className = "col-month col-sticky-sem"; - tdW.textContent = w.weekLabel || ""; + tdW.className = "col-month col-sticky-sem rotated-text"; + tdW.innerHTML = `${w.weekLabel || ""}`; tr.appendChild(tdW); + // 3. Jours de la semaine (Lundi à Vendredi) ["mon", "tue", "wed", "thu", "fri"].forEach((d) => { const td = document.createElement("td"); const dateObj = w.dayDates[d]; @@ -1503,7 +1539,11 @@ document.addEventListener("DOMContentLoaded", () => { td.className = "col-day"; const events = w.dayFlags?.[d]?.events || []; + const dayLeaves = (this.leaves || []).filter( + (l) => (l.leave_date || l.date) === iso, + ); + // A. Application des classes de coloration de fond CSS events.forEach((evt) => { if (evt.type === "PUBLIC_HOLIDAY") td.classList.add("fc-day--public-holiday"); @@ -1513,23 +1553,67 @@ document.addEventListener("DOMContentLoaded", () => { td.classList.add("fc-day--has-guard"); }); + // Détection dynamique et globale des congés de l'intervenant + let appliedColorIndex = -1; + + const helperLeaf = dayLeaves.find((l) => + helperIds.includes(parseInt(l.person_id)), + ); + if (helperLeaf) { + appliedColorIndex = + this.helperColorMap[ + `${helperLeaf.person_id}_${helperLeaf.leave_type}` + ]; + } else { + const helperEvent = events.find( + (e) => + helperIds.includes(parseInt(e.person_id)) || + String(e.type).toUpperCase().includes("OFF") || + String(e.type).toUpperCase().includes("EXTRA"), + ); + + if (helperEvent) { + const pId = helperIds.includes(parseInt(helperEvent.person_id)) + ? helperEvent.person_id + : helperIds[0]; + const rawType = String(helperEvent.type).toUpperCase(); + + let mappedType = helperEvent.type; + if (rawType.includes("EXTRA")) mappedType = "EXTRA"; + else if (rawType.includes("OFF")) mappedType = "OFF"; + + appliedColorIndex = + this.helperColorMap[`${pId}_${mappedType}`] ?? + this.helperColorMap[`${pId}_${helperEvent.type}`] ?? + 0; + } + } + + if (appliedColorIndex !== -1 && appliedColorIndex !== undefined) { + td.classList.add(`fc-bg-palette-${appliedColorIndex}`); + } + + // B. Contenu HTML de la cellule (Numéro du jour, Icônes de garde, Maladie Enfants, Initiales Parents) let content = `
${String(dateObj.getDate()).padStart(2, "0")}`; + // Icônes des modes de garde let iconsHtml = `
`; events.forEach((evt) => { if (upperCareModes.includes(evt.type)) { const modeName = String(evt.type).toLowerCase(); - if (modeName === "avis") + if (modeName === "avis") { iconsHtml += ``; - else if (modeName === "centre") + } else if (modeName === "centre") { iconsHtml += `🏫`; - else + } else { iconsHtml += `${modeName.substring(0, 3)}`; + } } }); content += iconsHtml + `
`; + // Icônes Enfant Malade let sickHtml = `
`; events.forEach((evt) => { if (evt.type === "CHILD_SICK") { @@ -1543,11 +1627,9 @@ document.addEventListener("DOMContentLoaded", () => { }); content += sickHtml + `
`; - const dayLeaves = (this.leaves || []).filter( - (l) => l.leave_date === iso || l.date === iso, - ); + // Initiales des Parents en congé if (dayLeaves.length) { - let html = `
`; + let parentLeavesHtml = `
`; (this.parents || []).forEach((person) => { if ( dayLeaves.some( @@ -1555,16 +1637,17 @@ document.addEventListener("DOMContentLoaded", () => { parseInt(l.person_id || l.person) === parseInt(person.id), ) ) { - html += `${String(person.name).charAt(0).toUpperCase()}`; + parentLeavesHtml += `${String(person.name).charAt(0).toUpperCase()}`; } }); - content += html + `
`; + content += parentLeavesHtml + `
`; } + td.innerHTML = content + `
`; tr.appendChild(td); }); - // 1. Congés intervenant (Dynamiques) + // 4. Totaux : Congés de l'intervenant / Helper (Nombres bruts) (this.helpers || []).forEach((h) => { const hLeaves = this.leaveMatrix[h.id] || this.leaveMatrix[Number(h.id)] || []; @@ -1572,33 +1655,42 @@ document.addEventListener("DOMContentLoaded", () => { const typeName = typeof lt === "object" ? lt.type : lt; const td = document.createElement("td"); td.className = "col-total"; - td.textContent = fmt(w.totals[`leave_${h.id}_${typeName}`] || 0); + + const val = w.totals[`leave_${h.id}_${typeName}`] || 0; + if (val > 0) { + td.textContent = fmt(val); + } else { + td.textContent = ""; + } tr.appendChild(td); }); }); - // 2. Modes de garde (On ignore Nounou si Helper présent) + // 5. Totaux : Modes de garde (On masque "Nounou" si un intervenant existe) (this.careModes || []).forEach((mode) => { if (mode.toLowerCase() === "nounou" && this.helpers.length > 0) return; const td = document.createElement("td"); td.className = "col-total"; - td.textContent = fmt(w.totals["mode_" + mode] || 0); + const val = w.totals["mode_" + mode] || 0; + td.textContent = fmt(val); tr.appendChild(td); }); - // 3. Maladie enfants + // 6. Totaux : Maladie par enfant (this.kids || []).forEach((kid) => { const td = document.createElement("td"); td.className = "col-total"; - td.textContent = fmt(w.totals["sick_" + kid.id] || 0); + const val = w.totals["sick_" + kid.id] || 0; + td.textContent = fmt(val); tr.appendChild(td); }); + // 7. Colonnes de suivi des soldes mensuels (Parents : Av. / Use) if (!processedLeavesCols[w.monthKey]) { processedLeavesCols[w.monthKey] = true; (this.parents || []).forEach((parent, index) => { - const cssPrefix = index % 2 === 0 ? "col-alex" : "col-laia"; + const cssPrefix = index % 2 === 0 ? "col-p1" : "col-p2"; const matrix = this.leaveMatrix[String(parent.id)] || this.leaveMatrix[Number(parent.id)] || @@ -1672,13 +1764,49 @@ document.addEventListener("DOMContentLoaded", () => { cls += " fc-day--school-holiday"; if (dayEvts.some((e) => e.type === "PUBLIC_HOLIDAY")) cls += " fc-day--public-holiday"; - if (dayEvts.some((e) => e.type === "HELPER_OFF")) - cls += " fc-day--off-carole"; - if (dayEvts.some((e) => e.type === "HELPER_EXTRA")) - cls += " fc-day--extra-off-carole"; if (dayEvts.some((e) => upperCareModes.includes(e.type))) cls += " fc-day--has-guard"; + const helperIds = (this.helpers || []).map((h) => parseInt(h.id)); + const dayLeaves = this.leaves.filter((l) => l.leave_date === iso); + + let appliedColorIndex = -1; + const helperLeaf = dayLeaves.find((l) => + helperIds.includes(parseInt(l.person_id)), + ); + + if (helperLeaf) { + appliedColorIndex = + this.helperColorMap[ + `${helperLeaf.person_id}_${helperLeaf.leave_type}` + ]; + } else { + const helperEvent = dayEvts.find( + (e) => + helperIds.includes(parseInt(e.person_id)) || + e.type === "HELPER_OFF" || + e.type === "HELPER_EXTRA", + ); + if (helperEvent) { + const mappedType = + helperEvent.type === "HELPER_OFF" + ? "OFF" + : helperEvent.type === "HELPER_EXTRA" + ? "EXTRA" + : helperEvent.type; + appliedColorIndex = + this.helperColorMap[`${helperEvent.person_id}_${mappedType}`] ?? + this.helperColorMap[ + `${helperEvent.person_id}_${helperEvent.type}` + ] ?? + 0; + } + } + + if (appliedColorIndex !== -1 && appliedColorIndex !== undefined) { + cls += ` fc-bg-palette-${appliedColorIndex}`; + } + let content = `
${d}`; let iconsHtml = `
`; @@ -1708,7 +1836,6 @@ document.addEventListener("DOMContentLoaded", () => { }); content += sickHtml + `
`; - const dayLeaves = this.leaves.filter((l) => l.leave_date === iso); if (dayLeaves.length) { content += `
`; this.parents.forEach((parent) => { @@ -1748,10 +1875,11 @@ document.addEventListener("DOMContentLoaded", () => { // 2. Boucler sur chaque enfant concerné pour un calcul individuel nounouKids.forEach((kid) => { let workingDays = 0; - let off = 0; - let extra = 0; + let absencesNounou = 0; let sick = 0; + const helperIds = this.helpers.map((h) => parseInt(h.id)); + for (let d = 1; d <= daysInMonth; d++) { const dateObj = new Date(year, month, d); const dayOfWeek = dateObj.getDay(); @@ -1768,12 +1896,20 @@ document.addEventListener("DOMContentLoaded", () => { workingDays += 1; const dayEvents = this.events.filter((e) => e.date === iso); + const dayLeaves = this.leaves.filter((l) => l.leave_date === iso); dayEvents.forEach((e) => { const dur = parseFloat(e.duration) || 1; + const rawType = String(e.type).toUpperCase(); - if (e.type === "HELPER_OFF") off += dur; - if (e.type === "HELPER_EXTRA") extra += dur; + // Si c'est un vieil événement historisé OFF/EXTRA + if ( + rawType.includes("OFF") || + rawType.includes("EXTRA") || + helperIds.includes(parseInt(e.person_id)) + ) { + absencesNounou += dur; + } // On vérifie que la maladie concerne BIEN cet enfant précis ! if ( @@ -1783,23 +1919,43 @@ document.addEventListener("DOMContentLoaded", () => { sick += dur; } }); + + // Prise en compte des nouveaux congés propres aux intervenants + dayLeaves.forEach((l) => { + const dur = parseFloat(l.duration) || 1; + if (helperIds.includes(parseInt(l.person_id))) { + absencesNounou += dur; + } + }); } - // Calcul final strict : Jours ouvrés - Maladie (de l'enfant) - Extra - Off - const presence = Math.max(0, workingDays - sick - extra - off); + // Récupération dynamique du nom de l'intervenant avec i18n + const fallbackHelper = window.I18N?.fc_role_helper || "Intervenant"; + const helperName = + this.helpers && this.helpers.length > 0 + ? this.helpers.map((h) => h.name).join(" & ") + : fallbackHelper; + + // Calcul final strict : Jours ouvrés - Maladie (de l'enfant) - Absences Nounou + const presence = Math.max(0, workingDays - sick - absencesNounou); + + // Textes traduits + const trPresence = window.I18N?.fc_presence || "Présence"; + const trWorking = window.I18N?.fc_working_days || "Ouvrés"; + const trAbs = window.I18N?.fc_absences || "Abs."; + const trSick = window.I18N?.fc_menu_sick || "Maladie"; // Rendu HTML individuel html += `
- 👧👦 Présence ${kid.name} (Nounou) + 👧👦 ${trPresence} ${kid.name} (${helperName})
-
Ouvrés ${workingDays} j
-
Off ${parseFloat(off.toFixed(1))} j
-
Extra ${parseFloat(extra.toFixed(1))} j
-
Maladie ${parseFloat(sick.toFixed(1))} j
-
Présence ${parseFloat(presence.toFixed(1))} j
+
${trWorking} ${workingDays} j
+
${trAbs} ${helperName} ${parseFloat(absencesNounou.toFixed(1))} j
+
${trSick} ${parseFloat(sick.toFixed(1))} j
+
${trPresence} ${parseFloat(presence.toFixed(1))} j
`; @@ -2355,10 +2511,11 @@ document.addEventListener("DOMContentLoaded", () => { const hLeaves = this.leaveMatrix[h.id] || this.leaveMatrix[Number(h.id)] || []; if (hLeaves.length > 0) { - const hColor = h.color || "var(--warning)"; html += `
${buildHeader(h.name, "clear-leaves-person", null, h.id)}
`; hLeaves.forEach((lt) => { const lType = typeof lt === "object" ? lt.type : lt; + const pIdx = this.helperColorMap[`${h.id}_${lType}`] ?? 0; + const hColor = `var(--fc-palette-text-${pIdx})`; html += ``; }); html += `
`;