diff --git a/assets/css/style.css b/assets/css/style.css index 82402d6..6a3197f 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -375,6 +375,13 @@ input[type="number"] { border: 1px solid #d9e2ec; } +.fc-calendar-and-summary { + display: grid; + grid-template-columns: 1fr auto; + gap: 24px; + align-items: start; +} + .fc-month-header { display: flex; align-items: center; @@ -548,6 +555,69 @@ input[type="number"] { cursor: pointer; } +/* === TABLEAU RÉCAPITULATIF === */ +.fc-month-summary { + min-width: 300px; +} + +.fc-summary-table-wrapper { + background: #f8fafc; + border-radius: 6px; + padding: 12px; + border: 1px solid #d9e2ec; +} + +.fc-summary-table { + width: 100%; + border-collapse: collapse; + font-size: 13px; +} + +.fc-summary-table thead th { + background: #f0f4f8; + padding: 8px 6px; + text-align: center; + font-weight: 600; + color: #243b53; + border: 1px solid #d9e2ec; + white-space: nowrap; +} + +.fc-summary-table tbody td { + border: 1px solid #d9e2ec; + padding: 6px 8px; + text-align: center; + background: #fff; +} + +.fc-summary-table tbody td:first-child { + text-align: left; + font-weight: 500; + color: #243b53; +} + +.fc-summary-total-row { + background: #f0f4f8 !important; + border-top: 2px solid #243b53; +} + +.fc-summary-total-row td { + background: #f0f4f8 !important; + font-weight: 600; + color: #243b53; +} + +/* Responsive pour le calendrier et le récapitulatif */ +@media (max-width: 1200px) { + .fc-calendar-and-summary { + grid-template-columns: 1fr; + } + + .fc-month-summary { + min-width: 100%; + } +} + /* === VUE 2 MOIS === */ .fc-two-months-container { display: grid; diff --git a/assets/js/family-calendar.js b/assets/js/family-calendar.js index 0dabd3e..899bd87 100644 --- a/assets/js/family-calendar.js +++ b/assets/js/family-calendar.js @@ -910,6 +910,9 @@ document.addEventListener("DOMContentLoaded", () => { } else { this.renderSingleMonthView(); } + + // Afficher le tableau récapitulatif + this.renderMonthSummary(); } renderSingleMonthView() { @@ -918,6 +921,191 @@ document.addEventListener("DOMContentLoaded", () => { this.monthCalendar.innerHTML = this.generateMonthHTML(year, month); } + calculateMonthTotals(year, month) { + // Calculer le premier et dernier jour du mois (uniquement jours de semaine) + const firstDay = new Date(year, month, 1); + const lastDay = new Date(year, month + 1, 0); + const totals = { + offCarole: 0, + extraOffCarole: 0, + centre: 0, + avis: 0, + }; + + // Parcourir tous les jours du mois + for (let day = 1; day <= lastDay.getDate(); day++) { + const date = new Date(year, month, day); + const dayOfWeek = date.getDay(); + + // Ignorer les samedi (6) et dimanche (0) + if (dayOfWeek === 0 || dayOfWeek === 6) { + continue; + } + + const isoDate = `${year}-${String(month + 1).padStart(2, "0")}-${String( + day + ).padStart(2, "0")}`; + + // Trouver les événements pour ce jour + const dayEvents = this.dbEvents.filter((evt) => evt.date === isoDate); + + dayEvents.forEach((evt) => { + const dur = parseFloat(evt.duration) || 1; + switch (evt.type) { + case "OFF_CAROLE": + totals.offCarole += dur; + break; + case "EXTRA_OFF_CAROLE": + totals.extraOffCarole += dur; + break; + case "CENTRE": + totals.centre += dur; + break; + case "AVIS": + totals.avis += dur; + break; + } + }); + } + + return totals; + } + + renderMonthSummary() { + const summaryDiv = document.getElementById("fc-month-summary"); + if (!summaryDiv) return; + + let html = '
'; + html += ''; + html += ""; + html += ""; + html += ""; + html += ""; + html += ""; + html += ""; + html += ""; + + const formatTotal = (total) => + total > 0 ? (Number.isInteger(total) ? total : total.toFixed(1)) : ""; + + if (this.viewMode === "year") { + // Afficher tous les mois de l'année scolaire + const year = this.currentMonth.getFullYear(); + const schoolYearMonths = []; + for (let month = 8; month < 12; month++) { + schoolYearMonths.push({ year, month }); + } + for (let month = 0; month < 8; month++) { + schoolYearMonths.push({ year: year + 1, month }); + } + + schoolYearMonths.forEach(({ year: monthYear, month }) => { + const totals = this.calculateMonthTotals(monthYear, month); + html += ""; + html += ``; + html += ``; + html += ``; + html += ``; + html += ``; + html += ""; + }); + + // Ligne de total + const yearTotals = schoolYearMonths.reduce( + (acc, { year: monthYear, month }) => { + const totals = this.calculateMonthTotals(monthYear, month); + acc.offCarole += totals.offCarole; + acc.extraOffCarole += totals.extraOffCarole; + acc.centre += totals.centre; + acc.avis += totals.avis; + return acc; + }, + { offCarole: 0, extraOffCarole: 0, centre: 0, avis: 0 } + ); + html += ''; + html += ``; + html += ``; + html += ``; + html += ``; + html += ``; + html += ""; + } else if (this.viewMode === "2months") { + // Afficher les 2 mois + const year = this.currentMonth.getFullYear(); + const month = this.currentMonth.getMonth(); + const nextMonth = month + 1; + const nextYear = nextMonth > 11 ? year + 1 : year; + const nextMonthIndex = nextMonth > 11 ? 0 : nextMonth; + + // Premier mois + const totals1 = this.calculateMonthTotals(year, month); + html += ""; + html += ``; + html += ``; + html += ``; + html += ``; + html += ``; + html += ""; + + // Deuxième mois + const totals2 = this.calculateMonthTotals(nextYear, nextMonthIndex); + html += ""; + html += ``; + html += ``; + html += ``; + html += ``; + html += ``; + html += ""; + + // Ligne de total + const combinedTotals = { + offCarole: totals1.offCarole + totals2.offCarole, + extraOffCarole: totals1.extraOffCarole + totals2.extraOffCarole, + centre: totals1.centre + totals2.centre, + avis: totals1.avis + totals2.avis, + }; + html += ''; + html += ""; + html += ``; + html += ``; + html += ``; + html += ``; + html += ""; + } else { + // Afficher 1 mois + const year = this.currentMonth.getFullYear(); + const month = this.currentMonth.getMonth(); + const totals = this.calculateMonthTotals(year, month); + html += ""; + html += ``; + html += ``; + html += ``; + html += ``; + html += ``; + html += ""; + } + + html += "
Mois# Off Carole# Extra off Carole# Centre# Avis
${getMonthNameFr(month)} ${monthYear}${formatTotal(totals.offCarole)}${formatTotal(totals.extraOffCarole)}${formatTotal(totals.centre)}${formatTotal(totals.avis)}
Total ${year}-${year + 1}${formatTotal( + yearTotals.offCarole + )}${formatTotal( + yearTotals.extraOffCarole + )}${formatTotal(yearTotals.centre)}${formatTotal(yearTotals.avis)}
${getMonthNameFr(month)} ${ + month >= 8 ? year : year + 1 + }${formatTotal(totals1.offCarole)}${formatTotal(totals1.extraOffCarole)}${formatTotal(totals1.centre)}${formatTotal(totals1.avis)}
${getMonthNameFr(nextMonthIndex)} ${ + nextMonthIndex >= 8 ? nextYear : nextYear + 1 + }${formatTotal(totals2.offCarole)}${formatTotal(totals2.extraOffCarole)}${formatTotal(totals2.centre)}${formatTotal(totals2.avis)}
Total${formatTotal( + combinedTotals.offCarole + )}${formatTotal( + combinedTotals.extraOffCarole + )}${formatTotal( + combinedTotals.centre + )}${formatTotal(combinedTotals.avis)}
${getMonthNameFr(month)} ${ + month >= 8 ? year : year + 1 + }${formatTotal(totals.offCarole)}${formatTotal(totals.extraOffCarole)}${formatTotal(totals.centre)}${formatTotal(totals.avis)}
"; + html += "
"; + summaryDiv.innerHTML = html; + } + renderTwoMonthsView() { const year = this.currentMonth.getFullYear(); const month = this.currentMonth.getMonth(); diff --git a/family-calendar.php b/family-calendar.php index 34b4ef8..940586f 100644 --- a/family-calendar.php +++ b/family-calendar.php @@ -108,8 +108,13 @@ require __DIR__ . '/header.php'; -
- +
+
+ +
+
+ +