From 3bfd25d566eb4a3ffdd50737683d84fc76efa0df Mon Sep 17 00:00:00 2001 From: "fefe.clochette" Date: Wed, 6 May 2026 13:24:27 +0200 Subject: [PATCH] infinite scroll --- family-calendar.php | 2 +- includes/lang/ca.php | 3 +- includes/lang/fr.php | 3 +- modules/budget/views/suivi.php | 18 +- modules/family-calendar/family-calendar.css | 15 +- modules/family-calendar/family-calendar.js | 107 +- pachafamily_source.md | 3411 +++++++++++++------ 7 files changed, 2371 insertions(+), 1188 deletions(-) diff --git a/family-calendar.php b/family-calendar.php index 3249345..4943c4c 100644 --- a/family-calendar.php +++ b/family-calendar.php @@ -229,7 +229,7 @@ window.I18N = { 'leg_pep_sick': "", 'leg_off_carole': "", 'leg_extra_off': "", - 'leg_presence Pep': "", + 'leg_presence': "", 'fc_menu_kids_leaves': "", 'fc_clear': "", 'fc_unit_days': "", diff --git a/includes/lang/ca.php b/includes/lang/ca.php index 6046752..7451beb 100644 --- a/includes/lang/ca.php +++ b/includes/lang/ca.php @@ -134,7 +134,7 @@ return [ 'fc_err_fetch_gov' => 'Error en la connexió amb l’API governamental.', 'fc_err_no_data_gov' => 'No s’han trobat dades a l’API del govern per a aquest any.', 'fc_err_action' => 'Error en l’acció: ', - 'leg_presence_pep' => 'Presència Pep', + 'leg_presence' => 'Presència Pep', 'leg_school_holidays' => 'Vacances Escolars', 'leg_public_holiday' => 'Festiu', @@ -143,7 +143,6 @@ return [ 'leg_centre' => 'Casal', 'leg_avis' => 'Avís', 'leg_pep_sick' => 'Pep Malalt', - 'leg_presence' => 'Presència', 'vac_toussaint' => 'Vacances de Tots Sants', 'vac_noel' => 'Vacances de Nadal', diff --git a/includes/lang/fr.php b/includes/lang/fr.php index 13fa386..5b093c1 100644 --- a/includes/lang/fr.php +++ b/includes/lang/fr.php @@ -137,7 +137,7 @@ return [ 'fc_err_fetch_gov' => 'Erreur lors de la connexion à l’API gouvernementale.', 'fc_err_no_data_gov' => 'Aucune donnée trouvée sur l’API du gouvernement pour cette année.', 'fc_err_action' => 'Erreur lors de l’action : ', - 'leg_presence_pep' => 'Présence Pep', + 'leg_presence' => 'Présence Pep', 'leg_school_holidays' => 'Vacances Scolaires', 'leg_public_holiday' => 'Férié', @@ -146,7 +146,6 @@ return [ 'leg_centre' => 'Centre', 'leg_avis' => 'Avis', 'leg_pep_sick' => 'Pep Malade', - 'leg_presence' => 'Présence', 'vac_toussaint' => 'Vacances de la Toussaint', 'vac_noel' => 'Vacances de Noël', diff --git a/modules/budget/views/suivi.php b/modules/budget/views/suivi.php index 1184a72..b259f9e 100644 --- a/modules/budget/views/suivi.php +++ b/modules/budget/views/suivi.php @@ -601,10 +601,11 @@ $monthName = $monthNames[(int)$viewM] . ' ' . $viewY;
-
-

🏦

- +
+

🏦

+
+
@@ -616,9 +617,10 @@ $monthName = $monthNames[(int)$viewM] . ' ' . $viewY;
-
@@ -728,7 +730,9 @@ window.I18N = { 'bud_confirm_delete': , 'bud_to_define_js': , 'error_occured': , - 'bud_err_tech': + 'bud_err_tech': , + 'btn_cancel': , + 'btn_delete': , }; const activeViewMonth = ''; diff --git a/modules/family-calendar/family-calendar.css b/modules/family-calendar/family-calendar.css index 03f0cc9..59c0651 100644 --- a/modules/family-calendar/family-calendar.css +++ b/modules/family-calendar/family-calendar.css @@ -2,11 +2,17 @@ :root { /* Couleurs sémantiques Calendrier */ - --c-school-holiday: #e5d9f2; - --c-public-holiday: #e2e8f0; /* Plus marqué que l'original */ - --c-off-carole: #ffedd5; + --c-school-holiday: #ede9fe; + --c-public-holiday: repeating-linear-gradient( + 45deg, + #f8fafc, + #f8fafc 8px, + #f1f5f9 8px, + #f1f5f9 16px + ); + --c-off-carole: #fef3c7; --c-extra-off: #fee2e2; - --c-selected: #bfdbfe; + --c-selected: #dbeafe; /* Thèmes Parents (Sync Budget) */ --bg-alex: #ecfeff; @@ -575,7 +581,6 @@ td.col-laia-sub { width: 16px; height: 16px; border-radius: 4px; - border: 1px solid rgba(0, 0, 0, 0.05); } .fc-legend-school-holiday { background: var(--c-school-holiday); diff --git a/modules/family-calendar/family-calendar.js b/modules/family-calendar/family-calendar.js index 26b4e66..68fd83c 100644 --- a/modules/family-calendar/family-calendar.js +++ b/modules/family-calendar/family-calendar.js @@ -105,14 +105,22 @@ document.addEventListener("DOMContentLoaded", () => { // Modifie dynamiquement le titre de la modale pour y insérer le selecteur d'année setupModalUI() { - const headerH2 = document.querySelector(".fc-modal-header h2"); - if (headerH2 && !document.getElementById("holidayYearSelect")) { - headerH2.innerHTML = `${tr("fc_modal_holidays_title")} - + ${options} `; document @@ -202,7 +210,7 @@ document.addEventListener("DOMContentLoaded", () => { renderModalHolidays() { if (!this.schoolHolidaysTableBody) return; - // Filtrer les événements de type VACANCES_SCOLAIRES pour l'année scolaire sélectionnée + // On utilise bien l'année de la modale, indépendamment du planning de fond const startDate = `${this.modalSelectedYear}-09-01`; const endDate = `${this.modalSelectedYear + 1}-08-31`; @@ -213,61 +221,50 @@ document.addEventListener("DOMContentLoaded", () => { e.date <= endDate, ); - // S'il n'y a pas de vacances en base pour cette année, on affiche le bouton "Générer" if (yearHolidays.length === 0) { this.schoolHolidaysTableBody.innerHTML = ` -

Les vacances de cette année ne sont pas encore enregistrées.

- +

${tr("fc_err_no_data_gov")}

+ `; - document .getElementById("btnFetchGovHolidays") - .addEventListener("click", (e) => { - e.target.innerText = "Téléchargement en cours..."; + ?.addEventListener("click", (e) => { + e.target.innerText = "..."; e.target.disabled = true; this.fetchAndSaveGovHolidays(this.modalSelectedYear); }); return; } - // 1. Tri chronologique strict des jours yearHolidays.sort((a, b) => new Date(a.date) - new Date(b.date)); - // 2. Regroupement par blocs de jours consécutifs const blocks = []; let currentBlock = null; yearHolidays.forEach((e) => { - const d = new Date(e.date + "T00:00:00"); // Force locale - + const d = new Date(e.date + "T00:00:00"); if (!currentBlock) { currentBlock = { start: d, end: d }; blocks.push(currentBlock); } else { - // Calcul de l'écart en jours entre la date actuelle et la fin du bloc en cours - const diffTime = d.getTime() - currentBlock.end.getTime(); - const diffDays = Math.round(diffTime / (1000 * 60 * 60 * 24)); - - // Si l'écart est minime (<= 4 jours, pour absorber un éventuel week-end non stocké) - // on considère qu'on est toujours dans la même période de vacances. + const diffDays = Math.round( + (d.getTime() - currentBlock.end.getTime()) / (1000 * 60 * 60 * 24), + ); if (diffDays <= 4) { currentBlock.end = d; } else { - // Sinon, l'écart est grand : c'est une NOUVELLE période de vacances currentBlock = { start: d, end: d }; blocks.push(currentBlock); } } }); - // 3. Rendu HTML et déduction des noms let html = ""; blocks.forEach((block) => { - // Déduction intelligente du nom selon le mois de départ ET la durée const m = block.start.getMonth() + 1; const durationDays = Math.round( @@ -276,26 +273,19 @@ document.addEventListener("DOMContentLoaded", () => { ) + 1; let name = tr("leg_school_holidays"); - - if (m === 10 || m === 11) { - name = tr("vac_toussaint"); - } else if (m === 12 || m === 1) { - name = tr("vac_noel"); - } else if (m === 2 || m === 3) { - name = tr("vac_hiver"); - } else if (m === 4 || (m === 5 && durationDays > 6)) { + if (m === 10 || m === 11) name = tr("vac_toussaint"); + else if (m === 12 || m === 1) name = tr("vac_noel"); + else if (m === 2 || m === 3) name = tr("vac_hiver"); + else if (m === 4 || (m === 5 && durationDays > 6)) name = tr("vac_printemps"); - } else if (m === 5 && durationDays <= 6) { - name = tr("vac_ascension"); - } else if (m === 7 || m === 8) { - name = tr("vac_ete"); - } + else if (m === 5 && durationDays <= 6) name = tr("vac_ascension"); + else if (m === 7 || m === 8) name = tr("vac_ete"); html += ` ${name} - ${block.start.toLocaleDateString("fr-FR")} - ${block.end.toLocaleDateString("fr-FR")} + ${block.start.toLocaleDateString(window.appLang || "fr-FR")} + ${block.end.toLocaleDateString(window.appLang || "fr-FR")} `; }); @@ -1101,7 +1091,7 @@ document.addEventListener("DOMContentLoaded", () => {
${tr("leg_off_carole")}${parseFloat(stats.off.toFixed(1))} ${tr("fc_unit_days")}
${tr("leg_extra_off")}${parseFloat(stats.extra.toFixed(1))} ${tr("fc_unit_days")}
${tr("leg_pep_sick")}${parseFloat(stats.sick.toFixed(1))} ${tr("fc_unit_days")}
-
${tr("leg_presence")} Pep${parseFloat(stats.pep.toFixed(1))} ${tr("fc_unit_days")}
+
${tr("leg_presence")}${parseFloat(stats.pep.toFixed(1))} ${tr("fc_unit_days")}
`; } @@ -1188,6 +1178,35 @@ document.addEventListener("DOMContentLoaded", () => { }); document.addEventListener("touchend", (e) => this.handleTouchEnd(e)); } + const scrollWrapper = document.getElementById("planningTable-wrapper"); + if (scrollWrapper) { + scrollWrapper.addEventListener("scroll", async () => { + // Bloquer si on est déjà en train de charger + if (this._isAutoLoading) return; + + // Détection du bas (On descend dans le temps : passage à l'année suivante) + // On met une tolérance de 5px pour les calculs de pixels décimaux + if ( + scrollWrapper.scrollTop + scrollWrapper.clientHeight >= + scrollWrapper.scrollHeight - 5 + ) { + this._isAutoLoading = true; + await this.changeSchoolYear(1); + // On replace le scroll tout en haut pour la continuité visuelle + scrollWrapper.scrollTop = 5; + setTimeout(() => (this._isAutoLoading = false), 500); + } + // Détection du haut (On remonte le temps : passage à l'année précédente) + else if (scrollWrapper.scrollTop === 0) { + this._isAutoLoading = true; + await this.changeSchoolYear(-1); + // On replace le scroll tout en bas pour la continuité visuelle + scrollWrapper.scrollTop = + scrollWrapper.scrollHeight - scrollWrapper.clientHeight - 5; + setTimeout(() => (this._isAutoLoading = false), 500); + } + }); + } // --- GESTION MODALE VACANCES SCOLAIRES --- const btnOpen = document.getElementById("btnOpenHolidays"); diff --git a/pachafamily_source.md b/pachafamily_source.md index 4f86a45..a58d594 100644 --- a/pachafamily_source.md +++ b/pachafamily_source.md @@ -1,6 +1,6 @@ # 🦙 Source Code PachaFamily -> *Généré le 2026-05-05 16:41:29* +> *Généré le 2026-05-06 13:00:43* ### 📄 Fichier : `budget.php` ```php @@ -136,7 +136,7 @@ require __DIR__ . '/header.php';

- +
@@ -159,7 +159,7 @@ require __DIR__ . '/header.php';

📸

- +
@@ -196,7 +196,7 @@ require __DIR__ . '/header.php';
@@ -329,7 +329,7 @@ window.I18N = { 'leg_pep_sick': "", 'leg_off_carole': "", 'leg_extra_off': "", - 'leg_presence Pep': "", + 'leg_presence': "", 'fc_menu_kids_leaves': "", 'fc_clear': "", 'fc_unit_days': "", @@ -444,37 +444,21 @@ echo $report; require __DIR__ . '/includes/auth.php'; require_login('/login.php'); require __DIR__ . '/includes/db.php'; -require_once __DIR__ . '/includes/i18n.php'; // Toujours s'assurer que tr() est dispo +require_once __DIR__ . '/includes/i18n.php'; if (session_status() === PHP_SESSION_NONE) { session_start(); } -// --- 1. CONFIGURATION & DONNÉES --- - +// --- 1. CONFIGURATION --- $year = (int)date('Y'); $pageTitle = tr('gift_page_title'); $activePage = "gift-list"; $bodyClass = "pf-gift-list"; $pageCss = "/modules/gift-list/gift-list.css"; -// Personnes +$children = ['Pol', 'Pep', 'Elna', 'Bru', 'Guim']; $baseAdults = ['Laia', 'Laura', 'Avi Iaia']; -$children = ['Pol', 'Pep', 'Elna', 'Bru', 'Guim']; - -// Configuration des Vues -$VIEWS = [ - 'nadal' => ['TIO', 'NOEL', 'ROIS'], - 'anniversary' => ['ANNIV', 'SANT'], -]; - -// Vue courante -$currentView = strtolower($_GET['view'] ?? ($_SESSION['gift_view'] ?? 'nadal')); -if (!isset($VIEWS[$currentView])) $currentView = 'nadal'; -$_SESSION['gift_view'] = $currentView; - -$allowedOccasions = $VIEWS[$currentView]; - -// Logique spécifique : Adultes supplémentaires pour Anniversaires $extraAdults = ['Pauline', 'Papy JC', 'Mamy Caro']; + $adultsByChildForAnniv = [ 'Pol' => array_merge($baseAdults, $extraAdults), 'Pep' => array_merge($baseAdults, $extraAdults), @@ -483,63 +467,56 @@ $adultsByChildForAnniv = [ 'Guim' => $baseAdults, ]; -// Labels & Icônes (Utilisation des clés de traduction pour l'affichage) +$VIEWS = [ + 'nadal' => ['TIO', 'NOEL', 'ROIS'], + 'anniversary' => ['ANNIV', 'SANT'], +]; + +$currentView = strtolower($_GET['view'] ?? ($_SESSION['gift_view'] ?? 'nadal')); +if (!isset($VIEWS[$currentView])) $currentView = 'nadal'; +$_SESSION['gift_view'] = $currentView; +$allowedOccasions = $VIEWS[$currentView]; + $allOccasionLabels = [ - 'TIO' => tr('gift_occ_tio'), - 'NOEL' => tr('gift_occ_noel'), - 'ROIS' => tr('gift_occ_rois'), - 'ANNIV' => tr('gift_occ_anniv'), - 'SANT' => tr('gift_occ_sant'), + 'TIO' => tr('gift_occ_tio'), 'NOEL' => tr('gift_occ_noel'), 'ROIS' => tr('gift_occ_rois'), + 'ANNIV' => tr('gift_occ_anniv'), 'SANT' => tr('gift_occ_sant') ]; - $occasionIcons = [ - 'TIO' => '/modules/gift-list/assets/img/tio.png', - 'NOEL' => '/modules/gift-list/assets/img/santa.png', - 'ROIS' => '/modules/gift-list/assets/img/reis.png', - 'ANNIV' => '/modules/gift-list/assets/img/corona.png', - 'SANT' => '/modules/gift-list/assets/img/sant.png', + 'TIO' => '/modules/gift-list/assets/img/tio.png', 'NOEL' => '/modules/gift-list/assets/img/santa.png', + 'ROIS' => '/modules/gift-list/assets/img/reis.png', 'ANNIV' => '/modules/gift-list/assets/img/corona.png', + 'SANT' => '/modules/gift-list/assets/img/sant.png' ]; -$tableGifts = 'pf_gifts'; - -// --- 2. RÉCUPÉRATION DES DONNÉES --- - +// --- 2. DONNÉES --- $inMarks = implode(',', array_fill(0, count($allowedOccasions), '?')); -$sql = "SELECT * FROM {$tableGifts} WHERE year = ? AND occasion IN ($inMarks) ORDER BY adult_name, child_name, occasion, created_at"; +// Tri: Par Fête, puis Enfant, puis Adulte +$sql = "SELECT * FROM pf_gifts WHERE year = ? AND occasion IN ($inMarks) ORDER BY occasion ASC, child_name ASC, adult_name ASC"; $stmt = $pdo->prepare($sql); -$params = array_merge([$year], $allowedOccasions); -$stmt->execute($params); -$gifts = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: []; +$stmt->execute(array_merge([$year], $allowedOccasions)); +$gifts = $stmt->fetchAll(PDO::FETCH_ASSOC); -$byOccasion = []; -foreach ($gifts as $gift) { - $byOccasion[$gift['occasion']][$gift['child_name']][$gift['adult_name']][] = $gift; +$data = []; +$adultsInView = []; + +foreach ($gifts as $g) { + $data[$g['occasion']][$g['child_name']]['gifts'][] = $g; + $data[$g['occasion']][$g['child_name']]['totals'][$g['adult_name']] = ($data[$g['occasion']][$g['child_name']]['totals'][$g['adult_name']] ?? 0) + $g['amount']; + $adultsInView[$g['adult_name']] = true; } +$allAdultsList = array_keys($adultsInView); sort($allAdultsList); -$occasionsToShow = array_values(array_intersect(array_keys($allOccasionLabels), $allowedOccasions)); - -// --- 3. CALCUL TRICOUNT --- - -$people = $baseAdults; -$adultsInDb = array_column($gifts, 'adult_name'); -$payersInDb = array_column($gifts, 'payer_name'); -$people = array_values(array_unique(array_merge($people, $adultsInDb, $payersInDb))); +// --- 3. TRICOUNT --- +$people = array_values(array_unique(array_merge($baseAdults, array_column($gifts, 'adult_name'), array_column($gifts, 'payer_name')))); $people = array_filter($people); - $matrix = []; -foreach ($people as $p1) { - foreach ($people as $p2) $matrix[$p1][$p2] = 0.0; -} +foreach ($people as $p1) { foreach ($people as $p2) $matrix[$p1][$p2] = 0.0; } foreach ($gifts as $g) { $adult = $g['adult_name']; $payer = $g['payer_name'] ?? $g['adult_name']; $amt = (float)$g['amount']; - if ($amt > 0 && $adult && $payer && $adult !== $payer) { - if (isset($matrix[$adult][$payer])) { - $matrix[$adult][$payer] += $amt; - } + $matrix[$adult][$payer] += $amt; } } @@ -547,425 +524,452 @@ $settlements = []; $countPeople = count($people); for ($i = 0; $i < $countPeople; $i++) { for ($j = $i + 1; $j < $countPeople; $j++) { - $a = $people[$i]; - $b = $people[$j]; + $a = $people[$i]; $b = $people[$j]; $net = $matrix[$a][$b] - $matrix[$b][$a]; - - if ($net > 0.01) { - $settlements[] = ['from' => $a, 'to' => $b, 'amount' => $net]; - } elseif ($net < -0.01) { - $settlements[] = ['from' => $b, 'to' => $a, 'amount' => -$net]; - } + if ($net > 0.01) { $settlements[] = ['from' => $a, 'to' => $b, 'amount' => $net]; } + elseif ($net < -0.01) { $settlements[] = ['from' => $b, 'to' => $a, 'amount' => -$net]; } } } -// --- 4. DÉBUT DU RENDU HTML --- require __DIR__ . '/header.php'; ?>
-

-
+

🎁

+
-
-

+
+ 🔍 + +
+
+ 👦 +
+
+ + + + +
+
- -

- +
+
+ 👤 +
+
+ + + + +
+
+
- -
-

- - +
+ +
+

+ + +

+ + [], 'totals' => []]; + $adultsForThisChild = ($currentView === 'anniversary' && in_array($child, ['Pol', 'Pep'])) ? array_merge($baseAdults, $extraAdults) : $baseAdults; + ?> +
+
+

👦

+ +
+ +
+ $tot): ?> + 👤 : + +
+ + +

+ + +
+ +
+
+

+ + 🔗 +

+ 👤 + +
+ +
+ +
+ +
- -

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
-
- - -
-
- - -
-
- - - - - - -
- ( €) - - - - -
-
- - - () - -
- - - -
-
+
-
-

- prepare("SELECT adult_name, child_name, occasion, SUM(amount) AS total FROM {$tableGifts} WHERE year = ? AND occasion IN ($inMarks) GROUP BY adult_name, child_name, occasion ORDER BY adult_name, child_name, occasion"); - $stmtSum->execute($params); - $sums = $stmtSum->fetchAll(PDO::FETCH_ASSOC); - ?> -
- - - - - - - - - - - - - - -
Total
-
-
- -
-

Tricount

-
- - - - - - - - - - - - - 0 ? 'cl-mtx-owe' : 'cl-mtx-empty'); - $display = $isDiag || $val == 0 ? '—' : number_format($val, 0, ',', ' ') . ' €'; - ?> - - - - - -
-
- -

+
+

⚖️

+ -

+

-
    +
      -
    • +
    • + à + +
    -
-
-

-
- - - - - - +
+ +
+
+ - - - - - - + + - - -
- - 🔗 - - \
-
+ + + + + + + + + + + + +
+
- - - - + ``` @@ -1424,19 +1428,16 @@ p { /* 📱 BOTTOM SHEET MODALES MOBILE */ .pf-modal { - align-items: flex-end !important; - padding: 0; + align-items: center !important; /* On remet au centre */ + padding: 20px; } .pf-modal-content { width: 100% !important; max-width: none !important; - border-radius: 24px 24px 0 0 !important; - padding: 24px 20px !important; - padding-bottom: env(safe-area-inset-bottom, 30px) !important; - transform: translateY(100%); - animation: slideUpSheet 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards !important; - max-height: 92vh; - margin: 0 !important; + border-radius: 20px !important; /* On garde les arrondis partout */ + transform: none !important; + animation: pfModalPop 0.3s ease !important; /* On remet l'animation desktop */ + margin: auto !important; } .pf-modal-content::before { content: ""; @@ -1462,6 +1463,99 @@ p { } } +/* === BOUTONS D'ACTION ICÔNES UNIVERSELS (Édition / Suppression) === */ +.btn-icon-action { + border: none; + background: transparent; + cursor: pointer; + font-size: 1.1rem; + line-height: 1; + padding: 6px; + border-radius: 6px; + transition: all 0.2s; + text-decoration: none; + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; +} +.btn-icon-action.edit { + color: var(--primary); +} +.btn-icon-action.edit:hover { + background: #eff6ff; /* Fond bleu très clair au survol */ +} +.btn-icon-action.delete { + color: var(--danger); +} +.btn-icon-action.delete:hover { + background: #fef2f2; /* Fond rouge très clair au survol */ +} + +/* === 13. PAGE DE CONNEXION (LOGIN) === */ +.pf-login-wrapper { + display: flex; + justify-content: center; + align-items: center; + min-height: calc(100vh - 200px); + padding: 20px; +} + +.pf-login-card { + width: 100%; + max-width: 400px; + padding: 32px; + background: white; + border-radius: 16px; + box-shadow: var(--shadow-lg); + border: 1px solid var(--border-light); +} + +.pf-login-header { + text-align: center; + margin-bottom: 24px; +} + +.pf-login-header .pf-login-icon { + width: 60px; /* Tu peux ajuster cette valeur selon le rendu voulu */ + height: auto; + margin-bottom: 15px; + border-radius: 12px; /* Optionnel : ajoute un léger arrondi si ton favicon est carré */ +} + +.pf-login-header h1 { + font-size: 1.8rem; + margin: 0; + color: var(--text-main); +} + +.pf-login-header p { + color: var(--text-muted); + margin-top: 8px; + font-size: 0.95rem; +} + +.pf-login-error { + background: #fef2f2; + color: #ef4444; + padding: 12px; + border-radius: 8px; + border: 1px solid #fca5a5; + margin-bottom: 20px; + font-size: 0.9rem; + text-align: center; + font-weight: 600; +} + +.pf-btn-block { + width: 100%; + justify-content: center; + margin-top: 10px; + padding: 14px; + font-size: 1.05rem; +} + ``` --- @@ -1879,7 +1973,7 @@ return [ 'tests_copy_report' => 'Copiar l\'informe', 'tests_waiting' => 'Esperant l\'inici...', 'tests_report_copied' => 'Informe copiat al porta-retalls!', - + 'tests_live_preview' => 'Previsualització en viu', // ========================================== // GLOBAL & NAVIGATION // ========================================== @@ -1936,6 +2030,7 @@ return [ 'btn_logout' => 'Tancar sessió', 'error_missing_fields' => 'Camps obligatoris.', 'error_invalid_credentials' => 'Identificadors incorrectes.', + 'login_subtitle' => 'Si us plau, identifiqueu-vos per continuar', // ========================================== // ACCUEIL / INDEX @@ -1995,6 +2090,11 @@ return [ 'fc_menu_carole' => 'Permisos Carole', 'fc_clear' => 'Esborrar', 'fc_menu_kids_leaves' => 'Permisos nens', + 'fc_err_save_snap' => 'Error en desar el correctiu.', + 'fc_err_fetch_gov' => 'Error en la connexió amb l’API governamental.', + 'fc_err_no_data_gov' => 'No s’han trobat dades a l’API del govern per a aquest any.', + 'fc_err_action' => 'Error en l’acció: ', + 'leg_presence' => 'Presència Pep', 'leg_school_holidays' => 'Vacances Escolars', 'leg_public_holiday' => 'Festiu', @@ -2003,7 +2103,6 @@ return [ 'leg_centre' => 'Casal', 'leg_avis' => 'Avís', 'leg_pep_sick' => 'Pep Malalt', - 'leg_presence' => 'Presència', 'vac_toussaint' => 'Vacances de Tots Sants', 'vac_noel' => 'Vacances de Nadal', @@ -2383,7 +2482,7 @@ return [ 'gift_col_party' => 'Festa', 'gift_debtor' => 'Deutor', 'gift_creditor' => 'Creditor', - 'gift_liquidations' => 'Liquidacions', + 'gift_liquidations' => 'Tricount', 'gift_no_debt' => 'Cap deute pendent.', 'gift_owes' => 'ha de pagar', 'gift_to' => 'a', @@ -2398,6 +2497,11 @@ return [ 'gift_modal_price' => 'Preu (€)', 'gift_modal_link' => 'Enllaç (opcional)', 'gift_confirm_delete' => 'Vols eliminar aquest regal?', + 'gift_filter_all_children' => 'Tots els nens', + 'gift_filter_all_adults' => 'Tots els adults', + 'gift_empty_state_no_gifts' => 'Cap regal de moment.', + 'gift_empty_state_no_filter' => 'Cap regal correspon al filtre.', + 'gift_view_matrix' => 'Veure la matriu detallada', ]; ``` @@ -2420,6 +2524,7 @@ return [ 'tests_copy_report' => 'Copier le rapport', 'tests_waiting' => 'En attente du lancement...', 'tests_report_copied' => 'Rapport copié dans le presse-papier !', + 'tests_live_preview' => 'Aperçu en direct', // ========================================== @@ -2479,6 +2584,7 @@ return [ 'btn_logout' => 'Déconnexion', 'error_missing_fields' => 'Champs obligatoires.', 'error_invalid_credentials' => 'Identifiants incorrects.', + 'login_subtitle' => 'Veuillez vous identifier pour continuer', // ========================================== // ACCUEIL / INDEX @@ -2538,6 +2644,11 @@ return [ 'fc_menu_carole' => 'Congés Carole', 'fc_clear' => 'Effacer', 'fc_menu_kids_leaves' => 'Congés Enfants', + 'fc_err_save_snap' => 'Erreur lors de la sauvegarde du correctif.', + 'fc_err_fetch_gov' => 'Erreur lors de la connexion à l’API gouvernementale.', + 'fc_err_no_data_gov' => 'Aucune donnée trouvée sur l’API du gouvernement pour cette année.', + 'fc_err_action' => 'Erreur lors de l’action : ', + 'leg_presence' => 'Présence Pep', 'leg_school_holidays' => 'Vacances Scolaires', 'leg_public_holiday' => 'Férié', @@ -2546,7 +2657,6 @@ return [ 'leg_centre' => 'Centre', 'leg_avis' => 'Avis', 'leg_pep_sick' => 'Pep Malade', - 'leg_presence' => 'Présence', 'vac_toussaint' => 'Vacances de la Toussaint', 'vac_noel' => 'Vacances de Noël', @@ -2908,7 +3018,7 @@ return [ 'gift_page_title' => 'PachaFamily - Liste de cadeaux', 'gift_occ_tio' => 'Tió', 'gift_occ_noel' => 'Noël', - 'gift_occ_rois' => 'Rois', + 'gift_occ_rois' => 'Rois mages', 'gift_occ_anniv' => 'Anniversaire', 'gift_occ_sant' => 'Saint', 'gift_main_title' => 'Liste de cadeaux %s', @@ -2925,7 +3035,7 @@ return [ 'gift_col_party' => 'Fête', 'gift_debtor' => 'Débiteur', 'gift_creditor' => 'Créancier', - 'gift_liquidations' => 'Liquidations', + 'gift_liquidations' => 'Tricount', 'gift_no_debt' => 'Aucune dette en cours.', 'gift_owes' => 'doit', 'gift_to' => 'à', @@ -2940,6 +3050,11 @@ return [ 'gift_modal_price' => 'Prix (€)', 'gift_modal_link' => 'Lien (optionnel)', 'gift_confirm_delete' => 'Voulez-vous vraiment supprimer ce cadeau ?', + 'gift_filter_all_children' => 'Tous les enfants', + 'gift_filter_all_adults' => 'Tous les adultes', + 'gift_empty_state_no_gifts' => 'Aucun cadeau pour le moment.', + 'gift_empty_state_no_filter' => 'Aucun cadeau ne correspond au filtre.', + 'gift_view_matrix' => 'Voir la matrice détaillée', ]; ``` @@ -3078,28 +3193,44 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { require __DIR__ . '/header.php'; ?> -