Auto-commit for deploy to production - 2025-12-08 17:46:31

This commit is contained in:
2025-12-08 17:46:31 +01:00
parent e0d26b28df
commit 87995be91d
2 changed files with 274 additions and 118 deletions
+249 -108
View File
@@ -1,48 +1,128 @@
// assets/js/family-calendar.js // assets/js/family-calendar.js
const weeks = [ // === 1. Utilitaires dates ===
{
month: "September", /**
code: "W36", * Formate une Date en "dd/mm".
dates: "01/09 - 07/09", */
caroleOffDays: 0, function formatDayMonth(date) {
isSchoolHoliday: false, const d = String(date.getDate()).padStart(2, "0");
isBankHoliday: false, const m = String(date.getMonth() + 1).padStart(2, "0");
alex: { cp: 0, rtt: 0, ja: 0 }, return `${d}/${m}`;
laia: { cp: 0, rtt: 0, ja: 0 }, }
},
{ /**
month: "September", * Retourne le nom de mois en français à partir du monthIndex JS (0..11).
code: "W38", */
dates: "15/09 - 21/09", function getMonthNameFr(monthIndex) {
caroleOffDays: 2, const map = {
isSchoolHoliday: false, 0: "Janvier",
isBankHoliday: false, 1: "Fevrier",
alex: { cp: 0, rtt: 0, ja: 0 }, 2: "Mars",
laia: { cp: 0, rtt: 0, ja: 0 }, 3: "Avril",
}, 4: "Mai",
{ 5: "Juin",
month: "October", 6: "Juillet",
code: "W40", 7: "Aout",
dates: "29/09 - 05/10", 8: "Septembre",
caroleOffDays: 0, 9: "Octobre",
isSchoolHoliday: false, 10: "Novembre",
isBankHoliday: false, 11: "Decembre",
alex: { cp: 0, rtt: 0, ja: 0 }, };
laia: { cp: 0, rtt: 0, ja: 0 }, return map[monthIndex] || "";
}, }
{
month: "August", /**
code: "W32", * Genere les semaines de la 1ere semaine de septembre 2025
dates: "03/08 - 09/08", * a la derniere semaine d'aout 2026.
caroleOffDays: 5, * Chaque element contient:
isSchoolHoliday: true, * - monthKey (ex: "2025-09")
isBankHoliday: false, * - monthName (ex: "Septembre")
alex: { cp: 0, rtt: 0, ja: 0 }, * - weekLabel (W1, W2, ...)
laia: { cp: 0, rtt: 0, ja: 0 }, * - days: { mon, tue, wed, thu, fri } en "dd/mm"
}, * - offCarole, extraOffCarole, centre, avis
// TODO: compléter le reste des semaines W36 → W35 * - 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() { function renderTable() {
const planningBody = document.getElementById("planningBody"); const planningBody = document.getElementById("planningBody");
@@ -52,46 +132,81 @@ function renderTable() {
const showOnlyCaroleOff = const showOnlyCaroleOff =
document.getElementById("showOnlyCaroleOff")?.checked; document.getElementById("showOnlyCaroleOff")?.checked;
const showOnlySchoolHoliday = document.getElementById( // showOnlySchoolHoliday est ignore pour l'instant
"showOnlySchoolHoliday"
)?.checked; const monthRowRendered = {}; // monthKey -> bool
weeks.forEach((week, index) => { weeks.forEach((week, index) => {
if (showOnlyCaroleOff && week.caroleOffDays === 0) return; if (showOnlyCaroleOff && week.offCarole === 0) return;
if (showOnlySchoolHoliday && !week.isSchoolHoliday) return;
const tr = document.createElement("tr"); const tr = document.createElement("tr");
if (week.caroleOffDays > 0) tr.classList.add("fc-row--carole-off"); // Colonne Mois avec rowspan uniquement pour la 1ere ligne du mois
if (week.isSchoolHoliday) tr.classList.add("fc-row--school-holiday"); if (!monthRowRendered[week.monthKey]) {
if (week.isBankHoliday) tr.classList.add("fc-row--bank-holiday"); monthRowRendered[week.monthKey] = true;
const tdMonth = document.createElement("td");
tdMonth.rowSpan = monthSpans[week.monthKey] || 1;
tdMonth.textContent = week.monthName;
tr.appendChild(tdMonth);
}
tr.innerHTML = ` // Colonne Semaine
<td>${week.month}</td> const tdWeek = document.createElement("td");
<td>${week.code}</td> tdWeek.textContent = week.weekLabel;
<td>${week.dates}</td> tr.appendChild(tdWeek);
<td>${week.caroleOffDays || ""}</td>
<td>${week.isSchoolHoliday ? "Oui" : ""}</td> // Jours Lundi -> Vendredi
<td>${week.isBankHoliday ? "Oui" : ""}</td> ["mon", "tue", "wed", "thu", "fri"].forEach((dayKey) => {
<td><input type="number" step="0.25" min="0" value="${ const td = document.createElement("td");
week.alex.cp td.textContent = week.days[dayKey];
}" data-week="${index}" data-person="alex" data-type="cp"></td> tr.appendChild(td);
<td><input type="number" step="0.25" min="0" value="${ });
week.alex.rtt
}" data-week="${index}" data-person="alex" data-type="rtt"></td> // # Off Carole
<td><input type="number" step="0.25" min="0" value="${ const tdOff = document.createElement("td");
week.alex.ja tdOff.innerHTML = `<input type="number" step="0.25" min="0" value="${week.offCarole}" data-week="${index}" data-field="offCarole">`;
}" data-week="${index}" data-person="alex" data-type="ja"></td> tr.appendChild(tdOff);
<td><input type="number" step="0.25" min="0" value="${
week.laia.cp // # Extra off Carole
}" data-week="${index}" data-person="laia" data-type="cp"></td> const tdExtraOff = document.createElement("td");
<td><input type="number" step="0.25" min="0" value="${ tdExtraOff.innerHTML = `<input type="number" step="0.25" min="0" value="${week.extraOffCarole}" data-week="${index}" data-field="extraOffCarole">`;
week.laia.rtt tr.appendChild(tdExtraOff);
}" data-week="${index}" data-person="laia" data-type="rtt"></td>
<td><input type="number" step="0.25" min="0" value="${ // #Centre
week.laia.ja const tdCentre = document.createElement("td");
}" data-week="${index}" data-person="laia" data-type="ja"></td> tdCentre.innerHTML = `<input type="number" step="0.25" min="0" value="${week.centre}" data-week="${index}" data-field="centre">`;
`; tr.appendChild(tdCentre);
// #Avis
const tdAvis = document.createElement("td");
tdAvis.innerHTML = `<input type="number" step="0.25" min="0" value="${week.avis}" data-week="${index}" data-field="avis">`;
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 = `<input type="text" value="${
week.alex.detail || ""
}" data-week="${index}" data-field="alex.detail">`;
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 = `<input type="text" value="${
week.laia.detail || ""
}" data-week="${index}" data-field="laia.detail">`;
tr.appendChild(tdLaiaDetail);
planningBody.appendChild(tr); planningBody.appendChild(tr);
}); });
@@ -100,22 +215,44 @@ function renderTable() {
updateSummary(); updateSummary();
} }
// === 4. Listeners sur les inputs ===
function attachInputListeners() { function attachInputListeners() {
const planningBody = document.getElementById("planningBody"); const planningBody = document.getElementById("planningBody");
if (!planningBody) return; if (!planningBody) return;
planningBody.querySelectorAll("input[type='number']").forEach((input) => { planningBody.querySelectorAll("input").forEach((input) => {
input.addEventListener("change", (e) => { input.addEventListener("change", (e) => {
const w = parseInt(e.target.dataset.week, 10); const weekIndex = parseInt(e.target.dataset.week, 10);
const person = e.target.dataset.person; const field = e.target.dataset.field;
const type = e.target.dataset.type; const value =
const value = parseFloat(e.target.value || "0"); e.target.type === "number"
weeks[w][person][type] = value; ? 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(); updateSummary();
}); });
}); });
} }
// === 5. Résumé (pour l'instant, 0 utilisés) ===
function updateSummary() { function updateSummary() {
const summaryDiv = document.getElementById("summaryText"); const summaryDiv = document.getElementById("summaryText");
if (!summaryDiv) return; if (!summaryDiv) return;
@@ -140,22 +277,14 @@ function updateSummary() {
document.getElementById("laiaJaInit")?.value || "0" document.getElementById("laiaJaInit")?.value || "0"
); );
let alexCpUsed = 0, // Pour l'instant, on n'a pas encore branché les CP/RTT/JA par semaine
alexRttUsed = 0, const alexCpUsed = 0;
alexJaUsed = 0; const alexRttUsed = 0;
let laiaCpUsed = 0, const alexJaUsed = 0;
laiaRttUsed = 0,
laiaJaUsed = 0;
weeks.forEach((week) => { const laiaCpUsed = 0;
alexCpUsed += week.alex.cp; const laiaRttUsed = 0;
alexRttUsed += week.alex.rtt; const laiaJaUsed = 0;
alexJaUsed += week.alex.ja;
laiaCpUsed += week.laia.cp;
laiaRttUsed += week.laia.rtt;
laiaJaUsed += week.laia.ja;
});
const alexCpLeft = alexCpInit - alexCpUsed; const alexCpLeft = alexCpInit - alexCpUsed;
const alexRttLeft = alexRttInit - alexRttUsed; const alexRttLeft = alexRttInit - alexRttUsed;
@@ -167,30 +296,35 @@ function updateSummary() {
summaryDiv.innerHTML = ` summaryDiv.innerHTML = `
<p><strong>Alex</strong><br> <p><strong>Alex</strong><br>
CP utilisés : ${alexCpUsed.toFixed(2)} / ${alexCpInit.toFixed( CP utilises : ${alexCpUsed.toFixed(2)} / ${alexCpInit.toFixed(
2 2
)} (reste ${alexCpLeft.toFixed(2)})<br> )} (reste ${alexCpLeft.toFixed(2)})<br>
RTT utilisés : ${alexRttUsed.toFixed(2)} / ${alexRttInit.toFixed( RTT utilises : ${alexRttUsed.toFixed(2)} / ${alexRttInit.toFixed(
2 2
)} (reste ${alexRttLeft.toFixed(2)})<br> )} (reste ${alexRttLeft.toFixed(2)})<br>
JA utilisés : ${alexJaUsed.toFixed(2)} / ${alexJaInit.toFixed( JA utilises : ${alexJaUsed.toFixed(2)} / ${alexJaInit.toFixed(
2 2
)} (reste ${alexJaLeft.toFixed(2)})</p> )} (reste ${alexJaLeft.toFixed(2)})</p>
<p><strong>Laia</strong><br> <p><strong>Laia</strong><br>
CP utilisés : ${laiaCpUsed.toFixed(2)} / ${laiaCpInit.toFixed( CP utilises : ${laiaCpUsed.toFixed(2)} / ${laiaCpInit.toFixed(
2 2
)} (reste ${laiaCpLeft.toFixed(2)})<br> )} (reste ${laiaCpLeft.toFixed(2)})<br>
RTT utilisés : ${laiaRttUsed.toFixed(2)} / ${laiaRttInit.toFixed( RTT utilises : ${laiaRttUsed.toFixed(2)} / ${laiaRttInit.toFixed(
2 2
)} (reste ${laiaRttLeft.toFixed(2)})<br> )} (reste ${laiaRttLeft.toFixed(2)})<br>
JA utilisés : ${laiaJaUsed.toFixed(2)} / ${laiaJaInit.toFixed(2)})</p> JA utilises : ${laiaJaUsed.toFixed(2)} / ${laiaJaInit.toFixed(
2
)} (reste ${laiaJaLeft.toFixed(2)})</p>
`; `;
} }
// === 6. Init ===
function initFamilyCalendar() { function initFamilyCalendar() {
if (!document.getElementById("planningBody")) return; if (!document.getElementById("planningBody")) return;
// Soldes initiaux
[ [
"alexCpInit", "alexCpInit",
"alexRttInit", "alexRttInit",
@@ -203,10 +337,17 @@ function initFamilyCalendar() {
if (el) el.addEventListener("change", updateSummary); if (el) el.addEventListener("change", updateSummary);
}); });
["showOnlyCaroleOff", "showOnlySchoolHoliday"].forEach((id) => { // Filtres (pour l'instant seul showOnlyCaroleOff a un effet)
const el = document.getElementById(id); const showOnlyCaroleOff = document.getElementById("showOnlyCaroleOff");
if (el) el.addEventListener("change", renderTable); if (showOnlyCaroleOff) {
}); showOnlyCaroleOff.addEventListener("change", renderTable);
}
const showOnlySchoolHoliday = document.getElementById(
"showOnlySchoolHoliday"
);
if (showOnlySchoolHoliday) {
showOnlySchoolHoliday.addEventListener("change", renderTable);
}
renderTable(); renderTable();
} }
+25 -10
View File
@@ -72,18 +72,34 @@ require __DIR__ . '/header.php';
<tr> <tr>
<th>Mois</th> <th>Mois</th>
<th>Semaine</th> <th>Semaine</th>
<th>Dates (lun-dim)</th> <th>Lundi</th>
<th>Mardi</th>
<th>Mercredi</th>
<th>Jeudi</th>
<th>Vendredi</th>
<th># Off Carole</th> <th># Off Carole</th>
<th>Vacances scolaires</th> <th># Extra off Carole</th>
<th>Bank holiday</th> <th>#Centre</th>
<th colspan="3">Alex - jours poses (semaine)</th> <th>#Avis</th>
<th colspan="3">Laia - jours poses (semaine)</th> <th colspan="2">Alex</th>
<th colspan="2">Laia</th>
</tr> </tr>
<tr> <tr>
<th></th><th></th><th></th> <th></th>
<th></th><th></th><th></th> <th></th>
<th>CP</th><th>RTT</th><th>JA</th> <th>jj/mm</th>
<th>CP</th><th>RTT</th><th>JA</th> <th>jj/mm</th>
<th>jj/mm</th>
<th>jj/mm</th>
<th>jj/mm</th>
<th>jours</th>
<th>jours</th>
<th>jours</th>
<th>jours</th>
<th>Total</th>
<th>Détail</th>
<th>Total</th>
<th>Détail</th>
</tr> </tr>
</thead> </thead>
<tbody id="planningBody"> <tbody id="planningBody">
@@ -93,7 +109,6 @@ require __DIR__ . '/header.php';
</div> </div>
</section> </section>
<!-- IMPORTANT : plus de /pachafamily ici -->
<script src="/assets/js/family-calendar.js"></script> <script src="/assets/js/family-calendar.js"></script>
<?php <?php