From 87995be91d58078551f4c9a97bfd4d33597ba1d7 Mon Sep 17 00:00:00 2001 From: "fefe.clochette" Date: Mon, 8 Dec 2025 17:46:31 +0100 Subject: [PATCH] Auto-commit for deploy to production - 2025-12-08 17:46:31 --- assets/js/family-calendar.js | 357 ++++++++++++++++++++++++----------- family-calendar.php | 35 +++- 2 files changed, 274 insertions(+), 118 deletions(-) diff --git a/assets/js/family-calendar.js b/assets/js/family-calendar.js index 5c8f5d3..f390c0f 100644 --- a/assets/js/family-calendar.js +++ b/assets/js/family-calendar.js @@ -1,48 +1,128 @@ // assets/js/family-calendar.js -const weeks = [ - { - month: "September", - code: "W36", - dates: "01/09 - 07/09", - caroleOffDays: 0, - isSchoolHoliday: false, - isBankHoliday: false, - alex: { cp: 0, rtt: 0, ja: 0 }, - laia: { cp: 0, rtt: 0, ja: 0 }, - }, - { - month: "September", - code: "W38", - dates: "15/09 - 21/09", - caroleOffDays: 2, - isSchoolHoliday: false, - isBankHoliday: false, - alex: { cp: 0, rtt: 0, ja: 0 }, - laia: { cp: 0, rtt: 0, ja: 0 }, - }, - { - month: "October", - code: "W40", - dates: "29/09 - 05/10", - caroleOffDays: 0, - isSchoolHoliday: false, - isBankHoliday: false, - alex: { cp: 0, rtt: 0, ja: 0 }, - laia: { cp: 0, rtt: 0, ja: 0 }, - }, - { - month: "August", - code: "W32", - dates: "03/08 - 09/08", - caroleOffDays: 5, - isSchoolHoliday: true, - isBankHoliday: false, - alex: { cp: 0, rtt: 0, ja: 0 }, - laia: { cp: 0, rtt: 0, ja: 0 }, - }, - // TODO: compléter le reste des semaines W36 → W35 -]; +// === 1. Utilitaires dates === + +/** + * Formate une Date en "dd/mm". + */ +function formatDayMonth(date) { + const d = String(date.getDate()).padStart(2, "0"); + const m = String(date.getMonth() + 1).padStart(2, "0"); + return `${d}/${m}`; +} + +/** + * Retourne le nom de mois en français à partir du monthIndex JS (0..11). + */ +function getMonthNameFr(monthIndex) { + const map = { + 0: "Janvier", + 1: "Fevrier", + 2: "Mars", + 3: "Avril", + 4: "Mai", + 5: "Juin", + 6: "Juillet", + 7: "Aout", + 8: "Septembre", + 9: "Octobre", + 10: "Novembre", + 11: "Decembre", + }; + return map[monthIndex] || ""; +} + +/** + * Genere les semaines de la 1ere semaine de septembre 2025 + * a la derniere semaine d'aout 2026. + * Chaque element contient: + * - monthKey (ex: "2025-09") + * - monthName (ex: "Septembre") + * - weekLabel (W1, W2, ...) + * - days: { mon, tue, wed, thu, fri } en "dd/mm" + * - offCarole, extraOffCarole, centre, avis + * - alex: { total, detail } + * - laia: { total, detail } + */ +function generateWeeks() { + const weeks = []; + + const start = new Date(2025, 8, 1); // 1er septembre 2025 (mois 8 car 0-based) + const end = new Date(2026, 7, 31); // 31 aout 2026 (mois 7) + + let current = new Date(start); + + // se placer sur le premier lundi >= 1er septembre 2025 + while (current.getDay() !== 1) { + // 1 = lundi + current.setDate(current.getDate() + 1); + } + + let weekCount = 1; + + while (current <= end) { + const monday = new Date(current); + const tuesday = new Date(current); + tuesday.setDate(monday.getDate() + 1); + const wednesday = new Date(current); + wednesday.setDate(monday.getDate() + 2); + const thursday = new Date(current); + thursday.setDate(monday.getDate() + 3); + const friday = new Date(current); + friday.setDate(monday.getDate() + 4); + + const monthIndex = monday.getMonth(); + const year = monday.getFullYear(); + const monthKey = `${year}-${String(monthIndex + 1).padStart(2, "0")}`; + const monthName = getMonthNameFr(monthIndex); + + weeks.push({ + monthKey, + monthName, + weekLabel: `W${weekCount}`, + days: { + mon: formatDayMonth(monday), + tue: formatDayMonth(tuesday), + wed: formatDayMonth(wednesday), + thu: formatDayMonth(thursday), + fri: formatDayMonth(friday), + }, + offCarole: 0, + extraOffCarole: 0, + centre: 0, + avis: 0, + alex: { + total: 0, + detail: "", + }, + laia: { + total: 0, + detail: "", + }, + }); + + current.setDate(current.getDate() + 7); + weekCount++; + } + + return weeks; +} + +const weeks = generateWeeks(); + +// === 2. Calcul des rowspans pour la colonne Mois === + +function computeMonthSpans(weeks) { + const counts = {}; + weeks.forEach((w) => { + counts[w.monthKey] = (counts[w.monthKey] || 0) + 1; + }); + return counts; +} + +const monthSpans = computeMonthSpans(weeks); + +// === 3. Rendu du tableau === function renderTable() { const planningBody = document.getElementById("planningBody"); @@ -52,46 +132,81 @@ function renderTable() { const showOnlyCaroleOff = document.getElementById("showOnlyCaroleOff")?.checked; - const showOnlySchoolHoliday = document.getElementById( - "showOnlySchoolHoliday" - )?.checked; + // showOnlySchoolHoliday est ignore pour l'instant + + const monthRowRendered = {}; // monthKey -> bool weeks.forEach((week, index) => { - if (showOnlyCaroleOff && week.caroleOffDays === 0) return; - if (showOnlySchoolHoliday && !week.isSchoolHoliday) return; + if (showOnlyCaroleOff && week.offCarole === 0) return; const tr = document.createElement("tr"); - if (week.caroleOffDays > 0) tr.classList.add("fc-row--carole-off"); - if (week.isSchoolHoliday) tr.classList.add("fc-row--school-holiday"); - if (week.isBankHoliday) tr.classList.add("fc-row--bank-holiday"); + // Colonne Mois avec rowspan uniquement pour la 1ere ligne du mois + if (!monthRowRendered[week.monthKey]) { + monthRowRendered[week.monthKey] = true; + const tdMonth = document.createElement("td"); + tdMonth.rowSpan = monthSpans[week.monthKey] || 1; + tdMonth.textContent = week.monthName; + tr.appendChild(tdMonth); + } - tr.innerHTML = ` - ${week.month} - ${week.code} - ${week.dates} - ${week.caroleOffDays || ""} - ${week.isSchoolHoliday ? "Oui" : ""} - ${week.isBankHoliday ? "Oui" : ""} - - - - - - - `; + // Colonne Semaine + const tdWeek = document.createElement("td"); + tdWeek.textContent = week.weekLabel; + tr.appendChild(tdWeek); + + // Jours Lundi -> Vendredi + ["mon", "tue", "wed", "thu", "fri"].forEach((dayKey) => { + const td = document.createElement("td"); + td.textContent = week.days[dayKey]; + tr.appendChild(td); + }); + + // # Off Carole + const tdOff = document.createElement("td"); + tdOff.innerHTML = ``; + tr.appendChild(tdOff); + + // # Extra off Carole + const tdExtraOff = document.createElement("td"); + tdExtraOff.innerHTML = ``; + tr.appendChild(tdExtraOff); + + // #Centre + const tdCentre = document.createElement("td"); + tdCentre.innerHTML = ``; + tr.appendChild(tdCentre); + + // #Avis + const tdAvis = document.createElement("td"); + tdAvis.innerHTML = ``; + tr.appendChild(tdAvis); + + // Alex total & détail + const tdAlexTotal = document.createElement("td"); + tdAlexTotal.textContent = week.alex.total.toFixed + ? week.alex.total.toFixed(2) + : week.alex.total; + tr.appendChild(tdAlexTotal); + + const tdAlexDetail = document.createElement("td"); + tdAlexDetail.innerHTML = ``; + tr.appendChild(tdAlexDetail); + + // Laia total & détail + const tdLaiaTotal = document.createElement("td"); + tdLaiaTotal.textContent = week.laia.total.toFixed + ? week.laia.total.toFixed(2) + : week.laia.total; + tr.appendChild(tdLaiaTotal); + + const tdLaiaDetail = document.createElement("td"); + tdLaiaDetail.innerHTML = ``; + tr.appendChild(tdLaiaDetail); planningBody.appendChild(tr); }); @@ -100,22 +215,44 @@ function renderTable() { updateSummary(); } +// === 4. Listeners sur les inputs === + function attachInputListeners() { const planningBody = document.getElementById("planningBody"); if (!planningBody) return; - planningBody.querySelectorAll("input[type='number']").forEach((input) => { + planningBody.querySelectorAll("input").forEach((input) => { input.addEventListener("change", (e) => { - const w = parseInt(e.target.dataset.week, 10); - const person = e.target.dataset.person; - const type = e.target.dataset.type; - const value = parseFloat(e.target.value || "0"); - weeks[w][person][type] = value; + const weekIndex = parseInt(e.target.dataset.week, 10); + const field = e.target.dataset.field; + const value = + e.target.type === "number" + ? parseFloat(e.target.value || "0") + : e.target.value; + + if (Number.isNaN(weekIndex) || !weeks[weekIndex]) return; + + if ( + field === "offCarole" || + field === "extraOffCarole" || + field === "centre" || + field === "avis" + ) { + weeks[weekIndex][field] = value; + } else if (field === "alex.detail") { + weeks[weekIndex].alex.detail = value; + } else if (field === "laia.detail") { + weeks[weekIndex].laia.detail = value; + } + + // plus tard : calculer alex.total / laia.total en fonction des CP/RTT/JA updateSummary(); }); }); } +// === 5. Résumé (pour l'instant, 0 utilisés) === + function updateSummary() { const summaryDiv = document.getElementById("summaryText"); if (!summaryDiv) return; @@ -140,22 +277,14 @@ function updateSummary() { document.getElementById("laiaJaInit")?.value || "0" ); - let alexCpUsed = 0, - alexRttUsed = 0, - alexJaUsed = 0; - let laiaCpUsed = 0, - laiaRttUsed = 0, - laiaJaUsed = 0; + // Pour l'instant, on n'a pas encore branché les CP/RTT/JA par semaine + const alexCpUsed = 0; + const alexRttUsed = 0; + const alexJaUsed = 0; - weeks.forEach((week) => { - alexCpUsed += week.alex.cp; - alexRttUsed += week.alex.rtt; - alexJaUsed += week.alex.ja; - - laiaCpUsed += week.laia.cp; - laiaRttUsed += week.laia.rtt; - laiaJaUsed += week.laia.ja; - }); + const laiaCpUsed = 0; + const laiaRttUsed = 0; + const laiaJaUsed = 0; const alexCpLeft = alexCpInit - alexCpUsed; const alexRttLeft = alexRttInit - alexRttUsed; @@ -167,30 +296,35 @@ function updateSummary() { summaryDiv.innerHTML = `

