From be2edcce824cba995752e593e320aad44dfabd83 Mon Sep 17 00:00:00 2001 From: "fefe.clochette" Date: Tue, 5 May 2026 20:50:22 +0200 Subject: [PATCH] filtre multiple --- gift-list.php | 619 +++++++++++++++++--------------- modules/gift-list/gift-list.css | 95 +++++ 2 files changed, 432 insertions(+), 282 deletions(-) diff --git a/gift-list.php b/gift-list.php index 7ec0637..704c6fa 100644 --- a/gift-list.php +++ b/gift-list.php @@ -8,15 +8,15 @@ 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"; +$children = ['Pol', 'Pep', 'Elna', 'Bru', 'Guim']; $baseAdults = ['Laia', 'Laura', 'Avi Iaia']; -$children = ['Pol', 'Pep', 'Elna', 'Bru', 'Guim']; $extraAdults = ['Pauline', 'Papy JC', 'Mamy Caro']; $adultsByChildForAnniv = [ @@ -35,71 +35,46 @@ $VIEWS = [ $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' ]; -// --- 2. RÉCUPÉRATION DES DONNÉES --- +// --- 2. DONNÉES --- $inMarks = implode(',', array_fill(0, count($allowedOccasions), '?')); -// Le tri SQL regroupe par Occasion, puis par Enfant, puis par Adulte -$sql = "SELECT * FROM pf_gifts WHERE year = ? AND occasion IN ($inMarks) ORDER BY occasion ASC, child_name ASC, adult_name ASC, created_at DESC"; +// 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); $stmt->execute(array_merge([$year], $allowedOccasions)); -$gifts = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: []; +$gifts = $stmt->fetchAll(PDO::FETCH_ASSOC); -$dataByOccasion = []; +$data = []; $adultsInView = []; foreach ($gifts as $g) { - $occ = $g['occasion']; - $child = $g['child_name']; - $adult = $g['adult_name']; - - // Groupement structuré : Occasion -> Enfant -> Cadeaux - $dataByOccasion[$occ][$child]['gifts'][] = $g; - - // Totaux pour les petites pills sous le nom de l'enfant - if (!isset($dataByOccasion[$occ][$child]['totals'][$adult])) { - $dataByOccasion[$occ][$child]['totals'][$adult] = 0; - } - $dataByOccasion[$occ][$child]['totals'][$adult] += (float)$g['amount']; - - $adultsInView[$adult] = true; + $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); -$allAdultsList = array_keys($adultsInView); -sort($allAdultsList); -$occasionsToShow = array_values(array_intersect(array_keys($allOccasionLabels), $allowedOccasions)); - -// --- 3. CALCUL TRICOUNT (Bilan financier global de la vue) --- +// --- 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) { $matrix[$adult][$payer] += $amt; } @@ -109,8 +84,7 @@ $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]; } @@ -123,116 +97,105 @@ require __DIR__ . '/header.php';
-

-
+

🎁

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

- - - - + +

- [], 'totals' => []]; - $childGifts = $childData['gifts'] ?? []; - $childTotals = $childData['totals'] ?? []; - $adultsForChild = ($currentView === 'anniversary') ? ($adultsByChildForAnniv[$childName] ?? $baseAdults) : $baseAdults; - - // Sécurisation du JSON pour éviter l'erreur "openGiftModal is not defined" - $addBtnData = json_encode([ - 'child' => $childName, - 'occ' => $occCode, - 'adults' => array_values($adultsForChild) - ], JSON_HEX_APOS | JSON_HEX_QUOT); + [], 'totals' => []]; + $adultsForThisChild = ($currentView === 'anniversary' && in_array($child, ['Pol', 'Pep'])) ? array_merge($baseAdults, $extraAdults) : $baseAdults; ?> -
-
-

👦

- -
+
+
+

👦

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

+ + +
+ +
+
+

+ + 🔗 +

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

- - -
- -
-
-

- - - 🔗 - -

- -
- 👤 -
-
- - -
- - - -
- -
- -
+ +
@@ -270,8 +233,7 @@ require __DIR__ . '/header.php'; @@ -287,44 +249,25 @@ require __DIR__ . '/header.php';
-

- +

Cadeau

+
-
- - - - - - -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- + + + + + + + +
+
+
+
+
+
@@ -332,63 +275,132 @@ require __DIR__ . '/header.php';
diff --git a/modules/gift-list/gift-list.css b/modules/gift-list/gift-list.css index d7e91a2..39a9f78 100644 --- a/modules/gift-list/gift-list.css +++ b/modules/gift-list/gift-list.css @@ -282,3 +282,98 @@ grid-template-columns: 1fr; } } +/* === COMPOSANT MULTI-SELECT VANILLA === */ +.pf-multi-select { + position: relative; + display: inline-block; +} + +/* Le bouton déclencheur (réutilise le style des filtres) */ +.pf-ms-trigger { + padding: 6px 16px; + border-radius: 20px; + border: 1px solid var(--border-light); + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(8px); + font-size: 0.85rem; + font-weight: 600; + color: var(--text-main); + cursor: pointer; + box-shadow: var(--shadow-sm); + display: flex; + align-items: center; + gap: 6px; + user-select: none; +} +.pf-ms-trigger:hover { + border-color: #cbd5e1; +} +.pf-ms-trigger.active { + border-color: var(--primary); + box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.1); +} + +/* Le menu déroulant */ +.pf-ms-dropdown { + display: none; + position: absolute; + top: calc(100% + 8px); + left: 0; + background: white; + border: 1px solid var(--border-light); + border-radius: 12px; + padding: 8px; + box-shadow: var(--shadow-lg); + z-index: 100; + min-width: 200px; + flex-direction: column; + gap: 4px; + max-height: 60vh; + overflow-y: auto; +} +.pf-ms-dropdown.open { + display: flex; + animation: popDown 0.2s cubic-bezier(0.16, 1, 0.3, 1) forwards; +} + +/* Les options (checkboxes) */ +.pf-ms-option { + display: flex; + align-items: center; + gap: 8px; + font-size: 0.85rem; + font-weight: 500; + cursor: pointer; + padding: 8px 10px; + border-radius: 6px; + color: var(--text-main); + transition: 0.2s; +} +.pf-ms-option:hover { + background: #f8fafc; +} +.pf-ms-option input[type="checkbox"] { + margin: 0; + cursor: pointer; + accent-color: var(--primary); + width: 16px; + height: 16px; +} +.pf-ms-option.is-all { + font-weight: 700; + border-bottom: 1px solid #e2e8f0; + padding-bottom: 10px; + margin-bottom: 4px; + border-radius: 6px 6px 0 0; +} + +@keyframes popDown { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +}