diff --git a/docker/schema_family.sql b/docker/schema_family.sql index 560bfed..573cf2e 100644 --- a/docker/schema_family.sql +++ b/docker/schema_family.sql @@ -309,7 +309,8 @@ CREATE TABLE IF NOT EXISTS pf_holidays ( budget_extra DECIMAL(10,2) DEFAULT 0, notes TEXT DEFAULT NULL, vehicle_id INT DEFAULT NULL, - return_step_id INT DEFAULT NULL, -- 🔥 NOUVEAU : Point de bascule du retour + return_step_id INT DEFAULT NULL, + image_url VARCHAR(500) DEFAULT NULL, FOREIGN KEY (vehicle_id) REFERENCES pf_vehicles(id) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/modules/holidays/holidays.css b/modules/holidays/holidays.css index ffc7f2e..368b4ac 100644 --- a/modules/holidays/holidays.css +++ b/modules/holidays/holidays.css @@ -1,11 +1,13 @@ /* modules/holidays/holidays.css */ -/* --- 1. VARIABLES & BASE --- */ +/* ========================================================================== + 1. VARIABLES & BASE + ========================================================================== */ -/* Bloque le défilement de la page en arrière-plan */ body.no-scroll { overflow: hidden !important; } + :root { --primary: #2563eb; --primary-hover: #1d4ed8; @@ -40,7 +42,13 @@ body.no-scroll { padding-bottom: 50px; } -/* --- 2. EN-TÊTE (Refonte Responsive) --- */ +.hol-hidden { + display: none !important; +} + +/* ========================================================================== + 2. EN-TÊTE DE LA LISTE (list.php) + ========================================================================== */ .pf-holidays__titlebar { background: transparent; padding-bottom: 1rem; @@ -57,7 +65,7 @@ body.no-scroll { align-items: center; gap: 20px; flex-wrap: wrap; - flex: 1; /* Prend l'espace disponible */ + flex: 1; } .hol-main-title { @@ -75,7 +83,7 @@ body.no-scroll { } .hol-year-select { - width: auto !important; /* Force la largeur au contenu sur PC */ + width: auto !important; padding: 6px 12px; font-weight: bold; cursor: pointer; @@ -100,7 +108,9 @@ body.no-scroll { flex-shrink: 0; } -/* --- 3. BOUTONS --- */ +/* ========================================================================== + 3. BOUTONS + ========================================================================== */ .hol-add-btn, .hol-map-toggle, .pf-btn { @@ -123,6 +133,7 @@ body.no-scroll { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); color: white; } + .hol-add-btn:hover, .pf-btn:hover { transform: translateY(-2px); @@ -134,6 +145,7 @@ body.no-scroll { color: #0f766e; border: 1px solid #ccfbf1; } + .hol-map-toggle:hover { background: #f0fdfa; color: #0d9488; @@ -146,37 +158,589 @@ body.no-scroll { border: 1px solid var(--border-strong); box-shadow: none; } + .pf-btn.btn-secondary:hover { background: var(--bg-page); color: var(--text-main); } -/* Petit bouton + pour les colonnes */ -.btn-icon-small { +.pf-btn-small { + padding: 6px 14px !important; + font-size: 0.85rem !important; + width: auto !important; + height: auto !important; + margin: 0 !important; +} + +.btn-icon-small, +.hol-btn-action-icon { background: var(--bg-panel) !important; border: 1px solid var(--border-light) !important; border-radius: 6px !important; - width: 32px !important; - height: 32px !important; - min-width: 32px !important; + width: 26px !important; + height: 26px !important; + min-width: 26px !important; + min-height: 26px !important; padding: 0 !important; margin: 0 !important; display: flex !important; align-items: center; justify-content: center; - font-size: 0.9rem; + font-size: 0.8rem; cursor: pointer; transition: all 0.2s; box-shadow: var(--shadow-sm); } -.btn-icon-small:hover { +.btn-icon-small:hover, +.hol-btn-action-icon:hover { background: var(--bg-subtle) !important; border-color: var(--border-strong) !important; transform: scale(1.05); } -/* --- 4. CARTES --- */ +/* ========================================================================== + 4. HERO HEADER IMMERSIF (detail.php) + ========================================================================== */ +.hol-hero-banner { + position: relative; + padding: 24px; + border-radius: var(--radius-l); + color: #ffffff; + margin-bottom: 20px; + box-shadow: var(--shadow-md); + overflow: hidden; +} + +.hol-hero-bg-img { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + z-index: 0; +} + +.hol-hero-overlay { + position: absolute; + inset: 0; + + z-index: 1; +} + +.hol-hero-content { + position: relative; + z-index: 2; +} + +.hol-hero-top { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 10px; +} + +.hol-hero-back-link { + color: white; + text-decoration: none; + font-size: 0.85rem; + font-weight: 600; + opacity: 0.8; + transition: opacity 0.2s; +} + +.hol-hero-back-link:hover { + opacity: 1; +} + +.hol-hero-status-badge { + font-size: 0.75rem; + background: rgba(255, 255, 255, 0.2); + padding: 4px 10px; + border-radius: 12px; + font-weight: bold; + backdrop-filter: blur(4px); +} + +.hol-hero-title { + margin: 0 0 5px 0; + font-size: 1.8rem; + line-height: 1.1; + color: #ffffff; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); +} + +.hol-hero-date-badge { + font-size: 0.85rem; + opacity: 0.8; + margin-bottom: 20px; + display: flex; + align-items: center; + gap: 6px; +} + +/* --- PILLS (Metrics Route & Logistique) --- */ +.hol-hero-pills { + display: flex; + gap: 10px; + overflow-x: auto; + margin-bottom: 24px; + padding-bottom: 5px; + scrollbar-width: none; + -webkit-overflow-scrolling: touch; +} + +.hol-pill-block { + display: inline-flex; +} + +.hol-pill { + background: rgba(255, 255, 255, 0.15); + backdrop-filter: blur(8px); + border: 1px solid rgba(255, 255, 255, 0.2); + padding: 6px 12px; + border-radius: 20px; + font-size: 0.7rem; + font-weight: 600; + white-space: nowrap; + display: inline-flex; + align-items: center; + gap: 6px; +} + +.hol-pill-action { + opacity: 0.7; + font-size: 0.75rem; + cursor: pointer; + margin-left: 4px; + transition: opacity 0.2s; +} + +.hol-pill-action:hover { + opacity: 1; +} + +/* --- FINANCES GLOBALES --- */ +.hol-hero-finances { + display: flex; + justify-content: space-between; + align-items: flex-end; + margin-bottom: 12px; +} + +.hol-finance-block { + display: flex; + flex-direction: column; +} + +.hol-finance-right { + text-align: right; +} + +.hol-finance-label { + font-size: 0.8rem; + opacity: 0.8; + text-transform: uppercase; + font-weight: 600; +} + +.hol-finance-value { + font-size: 1.8rem; + font-weight: 800; + line-height: 1.1; +} + +.hol-finance-value-due { + font-size: 1.2rem; + font-weight: 800; + color: #fca5a5; +} + +.hol-hero-progress-labels { + display: flex; + justify-content: space-between; + font-size: 0.75rem; + font-weight: 600; +} + +.hol-label-paid-text { + color: #a7f3d0; +} + +.hol-label-saved-text { + color: #bfdbfe; +} + +/* ========================================================================== + 5. BARRE D'ACTIONS RAPIDES & CARTE + ========================================================================== */ +.hol-quick-actions-bar { + display: flex; + gap: 10px; + margin-bottom: 24px; + overflow-x: auto; + padding-bottom: 5px; + scrollbar-width: none; + -webkit-overflow-scrolling: touch; +} + +.hol-quick-action-btn { + flex-shrink: 0; + display: flex; + align-items: center; + gap: 6px; + background: var(--bg-panel); +} + +.hol-map-wrapper { + margin-bottom: 24px; + border-radius: var(--radius-l); + overflow: hidden; + box-shadow: var(--shadow-sm); + border: 1px solid var(--border-light); +} + +.hol-map-panel-header { + background: var(--bg-page); + padding: 10px 15px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.hol-map-title { + margin: 0; + font-size: 0.95rem; + color: var(--text-main); +} + +.hol-map-canvas { + width: 100%; + height: 350px; + background: #e2e8f0; + z-index: 1; +} + +.hol-map-legend { + display: flex; + gap: 12px; + font-size: 0.75rem; + color: var(--text-muted); + background: transparent; + padding: 2px 8px; + border: none; +} + +.hol-legend-item { + display: flex; + align-items: center; + gap: 4px; +} + +.hol-legend-color { + display: inline-block; + width: 12px; + height: 4px; + border-radius: 2px; +} + +.hol-legend-color.aller { + background: #3b82f6; +} + +.hol-legend-color.interm { + background: #8b5cf6; +} + +.hol-legend-color.retour { + background: transparent; + height: 0; + border-bottom: 3px dashed #f97316; + border-radius: 0; +} + +/* ========================================================================== + 6. TIMELINE & CARNET DE ROUTE + ========================================================================== */ +.hol-panel { + background: var(--bg-panel); + border-radius: var(--radius-l); + box-shadow: var(--shadow-sm); + border: 1px solid var(--border-light); + display: flex; + flex-direction: column; + overflow: hidden; +} + +.hol-panel-timeline { + height: auto; + min-height: 500px; +} + +.hol-timeline-header { + background: var(--bg-page); + padding: 15px 20px; + border-bottom: 1px solid var(--border-light); + display: flex; + justify-content: space-between; + align-items: center; +} + +.hol-timeline-header h3 { + margin: 0; + font-size: 1.1rem; + color: var(--text-main); +} + +.hol-panel-body { + padding: 15px; + overflow-y: auto; + flex: 1; +} + +.hol-empty-steps-text { + color: var(--text-muted); + font-style: italic; + text-align: center; + margin-top: 40px; +} + +.hol-checkpoint { + border: 1px solid var(--border-light); + border-radius: 8px; + margin-bottom: 15px; + overflow: hidden; + background: var(--bg-panel); +} + +.hol-step-header { + padding: 6px 8px; + border-bottom: 1px solid var(--border-light); + display: flex; + flex-direction: column; + gap: 8px; + background: var(--bg-page); +} + +.hol-step-row-top { + display: flex; + align-items: flex-start; + gap: 10px; + width: 100%; +} + +.hol-step-icon { + border-radius: 6px; + display: flex; + align-items: center; + justify-content: center; + font-size: 1rem; + flex-shrink: 0; + margin-top: 2px; + padding: 2px 6px; +} + +.hol-step-icon-origin { + background: #ecfdf5; + color: #059669; +} + +.hol-step-icon-destination { + background: #fef2f2; + color: #e11d48; +} + +.hol-step-icon-stop { + background: transparent; + color: #64748b; +} + +.hol-step-title { + flex: 1; + font-size: 1.05rem; + font-weight: 700; + color: var(--text-main); + line-height: 1.3; + word-break: break-word; + cursor: pointer; + padding-top: 4px; +} + +.hol-step-title:hover { + color: var(--primary); +} + +.hol-step-controls { + flex-shrink: 0; + display: flex; + flex-direction: column; + align-items: center; +} + +.hol-drag-handle { + color: #cbd5e1; + font-size: 1.4rem; + cursor: grab; + user-select: none; + line-height: 1; +} + +.hol-step-arrows button { + background: transparent; + border: none; + color: #94a3b8; + font-size: 0.75rem; + padding: 4px 8px; + cursor: pointer; + line-height: 1; +} + +.hol-step-row-bottom { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 5px; + width: 100%; +} + +.hol-step-meta { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 6px; +} + +.hol-tag-return { + background: #fff7ed; + color: #ea580c; + padding: 2px 6px; + border-radius: 4px; + font-size: 0.75rem; + font-weight: 700; + border: 1px solid #ffedd5; + line-height: 1.2; +} + +.hol-step-date { + font-size: 0.8rem; + color: #64748b; + background: var(--bg-page); + padding: 2px 6px; + border-radius: 4px; + border: 1px solid var(--border-light); + line-height: 1.2; +} + +.hol-step-actions { + display: flex; + align-items: center; + gap: 8px; + margin-left: auto; +} + +.hol-step-price { + font-weight: 800; + color: var(--primary); + white-space: nowrap; +} + +.hol-cp-body { + padding: 10px 15px; +} + +/* --- DÉPENSES DANS UNE ÉTAPE --- */ +.hol-expense-wrapper { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 4px; + margin-bottom: 8px; + border-bottom: 1px dashed var(--bg-subtle); + padding-bottom: 8px; +} + +.hol-expense-wrapper:last-child { + margin-bottom: 0; + border-bottom: none; + padding-bottom: 0; +} + +.hol-expense-main { + display: flex; + justify-content: space-between; + align-items: flex-start; + width: 100%; + font-size: 0.85rem; + gap: 8px; +} + +.hol-expense-name { + flex: 1; + min-width: 0; + word-break: break-word; + color: var(--text-muted); + font-weight: 500; +} + +.hol-custom-gps-link { + cursor: pointer; + color: var(--primary); + text-decoration: underline; + font-weight: 600; +} + +.hol-expense-amount { + color: var(--text-main); + font-weight: bold; +} + +.status-paid { + color: #10b981; + margin-left: 5px; +} + +.status-pending { + color: #f59e0b; + margin-left: 5px; +} + +.hol-expense-note { + font-size: 0.75rem; + color: var(--text-muted); + margin-top: 2px; + padding-left: 24px; + word-break: break-all; +} + +.hol-empty-step { + font-size: 0.8rem; + color: var(--text-muted); + font-style: italic; + padding: 5px 0; +} + +/* ========================================================================== + 7. NOTES GLOBALE DU VOYAGE + ========================================================================== */ +.hol-notes-card { + margin-top: 24px; +} + +.hol-notes-textarea { + resize: vertical; + width: 100%; + line-height: 1.5; + padding: 12px; +} + +.hol-notes-actions { + text-align: right; + margin-top: 12px; +} + +/* ========================================================================== + 8. CARTES DE LA LISTE (list.php) + ========================================================================== */ .hol-ideas-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); @@ -230,19 +794,6 @@ body.no-scroll { gap: 4px; } -.hol-notes { - font-size: 0.85rem; - color: var(--text-muted); - display: -webkit-box; - -webkit-line-clamp: 2; - line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - margin: 0; - font-style: italic; -} - -/* --- 5. UTILITAIRES STATUTS --- */ .bg-green-100 { background-color: #dcfce7; } @@ -268,17 +819,20 @@ body.no-scroll { color: #4b5563; } -/* --- 6. MODALE & FORMULAIRE (Refonte Centrage & Largeur) --- */ +/* ========================================================================== + 9. MODALES & DIALOGUES + ========================================================================== */ .pf-modal { display: none; position: fixed; inset: 0; z-index: 9999; - align-items: center; /* Centrage Vertical */ - justify-content: center; /* Centrage Horizontal */ + align-items: center; + justify-content: center; background: rgba(15, 23, 42, 0.6); backdrop-filter: blur(4px); } + .pf-modal.open { display: flex; } @@ -286,8 +840,8 @@ body.no-scroll { .pf-modal-content { position: relative; background: var(--bg-panel); - width: 95%; /* Responsive */ - max-width: 1100px; /* Largeur augmentée pour 3 colonnes */ + width: 95%; + max-width: 1100px; max-height: 90vh; overflow-y: auto; border-radius: 20px; @@ -295,45 +849,164 @@ body.no-scroll { padding: 32px; display: flex; flex-direction: column; - margin: auto; /* Sécurité centrage */ + margin: auto; } -.hol-modal-content { - max-width: 800px; - width: 95%; +/* --- Modale Étape (Checkpoint) --- */ +.hol-modal-cp { + max-width: 600px; + padding: 0; + overflow: hidden; } -.hol-flex-1 { - flex: 1; -} - -.hol-flex-2 { - flex: 2; -} - -.hol-date-range-group { +.hol-modal-header { display: flex; + justify-content: space-between; + align-items: center; + padding: 20px 20px 0 20px; +} + +.hol-modal-title { + margin: 0; + font-size: 1.3rem; + color: var(--text-main); +} + +.hol-modal-tabs { + display: flex; + border-bottom: 1px solid var(--border-light); + margin-top: 15px; + padding: 0 20px; +} + +.hol-modal-tab-btn { + flex: 1; + padding: 10px; + background: none; + border: none; + border-bottom: 3px solid transparent; + font-weight: bold; + color: var(--text-muted); + cursor: pointer; + font-size: 0.95rem; +} + +.hol-modal-tab-btn.active { + border-bottom-color: var(--primary); + color: var(--primary); +} + +.hol-modal-form { + display: flex; + flex-direction: column; + max-height: calc(90vh - 100px); +} + +.hol-tab-content { + padding: 20px; + overflow-y: auto; +} + +.hol-search-block { + margin-bottom: 15px; + background: var(--bg-subtle); + padding: 12px; + border-radius: 8px; + border: 1px dashed var(--border-strong); +} + +.hol-search-label { + margin-bottom: 4px; + font-size: 0.8rem; +} + +.hol-search-input-group { + display: flex; + gap: 8px; +} + +.hol-search-btn { + padding: 0 15px; +} + +.hol-search-results { + margin-top: 8px; + max-height: 150px; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 4px; +} + +.hol-input-highlight { + font-weight: bold; + color: var(--primary); + font-size: 1.1rem; +} + +.hol-date-range-block { + background: var(--bg-subtle); + padding: 12px; + border-radius: 8px; + border: 1px dashed var(--border-strong); +} + +.hol-date-picker-input { + cursor: pointer; + background-color: var(--bg-panel); + color: var(--primary); + font-weight: bold; + text-align: center; + letter-spacing: 0.5px; +} + +.hol-checkbox-group { + margin-top: 15px; + display: flex; + flex-direction: column; + gap: 8px; +} + +.hol-checkbox-label { + display: flex; + align-items: center; + cursor: pointer; + font-size: 0.85rem; + color: var(--text-main); +} + +.hol-checkbox-return { + margin-right: 8px; + width: 16px; + height: 16px; + accent-color: #ea580c; +} + +.hol-checkbox { + margin-right: 8px; + width: 16px; + height: 16px; +} + +.hol-prog-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; + position: sticky; + top: 0; + background: var(--bg-panel); + z-index: 10; + padding-bottom: 10px; + border-bottom: 1px solid var(--border-light); +} + +.hol-expenses-container { + display: flex; + flex-direction: column; gap: 10px; } -.hol-divider { - border: 0; - border-top: 1px solid var(--border-light); - margin: 20px 0; -} - -.hol-cat-transport { - color: var(--hol-accent-transport); -} - -.hol-cat-accommodation { - color: var(--hol-accent-accommodation); -} - -.hol-cat-activity { - color: var(--hol-accent-activity); -} - .hol-btn-delete { color: var(--danger); border-color: var(--border-danger-soft); @@ -341,189 +1014,99 @@ body.no-scroll { display: none; } -/* Cas spécifique modale carte */ -.hol-dialog--map { - width: 95vw; +/* --- Modale Planning Global --- */ +.hol-modal-planning { + max-width: 95vw; + width: 1400px; height: 90vh; - max-width: 1400px; - padding: 0; - background: var(--bg-panel); - border-radius: 12px; display: flex; flex-direction: column; -} - -/* Inputs généraux */ -.pf-label { - display: block; - font-weight: 600; - font-size: 0.85rem; - color: var(--text-muted); - margin-bottom: 6px; -} - -.pf-input { - width: 100%; - padding: 10px 12px; - border: 1px solid var(--border-strong); - border-radius: var(--radius-m); - font-size: 1rem; - background: var(--bg-panel); - color: var(--text-main); - box-sizing: border-box; - transition: all 0.2s; -} - -.pf-input:focus { - background: var(--bg-panel); - border-color: var(--primary); - outline: none; - box-shadow: 0 0 0 3px var(--focus-ring); -} - -.form-row { - display: flex; - gap: 16px; - flex-wrap: wrap; - margin-bottom: 16px; -} - -/* --- 7. SECTIONS DE DÉTAILS (Transport/Hotel/Activité) --- */ -.hol-columns-wrapper { - display: flex; /* Flexbox */ - flex-direction: column; /* Alignement vertical (les uns sous les autres) */ - gap: 24px; /* Espace entre les blocs */ - width: 100%; -} - -.hol-col { padding: 20px; - border-radius: 12px; - border: 1px solid var(--border-light); - width: 100%; /* Prend toute la largeur disponible */ - box-sizing: border-box; /* Empêche le padding de casser la largeur */ } -.hol-col-header { +.hol-planning-container { + flex: 1; + overflow: hidden; display: flex; - justify-content: space-between; /* Titre à gauche, bouton à droite */ - align-items: center; - border-bottom: 1px solid var(--border-light); - padding-bottom: 8px; - margin-bottom: 12px; } -.hol-col-header h4 { - margin: 0; - font-size: 1rem; - text-transform: uppercase; - font-weight: 700; - /* On retire les bordures/marges de l'ancien h4 car c'est le header qui gère */ - border: none; - padding: 0; +/* --- Modale Trajets & GPS --- */ +.hol-modal-sm { + max-width: 500px; } -/* Le bouton "+" style Gift List */ -.btn-add-item { - /* Style de base */ - background: rgba(255, 255, 255, 0.6); - color: var(--text-muted); - border: 1px solid rgba(0, 0, 0, 0.1); +.hol-transit-container { + max-height: 60vh; + overflow-y: auto; + padding-right: 5px; +} - /* Forme et Taille */ - width: 28px; - height: 28px; - border-radius: 50%; +.hol-modal-gps { + max-width: 320px; + height: auto !important; + min-height: 0 !important; + text-align: center; + padding: 20px; + margin: auto; +} - /* Texte */ - font-size: 18px; - line-height: 1; +.hol-gps-buttons { + display: flex; + flex-direction: column; + gap: 12px; +} - /* Flex pour centrer le + */ +.hol-gps-btn { + font-size: 1.1rem; + padding: 12px; display: flex; align-items: center; justify-content: center; - - cursor: pointer; - - /* Animation fluide "Cubic Bezier" copiée de gift-list */ - transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); + gap: 10px; } -.btn-add-item:hover { - background: white; - color: var(--primary); /* On ajoute la couleur primaire au survol */ - - /* L'effet de rotation et d'agrandissement */ - transform: rotate(90deg) scale(1.1); - - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15); - border-color: currentColor; +.hol-gps-icon { + width: 24px; + height: 24px; } -/* --- 8. ITEMS DYNAMIQUES (Inputs optimisés) --- */ -.savings-line-item { - display: flex; - align-items: center; - gap: 8px; /* Espace réduit */ - margin-bottom: 10px; - background: var(--bg-panel); - padding: 8px; +/* --- Modale Porte-Documents --- */ +.hol-modal-docs { + max-width: 450px; + padding: 20px; +} + +.hol-docs-dropzone { + text-align: center; + padding: 20px; + background: var(--bg-page); + border: 2px dashed var(--border-light); border-radius: 8px; - border: 1px solid var(--border-light); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03); + margin-bottom: 15px; } -/* Champ NOM : prend toute la place */ -.savings-line-item input[type="text"] { - flex-grow: 1; - min-width: 120px; - padding: 6px 10px; +.hol-docs-hint { + margin-top: 0; + color: var(--text-muted); font-size: 0.9rem; } -/* Champ PRIX : compact */ -.savings-line-item input[type="number"] { - width: 120px !important; - padding: 6px 8px !important; - text-align: right; - font-weight: 600; - color: var(--hol-accent-accommodation); +.hol-docs-select-btn { + margin: 10px 0; } -/* Checkbox Payé */ -.savings-line-item label { +.hol-upload-status { + font-size: 0.85rem; + font-weight: bold; + margin-top: 10px; +} + +.hol-docs-list { display: flex; - align-items: center; - font-size: 0.75rem; - color: var(--text-muted); - gap: 4px; - cursor: pointer; - white-space: nowrap; + flex-direction: column; + gap: 8px; } -/* Bouton Supprimer (Croix) */ -.btn-remove { - width: 28px; - height: 28px; - display: flex; - align-items: center; - justify-content: center; - background: transparent; - color: #ef4444; - border: none; - border-radius: 4px; - font-size: 1.2rem; - cursor: pointer; - line-height: 1; - transition: background 0.2s; -} -.btn-remove:hover { - background: var(--bg-danger-soft); - color: #b91c1c; -} - -/* --- 9. FOOTER MODALE --- */ .modal-footer { display: flex; justify-content: flex-end; @@ -533,596 +1116,9 @@ body.no-scroll { border-top: 1px solid var(--border-light); } -/* --- 10. MOBILE --- */ -@media (max-width: 768px) { - .pf-holidays__titlebar { - flex-direction: column; - align-items: stretch; /* Étire les éléments de haut en bas */ - gap: 15px; - } - .hol-title-group { - flex-direction: column; - align-items: stretch; - gap: 15px; - } - - .hol-filters-row { - justify-content: space-between; /* Écarte l'année et le badge */ - width: 100%; - } - .hol-badge-left-to-pay { - flex: 1; - justify-content: center; /* Centre le texte dans le badge */ - font-size: 0.8rem; /* Un peu plus petit sur mobile */ - } - - /* On empile proprement les boutons d'action */ - .hol-title-actions { - width: 100%; - flex-direction: column; /* Essentiel pour que les boutons width: 100% ne s'écrasent pas */ - gap: 10px; - } - .hol-actions-group .hol-add-btn { - width: 100%; - justify-content: center; - padding: 12px; - font-size: 1rem; - } - .hol-add-btn, - .hol-map-toggle { - width: 100%; - justify-content: center; /* Centre le texte et l'icône */ - } - - .form-row { - flex-direction: column; - gap: 10px; - } - - .hol-columns-wrapper { - grid-template-columns: 1fr; - } - - /* Modale 100% écran avec scroll natif fluide */ - .pf-modal { - padding: 0 !important; /* Retire le padding global pour faire un vrai plein écran */ - } - - .pf-modal-content { - padding: 16px; - width: 100% !important; - height: 100dvh !important; /* Utilise la hauteur dynamique (prend en compte la barre d'URL du tel) */ - max-height: 100dvh !important; - margin: 0 !important; - border-radius: 0 !important; - overflow-y: auto; - overscroll-behavior-y: contain; /* Empêche le scroll de se propager au body (fond) */ - -webkit-overflow-scrolling: touch; - } - - /* Adaptation des lignes de budget sur mobile pour éviter qu'elles ne soient compressées */ - .savings-line-item { - flex-wrap: wrap; - gap: 10px; - } - .savings-line-item input[type="text"] { - min-width: 100%; /* Le nom de la dépense prend toute la ligne */ - } - .savings-line-item input[type="number"] { - flex-grow: 1; /* Le prix s'ajuste sur la 2ème ligne */ - } - - .hol-date-weather-wrapper { - gap: 6px; - } - - .hol-cp-header { - align-items: flex-start; - flex-direction: column; /* On passe le titre et le prix l'un sous l'autre si besoin */ - } - - .hol-cp-info-group { - flex: 1; - min-width: 0; - width: 100%; - align-items: flex-start; - } - - .hol-cp-title { - white-space: normal !important; - overflow: visible !important; - text-overflow: clip !important; - line-height: 1.4; - word-break: break-word; - padding-top: 2px; - } - - .hol-cp-actions-group { - width: 100%; - justify-content: flex-end; - margin-top: 8px; - } -} - -/* --- 11. CALENDRIER & DATES (Force Light Theme) --- */ -input[type="date"] { - color-scheme: light; /* Force le popup blanc */ - background-color: #ffffff; - color: #1e293b; -} - -/* Cible spécifique pour l'icône calendrier (Chrome/Edge/Safari) */ -input[type="date"]::-webkit-calendar-picker-indicator { - cursor: pointer; - opacity: 0.6; - filter: invert(0); -} -input[type="date"]::-webkit-calendar-picker-indicator:hover { - opacity: 1; -} - /* ========================================================================== - 12. PAGE DE DÉTAIL DU VOYAGE (detail.php) + 10. PLANNING DRAG & DROP ========================================================================== */ - -/* Structure principale de la page détail */ -.pf-holidays-detail { - padding-top: 10px; -} - -/* En-tête de la page détail */ -.hol-detail-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 20px; - flex-wrap: wrap; - gap: 15px; -} - -.hol-detail-title-group { - display: flex; - align-items: center; - gap: 15px; - flex-wrap: wrap; -} - -.hol-detail-title-group h1 { - margin: 0; - font-size: 1.5rem; - color: var(--text-main); -} - -.hol-badge-status { - font-size: 0.75rem; - padding: 4px 10px; - border-radius: 12px; - font-weight: bold; - background: var(--hol-info-bg); - color: var(--hol-info-text); -} - -/* Bloc Résumé Financier */ -.hol-summary-card { - background: var(--bg-panel); - padding: 20px; - border-radius: var(--radius-l); - box-shadow: var(--shadow-sm); - border: 1px solid var(--border-light); - margin-bottom: 24px; -} - -.hol-summary-grid { - display: flex; - justify-content: space-between; - margin-bottom: 15px; - flex-wrap: wrap; - gap: 15px; -} - -.hol-summary-item { - min-width: 150px; -} - -.hol-summary-label { - font-size: 0.85rem; - color: var(--text-muted); - margin-bottom: 4px; -} - -.hol-summary-value { - font-weight: 600; - color: var(--text-main); - font-size: 1.1rem; -} - -.hol-summary-value.total { - font-size: 1.4rem; - font-weight: bold; - color: var(--text-main); -} - -/* Grille principale : Carte + Timeline */ -.hol-layout-grid { - display: grid; - grid-template-columns: 2fr 1fr; - gap: 20px; - align-items: stretch; -} - -/* Panneaux (Carte et Timeline) */ -.hol-panel { - background: var(--bg-panel); - border-radius: var(--radius-l); - box-shadow: var(--shadow-sm); - border: 1px solid var(--border-light); - display: flex; - flex-direction: column; - height: 600px; - overflow: hidden; -} - -.hol-panel-header { - padding: 15px 20px; - border-bottom: 1px solid var(--border-light); - display: flex; - justify-content: space-between; - align-items: center; - background: var(--bg-page); -} - -.hol-panel-header h3 { - margin: 0; - font-size: 1.1rem; - color: var(--text-main); -} - -.hol-panel-body { - padding: 15px; - overflow-y: auto; - flex: 1; -} - -/* Styles des Checkpoints (Timeline) */ -.hol-checkpoint { - border: 1px solid var(--border-light); - border-radius: 8px; - margin-bottom: 15px; - overflow: hidden; - background: var(--bg-panel); -} - -.hol-cp-header { - background: var(--bg-page); - padding: 6px 8px; - display: flex; - justify-content: space-between; - align-items: center; - border-bottom: 1px solid var(--border-light); - gap: 12px; -} - -.hol-cp-info-group { - display: flex; - align-items: center; - gap: 12px; - flex: 1; - min-width: 0; -} - -.hol-cp-title { - color: var(--text-main); - font-size: 0.95rem; - font-weight: 700; - cursor: pointer; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.hol-cp-title:hover { - color: var(--primary); -} - -.hol-cp-actions-group { - display: flex; - align-items: center; - gap: 10px; - flex-shrink: 0; -} - -.hol-cp-total { - font-size: 0.9rem; - font-weight: 700; - color: var(--primary); - white-space: nowrap; -} - -.hol-cp-body { - padding: 10px 15px; -} - -.hol-expense-line { - display: flex; - justify-content: space-between; - font-size: 0.85rem; - margin-bottom: 5px; - border-bottom: 1px dashed var(--bg-subtle); - padding-bottom: 5px; -} - -.hol-expense-line:last-child { - border-bottom: none; - margin-bottom: 0; - padding-bottom: 0; -} - -.hol-notes-panel { - padding: 15px; - border-top: 1px solid var(--border-light); - background: var(--hol-warning-bg); - flex-shrink: 0; - max-height: 200px; - overflow-y: auto; -} - -/* --- RESPONSIVE DETAIL PAGE --- */ -@media (max-width: 992px) { - .hol-layout-grid { - grid-template-columns: 1fr; /* Sur tablette/mobile, la carte et la liste s'empilent */ - } - - .hol-panel { - height: 500px; /* On réduit un peu la hauteur pour que ce soit agréable sur mobile */ - } - - .hol-summary-grid { - flex-direction: column; /* Les infos financières s'empilent */ - } - - .hol-summary-item { - text-align: left !important; /* On annule l'alignement à droite du total */ - } -} - -/* ========================================================================== - 13. BARRE DE PROGRESSION & FINANCES - ========================================================================== */ -.hol-progress-bar { - width: 100%; - height: 12px; - background: #e2e8f0; - border-radius: 6px; - margin-bottom: 10px; - display: flex; - overflow: hidden; -} -.hol-progress-paid { - background: #10b981; -} -.hol-progress-saved { - background: #3b82f6; -} - -.hol-progress-labels { - display: flex; - justify-content: space-between; - font-size: 0.85rem; -} -.hol-label-paid { - color: #10b981; - font-weight: 600; -} -.hol-label-saved { - color: #3b82f6; - font-weight: 600; -} -.hol-label-left { - color: #ef4444; - font-weight: 700; -} - -/* ========================================================================== - 14. LÉGENDE DE LA CARTE - ========================================================================== */ -.hol-panel-header-group { - display: flex; - align-items: center; - gap: 15px; - flex-wrap: wrap; -} -.hol-map-legend { - display: flex; - gap: 12px; - font-size: 0.75rem; - color: var(--text-muted); - background: var(--bg-panel); - padding: 4px 10px; - border-radius: 12px; - border: 1px solid var(--border-light); -} -.hol-legend-item { - display: flex; - align-items: center; - gap: 4px; -} -.hol-legend-color { - display: inline-block; - width: 12px; - height: 4px; - border-radius: 2px; -} -.hol-legend-color.aller { - background: #3b82f6; -} -.hol-legend-color.interm { - background: #8b5cf6; -} -.hol-legend-color.retour { - background: transparent; - height: 0; - border-bottom: 3px dashed #f97316; - border-radius: 0; -} - -/* ========================================================================== - 15. LIGNES DE DÉPENSES (Timeline & Modale JS) - ========================================================================== */ -.hol-expense-wrapper { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 4px; - margin-bottom: 8px; - border-bottom: 1px dashed var(--bg-subtle); - padding-bottom: 8px; -} -.hol-expense-wrapper:last-child { - margin-bottom: 0; - border-bottom: none; - padding-bottom: 0; -} - -.hol-expense-main { - display: flex; - justify-content: space-between; - width: 100%; - font-size: 0.85rem; -} -.hol-expense-name { - color: var(--text-muted); - font-weight: 500; -} -.hol-expense-amount { - color: var(--text-main); - font-weight: bold; -} -.status-paid { - color: #10b981; - margin-left: 5px; -} -.status-pending { - color: #f59e0b; - margin-left: 5px; -} - -.hol-expense-note { - font-size: 0.75rem; - color: var(--border-strong); - padding-left: 24px; - word-break: break-all; -} -.hol-expense-link { - color: #3b82f6; - text-decoration: none; -} -.hol-expense-link:hover { - text-decoration: underline; -} - -.hol-empty-step { - font-size: 0.8rem; - color: var(--text-muted); - font-style: italic; - padding: 5px 0; -} - -/* Boutons de petite taille */ -.pf-btn-small { - padding: 6px 14px !important; - font-size: 0.85rem !important; - width: auto !important; - height: auto !important; - margin: 0 !important; -} - -/* Modale JS d'ajout de dépense */ -.hol-form-row { - display: flex; - flex-direction: column; - gap: 6px; - padding: 10px; - background: var(--bg-page); - border-radius: 8px; - border: 1px solid var(--border-light); -} -.hol-form-inner { - display: flex; - gap: 8px; - align-items: center; - width: 100%; -} -.hol-form-select { - width: 50px; - padding: 8px 4px; - font-size: 1.2rem; - cursor: pointer; -} -.hol-form-text { - flex: 2; - padding: 8px; - font-size: 0.9rem; -} -.hol-form-number { - width: 80px; - text-align: right; - padding: 8px; - font-size: 0.9rem; -} -.hol-form-paid-label { - display: flex; - align-items: center; - cursor: pointer; - width: 55px; -} -.hol-form-paid-text { - font-size: 0.75rem; - margin-left: 4px; - font-weight: bold; - color: var(--text-muted); -} -.hol-form-notes-input { - font-size: 0.8rem; - padding: 6px 8px; - border-style: dashed; - color: var(--text-muted); - width: calc(100% - 58px); - margin-left: 58px; -} -.btn-remove-expense { - width: 28px; - height: 28px; - border: none; - background: #fee2e2; - color: #ef4444; - border-radius: 6px; - cursor: pointer; - font-weight: bold; - display: flex; - justify-content: center; - align-items: center; - transition: 0.2s; -} -.btn-remove-expense:hover { - background: #fca5a5; - color: #b91c1c; -} - -/* ========================================================================== - 16. PLANNING DRAG & DROP (CARNET DE VOYAGE) - ========================================================================== */ -/* Simplification de la sous-ligne du formulaire d'édition */ -.hol-form-subrow { - display: flex; - margin-top: 6px; - padding-left: 58px; -} -.hol-form-notes-full { - margin: 0 !important; - width: 100%; -} - -/* Layout du Planning Interactif */ .hol-planning-layout { display: flex; gap: 20px; @@ -1131,7 +1127,6 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { overflow: hidden; } -/* Zone des activités non planifiées */ .hol-unmapped-zone { width: 250px; background: var(--bg-page); @@ -1143,6 +1138,7 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { gap: 10px; overflow-y: auto; } + .hol-unmapped-title { font-size: 0.85rem; font-weight: 700; @@ -1152,55 +1148,35 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { text-align: center; } -/* Grille du calendrier */ .hol-calendar-zone { flex: 1; display: flex; gap: 15px; - overflow: auto; /* Gère à la fois gauche/droite ET haut/bas */ + overflow: auto; padding-bottom: 10px; position: relative; } -.hol-calendar-zone::-webkit-scrollbar, -.hol-unmapped-zone::-webkit-scrollbar { - height: 10px; -} -.hol-calendar-zone::-webkit-scrollbar-track, -.hol-unmapped-zone::-webkit-scrollbar-track { - background: var(--bg-subtle); - border-radius: 5px; -} -.hol-calendar-zone::-webkit-scrollbar-thumb, -.hol-unmapped-zone::-webkit-scrollbar-thumb { - background: var(--border-strong); - border-radius: 5px; -} -.hol-calendar-zone::-webkit-scrollbar-thumb:hover { - background: var(--text-muted); -} .hol-calendar-zone .hol-drag-item { position: absolute; top: 1px; - left: 52px; /* Dégage l'espace pour lire l'heure proprement */ + left: 45px; right: 5px; height: calc(60px * var(--duration) - 2px); } -/* Dans la boîte d'attente : Position normale */ + .hol-unmapped-zone .hol-drag-item { position: relative; min-width: 150px; height: auto; } -/* Mode "Tap-to-Move" pour Mobile */ .hol-drag-item.selected-for-move { border-color: #f59e0b; transform: scale(1.02); box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.3); } -/* Boutons Durée */ .hol-item-duration-controls { display: flex; align-items: center; @@ -1208,7 +1184,7 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { margin: 0; padding: 2px; border: none; - background: rgba(255, 255, 255, 0.4); /* Léger fond pour se détacher */ + background: rgba(255, 255, 255, 0.4); border-radius: 4px; } @@ -1220,7 +1196,7 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { border: 1px solid var(--border-light); display: flex; flex-direction: column; - height: max-content; /* Laisse la colonne grandir jusqu'à 22h */ + height: max-content; overflow: visible; } @@ -1230,11 +1206,10 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { background: #f8fafc; border-bottom: 2px solid #e2e8f0; position: sticky; - top: 0; /* Garde la date toujours visible en haut ! */ + top: 0; z-index: 20; } -/* Les créneaux horaires (Drop Zones) */ .hol-time-slots-container { display: flex; flex-direction: column; @@ -1249,8 +1224,9 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { } .hol-time-slot.drag-over { - background: #e0f2fe; /* Surbrillance quand on survole avec une activité */ + background: #e0f2fe; } + .hol-slot-label { position: absolute; top: 2px; @@ -1261,7 +1237,6 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { pointer-events: none; } -/* L'Activité (Élément draggable) */ .hol-drag-item { background: white; padding: 6px 8px; @@ -1279,12 +1254,15 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { transform 0.2s, border-color 0.2s; } + .hol-drag-item:active { cursor: grabbing; } + .hol-drag-item.cat-accommodation { border-left-color: #8b5cf6; } + .hol-drag-item.cat-transport { border-left-color: #10b981; } @@ -1294,6 +1272,7 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { color: #0f172a; line-height: 1.2; } + .hol-drag-note { font-size: 0.75rem; color: #64748b; @@ -1302,18 +1281,12 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { text-overflow: ellipsis; } -/* Élargir la modale de planning */ -#planningModal .pf-modal-content { - max-width: 1100px !important; - width: 95%; -} - .hol-dur-btn { background: #f1f5f9; border: none; border-radius: 4px; width: 18px; - height: 18px; /* Plus petit */ + height: 18px; cursor: pointer; font-weight: bold; color: #475569; @@ -1322,18 +1295,19 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { justify-content: center; font-size: 0.8rem; } + .hol-dur-btn:hover { background: #e2e8f0; } + .hol-dur-text { font-size: 0.7rem; color: #64748b; font-weight: 700; } -/* Bouton pour retirer une carte du planning (Undo) */ .hol-unplace-btn { - display: none; /* Caché par défaut dans la zone "À placer" */ + display: none; background: #fee2e2; color: #ef4444; border: 1px solid #fca5a5; @@ -1354,20 +1328,13 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { color: white; } -/* Le bouton n'apparaît QUE quand la carte est physiquement dans le calendrier */ .hol-time-slot .hol-drag-item .hol-unplace-btn { display: flex; } -.highlight-step { - transition: - box-shadow 0.3s, - transform 0.3s; - box-shadow: 0 0 0 3px var(--primary); - transform: scale(1.02); -} - -/* Style du badge météo injecté par le JS */ +/* ========================================================================== + 11. MÉTÉO & DATES + ========================================================================== */ .hol-weather-info { display: inline-flex; } @@ -1376,11 +1343,11 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { display: flex; align-items: center; gap: 4px; - background: #f8fafc; /* Slate 50 */ - border: 1px solid var(--border-light); /* Slate 200 */ + background: #f8fafc; + border: 1px solid var(--border-light); padding: 1px 6px; border-radius: 6px; - color: #475569; /* Slate 600 */ + color: #475569; font-weight: 600; font-size: 0.7rem; line-height: 1; @@ -1390,7 +1357,6 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { font-size: 0.9rem; } -/* Conteneur Date + Météo */ .hol-date-weather-wrapper { font-size: 0.75rem; color: #64748b; @@ -1399,268 +1365,80 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { display: flex; align-items: center; gap: 10px; - flex-wrap: wrap; /* Le secret pour le responsive ! */ + flex-wrap: wrap; } -/* On s'assure que le texte de la date ne se coupe pas au milieu d'un mot */ .hol-step-dates { white-space: nowrap; } -.leaflet-container img.leaflet-tile { - pointer-events: none !important; - user-select: none !important; - -moz-user-select: none !important; -} -#tripMap { - touch-action: none; + +input[type="date"] { + color-scheme: light; + background-color: #ffffff; + color: #1e293b; } -/* --- Toll cost estimator panel --- */ -.hol-cost-stat { - background: var(--bg-page, #f8fafc); - border: 1px solid var(--border-light, #e2e8f0); - border-radius: 10px; - padding: 0.75rem 1rem; - text-align: center; +input[type="date"]::-webkit-calendar-picker-indicator { + cursor: pointer; + opacity: 0.6; + filter: invert(0); } -.hol-cost-stat-val { - font-size: 1.2rem; - font-weight: 700; - color: var(--text-main, #0f172a); -} -.hol-cost-stat-label { - font-size: 0.72rem; - color: var(--text-muted, #64748b); - margin-top: 2px; - text-transform: uppercase; - letter-spacing: 0.04em; -} -.hol-cost-total { - border-color: var(--primary, #4361ee); -} -.hol-cost-total .hol-cost-stat-val { - color: var(--primary, #4361ee); + +input[type="date"]::-webkit-calendar-picker-indicator:hover { + opacity: 1; } /* ========================================================================== - 17. ENCART D'ESTIMATION DE TRAJET (OSRM) + 12. UX MOBILE & ADAPTATIONS RESPONSIVE ========================================================================== */ -.hol-transit-info { - margin: 0 15px 15px 15px; - padding: 12px 16px; - background: var(--hol-info-bg); - border-radius: var(--radius-m); - border: 1px dashed #7dd3fc; - display: flex; - justify-content: space-between; - align-items: center; - flex-wrap: wrap; - gap: 12px; - transition: all 0.2s ease; -} - -.hol-transit-details { - font-size: 0.85rem; - color: var(--hol-info-text); - display: flex; - align-items: center; - gap: 12px; -} - -.hol-transit-icon { - font-size: 1.6rem; - line-height: 1; -} - -.hol-transit-text strong { - font-size: 0.95rem; -} - -.hol-transit-text span { - opacity: 0.85; - font-size: 0.8rem; - display: block; - margin-top: 2px; -} - -.hol-transit-btn { - padding: 6px 14px; - font-size: 0.8rem; - white-space: nowrap; -} - @media (max-width: 768px) { - .hol-transit-info { - margin: 0 10px 15px 10px; - padding: 10px; + .pf-holidays__titlebar { flex-direction: column; - align-items: flex-start; + align-items: stretch; + gap: 15px; } - .hol-transit-btn { + + .hol-title-group { + flex-direction: column; + align-items: stretch; + gap: 15px; + } + + .hol-filters-row { + justify-content: space-between; + width: 100%; + } + + .hol-badge-left-to-pay { + flex: 1; + justify-content: center; + font-size: 0.8rem; + } + + .hol-actions-group .hol-add-btn, + .hol-add-btn, + .hol-map-toggle { width: 100%; justify-content: center; } -} -/* --- EN-TÊTE DES ÉTAPES ROADTRIP --- */ -.hol-step-header { - padding: 6px 8px; - border-bottom: 1px solid var(--border-light); - display: flex; - flex-direction: column; - gap: 8px; -} - -/* Ligne 1 : Icône + Titre + Poignée */ -.hol-step-row-top { - display: flex; - align-items: flex-start; - gap: 10px; - width: 100%; -} - -.hol-step-icon { - border-radius: 6px; - display: flex; - align-items: center; - justify-content: center; - font-size: 1rem; - flex-shrink: 0; - margin-top: 2px; -} - -.hol-step-title { - flex: 1; - font-size: 1.05rem; - font-weight: 700; - color: var(--text-main); - line-height: 1.3; - word-break: break-word; - cursor: pointer; - padding-top: 4px; -} - -.hol-step-controls { - flex-shrink: 0; - display: flex; - flex-direction: column; - align-items: center; -} - -.hol-drag-handle { - color: #cbd5e1; - font-size: 1.4rem; - cursor: grab; - user-select: none; - line-height: 1; -} - -.hol-step-arrows { - display: flex; - flex-direction: column; - gap: 0; -} - -.hol-step-arrows button { - background: transparent; - border: none; - color: #94a3b8; - font-size: 0.75rem; - padding: 4px 8px; - cursor: pointer; - line-height: 1; -} - -/* Ligne 2 : Tags/Dates + Prix/Actions */ -.hol-step-row-bottom { - display: flex; - align-items: center; - justify-content: space-between; - margin-top: 5px; - width: 100%; -} - -.hol-step-meta { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 6px; -} - -.hol-tag-return { - background: #fff7ed; - color: #ea580c; - padding: 2px 6px; - border-radius: 4px; - font-size: 0.75rem; - font-weight: 700; - border: 1px solid #ffedd5; - line-height: 1.2; -} - -.hol-step-date { - font-size: 0.8rem; - color: #64748b; - background: var(--bg-page); - padding: 2px 6px; - border-radius: 4px; - border: 1px solid var(--border-light); - line-height: 1.2; -} - -.hol-step-actions { - display: flex; - align-items: center; - gap: 8px; - margin-left: auto; /* Pousse le prix et les boutons tout à droite */ -} - -.hol-step-price { - font-weight: 800; - color: var(--primary); - white-space: nowrap; -} - -/* Optimisation Mobile */ -@media (max-width: 768px) { - .hol-step-row-bottom { - padding-left: 0; /* Sur mobile, on prend toute la largeur pour éviter d'écraser les boutons */ + .pf-modal { + padding: 0 !important; } -} -/* --- LIGNES DE DÉPENSES --- */ -.hol-expense-main { - display: flex; - justify-content: space-between; - align-items: flex-start; - gap: 8px; -} + .pf-modal-content { + padding: 16px; + width: 100% !important; + height: 100dvh !important; + max-height: 100dvh !important; + margin: 0 !important; + border-radius: 0 !important; + overflow-y: auto; + overscroll-behavior-y: contain; + -webkit-overflow-scrolling: touch; + } -.hol-expense-name { - flex: 1; - min-width: 0; - word-break: break-word; -} - -.hol-expense-price-group { - display: inline-flex; - align-items: center; - gap: 6px; - white-space: nowrap; /* Interdit le passage à la ligne */ - flex-shrink: 0; /* Empêche le bloc d'être écrasé */ - margin-top: 2px; -} - -.hol-expense-price-group .status-paid, -.hol-expense-price-group .status-pending { - line-height: 1; -} - -/* ============================================================================ - 📱 UX MOBILE : MODALE DE PLANNING (DRAG & DROP) - ============================================================================ */ -@media (max-width: 768px) { - /* --- MODALE GLOBALE --- */ + /* --- MODALE DE PLANNING MOBILE (BOTTOM SHEET) --- */ #planningModal .pf-modal-content { padding: 6px !important; height: 98vh !important; @@ -1673,12 +1451,6 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { margin-bottom: 6px !important; padding-bottom: 6px !important; } - #planningModalTitle { - font-size: 1rem !important; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } #planningContainer > div { flex-direction: column !important; @@ -1687,7 +1459,6 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { height: 100% !important; } - /* --- 1. LE CALENDRIER (EN HAUT) --- */ .hol-calendar-zone { width: 100% !important; flex: 1 1 auto !important; @@ -1697,40 +1468,11 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { gap: 6px !important; } - /* 🎯 Header des Jours ultra-compressé */ - .hol-calendar-day-header { - padding: 4px !important; - } - .hol-cal-weekday { - font-size: 0.6rem !important; - margin-bottom: 0 !important; - } - .hol-cal-date { - font-size: 0.9rem !important; - line-height: 1 !important; - margin-bottom: 2px !important; - } - - div[id^="plan-weather-"] { - min-height: 14px !important; - margin-top: 0 !important; - } - div[id^="plan-weather-"] .pf-weather-badge { - padding: 1px 4px !important; - font-size: 0.55rem !important; - } - - .hol-time-slot { - min-height: 40px !important; - padding: 4px !important; - } - - /* --- 2. LA ZONE "À PLACER" (BOTTOM SHEET - 30%) --- */ .hol-unmapped-zone { width: 100% !important; - height: 35vh !important; /* 🔼 Prend exactement 30% de l'écran */ + height: 35vh !important; min-height: 180px !important; - flex: 0 0 auto !important; /* 🛡️ Protection anti-écrasement */ + flex: 0 0 auto !important; order: 2 !important; border-radius: 12px 12px 0 0 !important; border-top: 2px solid var(--primary) !important; @@ -1738,34 +1480,25 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { border-left: none !important; border-right: none !important; box-shadow: 0 -4px 15px rgba(0, 0, 0, 0.15) !important; - margin: 0px !important; + margin: 0 !important; padding: 6px !important; z-index: 100; background: var(--bg-panel) !important; display: flex !important; - flex-direction: column !important; /* ↕️ On repasse en mode vertical */ + flex-direction: column !important; } - .hol-unmapped-title { - font-size: 0.8rem !important; - margin-bottom: 8px !important; - flex-shrink: 0 !important; - } - - /* --- 3. LISTE VERTICALE (Scroll Down) --- */ #unmapped-pool { - flex-direction: column !important; /* ↕️ Les cartes s'empilent */ - overflow-y: auto !important; /* ↕️ Apparition du scroll vertical */ + flex-direction: column !important; + overflow-y: auto !important; overflow-x: hidden !important; padding-bottom: 10px !important; - padding-right: 5px !important; /* Espace pour la barre de scroll */ gap: 8px !important; -webkit-overflow-scrolling: touch; - flex: 1 !important; /* Prend tout l'espace des 30vh */ + flex: 1 !important; align-items: stretch !important; } - /* 🎯 Les cartes s'adaptent à 100% de la largeur du téléphone */ #unmapped-pool .hol-drag-item { width: 100% !important; height: auto !important; @@ -1774,7 +1507,6 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover { white-space: normal !important; } - /* 🗑️ On cache le footer de la modale pour gagner de l'espace */ #planningModal .modal-footer { display: none !important; } diff --git a/modules/holidays/includes/api/save_holiday.php b/modules/holidays/includes/api/save_holiday.php index 6cc663f..7b19498 100644 --- a/modules/holidays/includes/api/save_holiday.php +++ b/modules/holidays/includes/api/save_holiday.php @@ -28,16 +28,51 @@ $vehicle_id = !empty($_POST['vehicle_id']) ? (int)$_POST['vehicle_id'] : null; try { $pdo->beginTransaction(); + // 1. Détection d'un changement de nom pour refaire l'appel API + $image_url = null; + $old_title = null; if ($id) { - // UPDATE (avec vehicle_id) - $sql = "UPDATE pf_holidays SET title=?, period_hint=?, start_date=?, end_date=?, status=?, budget_food=?, budget_extra=?, notes=?, vehicle_id=? WHERE id=?"; + $stmtOld = $pdo->prepare("SELECT title, image_url FROM pf_holidays WHERE id = ?"); + $stmtOld->execute([$id]); + if ($row = $stmtOld->fetch()) { + $old_title = $row['title']; + $image_url = $row['image_url']; + } + } + + // 2. Appel à Pixabay si nouveau voyage ou si le titre a changé + if (!$id || strcasecmp($old_title ?? '', $title) !== 0) { + $apiKey = '56931941-a86fbea4e14b88712cc1e9ed9'; + $query = urlencode($title); + // On force des photos horizontales HD + $url = "https://pixabay.com/api/?key={$apiKey}&q={$query}&image_type=photo&orientation=horizontal&min_width=1280&per_page=3"; + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_TIMEOUT, 3); // Timeout de 3s max pour ne pas bloquer l'UI + $response = curl_exec($ch); + curl_close($ch); + + if ($response) { + $data = json_decode($response, true); + if (!empty($data['hits'][0]['largeImageURL'])) { + $image_url = $data['hits'][0]['largeImageURL']; + } + } + } + + // 3. Sauvegarde en Base + if ($id) { + // UPDATE + $sql = "UPDATE pf_holidays SET title=?, period_hint=?, start_date=?, end_date=?, status=?, budget_food=?, budget_extra=?, notes=?, vehicle_id=?, image_url=? WHERE id=?"; $stmt = $pdo->prepare($sql); - $stmt->execute([$title, $period, $start, $end, $status, $food, $extra, $notes, $vehicle_id, $id]); + $stmt->execute([$title, $period, $start, $end, $status, $food, $extra, $notes, $vehicle_id, $image_url, $id]); } else { - // INSERT (avec vehicle_id) - $sql = "INSERT INTO pf_holidays (title, period_hint, start_date, end_date, status, budget_food, budget_extra, notes, vehicle_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + // INSERT + $sql = "INSERT INTO pf_holidays (title, period_hint, start_date, end_date, status, budget_food, budget_extra, notes, vehicle_id, image_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; $stmt = $pdo->prepare($sql); - $stmt->execute([$title, $period, $start, $end, $status, $food, $extra, $notes, $vehicle_id]); + $stmt->execute([$title, $period, $start, $end, $status, $food, $extra, $notes, $vehicle_id, $image_url]); $id = $pdo->lastInsertId(); } diff --git a/modules/holidays/views/detail.php b/modules/holidays/views/detail.php index 8e145e4..a463589 100644 --- a/modules/holidays/views/detail.php +++ b/modules/holidays/views/detail.php @@ -77,294 +77,276 @@ $saved = (float)$holiday['total_saved']; $leftToPay = max(0, $cost - $paid); $pctPaid = $cost > 0 ? min(100, ($paid / $cost) * 100) : 0; $pctSaved = $cost > 0 ? min(100 - $pctPaid, ($saved / $cost) * 100) : 0; + +// Image de fond (API Pixabay ou fallback par défaut) +$bgImage = !empty($holiday['image_url']) ? htmlspecialchars($holiday['image_url']) : '/modules/home/assets/img/background.jpg'; ?> - -
= tr('hdl_no_steps') ?>
- + += tr('hdl_no_steps') ?>
+ - - - -