Alex
- CP utilisés : ${alexCpUsed.toFixed(2)} / ${alexCpInit.toFixed( + CP utilises : ${alexCpUsed.toFixed(2)} / ${alexCpInit.toFixed( 2 )} (reste ${alexCpLeft.toFixed(2)})
- RTT utilisés : ${alexRttUsed.toFixed(2)} / ${alexRttInit.toFixed( + RTT utilises : ${alexRttUsed.toFixed(2)} / ${alexRttInit.toFixed( 2 )} (reste ${alexRttLeft.toFixed(2)})
- JA utilisés : ${alexJaUsed.toFixed(2)} / ${alexJaInit.toFixed( + JA utilises : ${alexJaUsed.toFixed(2)} / ${alexJaInit.toFixed( 2 )} (reste ${alexJaLeft.toFixed(2)})

Laia
- CP utilisés : ${laiaCpUsed.toFixed(2)} / ${laiaCpInit.toFixed( + CP utilises : ${laiaCpUsed.toFixed(2)} / ${laiaCpInit.toFixed( 2 )} (reste ${laiaCpLeft.toFixed(2)})
- RTT utilisés : ${laiaRttUsed.toFixed(2)} / ${laiaRttInit.toFixed( + RTT utilises : ${laiaRttUsed.toFixed(2)} / ${laiaRttInit.toFixed( 2 )} (reste ${laiaRttLeft.toFixed(2)})
- JA utilisés : ${laiaJaUsed.toFixed(2)} / ${laiaJaInit.toFixed(2)})

+ JA utilises : ${laiaJaUsed.toFixed(2)} / ${laiaJaInit.toFixed( + 2 + )} (reste ${laiaJaLeft.toFixed(2)})

`; } +// === 6. Init === + function initFamilyCalendar() { if (!document.getElementById("planningBody")) return; + // Soldes initiaux [ "alexCpInit", "alexRttInit", @@ -203,10 +337,17 @@ function initFamilyCalendar() { if (el) el.addEventListener("change", updateSummary); }); - ["showOnlyCaroleOff", "showOnlySchoolHoliday"].forEach((id) => { - const el = document.getElementById(id); - if (el) el.addEventListener("change", renderTable); - }); + // Filtres (pour l'instant seul showOnlyCaroleOff a un effet) + const showOnlyCaroleOff = document.getElementById("showOnlyCaroleOff"); + if (showOnlyCaroleOff) { + showOnlyCaroleOff.addEventListener("change", renderTable); + } + const showOnlySchoolHoliday = document.getElementById( + "showOnlySchoolHoliday" + ); + if (showOnlySchoolHoliday) { + showOnlySchoolHoliday.addEventListener("change", renderTable); + } renderTable(); } diff --git a/family-calendar.php b/family-calendar.php index 33f9699..e558023 100644 --- a/family-calendar.php +++ b/family-calendar.php @@ -72,18 +72,34 @@ require __DIR__ . '/header.php'; Mois Semaine - Dates (lun-dim) + Lundi + Mardi + Mercredi + Jeudi + Vendredi # Off Carole - Vacances scolaires - Bank holiday - Alex - jours poses (semaine) - Laia - jours poses (semaine) + # Extra off Carole + #Centre + #Avis + Alex + Laia - - - CPRTTJA - CPRTTJA + + + jj/mm + jj/mm + jj/mm + jj/mm + jj/mm + jours + jours + jours + jours + Total + Détail + Total + Détail @@ -93,7 +109,6 @@ require __DIR__ . '/header.php'; -