{% set _locale = app.request.locale %}{% set _isFr = _locale == 'fr' %}{# Données dynamiques #}{% set footerArticles = getFooterArticles(_locale, 5) %}{% set footerLandingJobs = getFooterFeaturedLandingJobs(_locale, 5) %}{% set footerJobsCities = getFooterJobsCities(_locale, 6) %}{% set footerEnterprisesCities = getFooterEnterprisesCities(_locale, 6) %}{# Liens stores : nouvelle source de vérité (table cvs_app_store_links) #}{% set _storeData = getAppStoreCountries() %}{% set _storePrimary = _storeData.primary|default({}) %}{% set _storeOthers = _storeData.others|default({}) %}<style> /* ---------- Footer WhileResume ---------- */ .whr-footer { margin-top: 32px; padding: 36px 24px 24px; background: #F9FAFD; border-radius: 16px; color: #2c2c46; width: auto; max-width: none; margin-left: 16px; margin-right: 16px; } .theme-dark .whr-footer { background: #2a2a3c; color: #e9e9ef; } .middle-sidebar-left .whr-footer { width: 100%; margin-left: 0; margin-right: 0; } /* Stores en haut de la col 1 */ .whr-footer .whr-stores { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; position: relative; /* pour le dropdown */ } .whr-footer .whr-store-link { display: inline-flex; align-items: center; gap: 10px; padding: 8px 14px; background: #111; color: #fff !important; border-radius: 10px; font-size: 12px; font-weight: 600; text-decoration: none !important; line-height: 1.2; transition: transform .15s ease, background .2s ease; max-width: 200px; cursor: pointer; border: none; font-family: inherit; text-align: left; } .whr-footer .whr-store-link:hover { background: #2c2c46; transform: translateY(-1px); } .whr-footer .whr-store-link small { display: block; font-weight: 400; font-size: 10px; opacity: .7; } .whr-footer .whr-store-link strong { font-size: 13px; display: block; } /* Wrapper du bouton + dropdown (version EN) */ .whr-store-wrap { position: relative; display: inline-block; } .whr-store-wrap .whr-store-link { width: 100%; max-width: 200px; } /* === Dropdown élargi (2 colonnes + search + featured pinné) === */ .whr-store-dropdown { position: absolute; bottom: calc(100% + 6px); left: 0; width: 380px; max-width: calc(100vw - 32px); background: #fff; border-radius: 12px; box-shadow: 0 -8px 24px rgba(0,0,0,.15), 0 -2px 6px rgba(0,0,0,.08); z-index: 1000; display: none; overflow: hidden; } .theme-dark .whr-store-dropdown { background: #34344a; box-shadow: 0 -8px 24px rgba(0,0,0,.4), 0 -2px 6px rgba(0,0,0,.2); } .whr-store-wrap.is-open .whr-store-dropdown { display: flex; flex-direction: column; animation: whrFadeInUp .15s ease; } @keyframes whrFadeInUp { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } } /* Chevron */ .whr-store-link .whr-store-chevron { margin-left: auto; font-size: 10px; opacity: .7; transition: transform .2s ease; } .whr-store-wrap.is-open .whr-store-link .whr-store-chevron { transform: rotate(180deg); } /* Zone search en haut */ .whr-store-search-wrap { padding: 10px 10px 6px; border-bottom: 1px solid rgba(0,0,0,.06); flex-shrink: 0; } .theme-dark .whr-store-search-wrap { border-bottom-color: rgba(255,255,255,.08); } .whr-store-search { width: 100%; height: 34px; padding: 0 12px 0 32px; border: 1px solid rgba(0,0,0,.1); border-radius: 8px; background: #f5f5f8 url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='8'/><line x1='21' y1='21' x2='16.65' y2='16.65'/></svg>") no-repeat 10px center; font-size: 13px; color: #2c2c46; outline: none; transition: border-color .15s ease, background-color .15s ease; font-family: inherit; } .whr-store-search:focus { border-color: var(--theme-color, #6C3AED); background-color: #fff; } .theme-dark .whr-store-search { background-color: #2a2a3c; border-color: rgba(255,255,255,.1); color: #e9e9ef; } .theme-dark .whr-store-search:focus { background-color: #3c3c52; } .whr-store-search::placeholder { color: #999; } /* Featured pinné (toujours visible, hors scroll) */ .whr-store-featured { padding: 8px 8px 4px; flex-shrink: 0; border-bottom: 1px solid rgba(0,0,0,.06); } .theme-dark .whr-store-featured { border-bottom-color: rgba(255,255,255,.08); } /* Zone scrollable des "other regions" */ .whr-store-others { padding: 8px; max-height: 280px; overflow-y: auto; flex: 1; } .whr-store-others::-webkit-scrollbar { width: 6px; } .whr-store-others::-webkit-scrollbar-thumb { background: rgba(0,0,0,.15); border-radius: 3px; } .theme-dark .whr-store-others::-webkit-scrollbar-thumb { background: rgba(255,255,255,.15); } /* Header de section */ .whr-store-dropdown-header { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; opacity: .55; padding: 4px 8px 6px; color: #2c2c46; } .theme-dark .whr-store-dropdown-header { color: #e9e9ef; } /* Grille 2 colonnes pour les pays */ .whr-store-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; } /* Item pays */ .whr-store-country { display: flex; align-items: center; gap: 8px; padding: 7px 9px; border-radius: 6px; text-decoration: none !important; color: #2c2c46 !important; font-size: 12.5px; transition: background .15s ease; min-width: 0; } .theme-dark .whr-store-country { color: #e9e9ef !important; } .whr-store-country:hover { background: rgba(108, 58, 237, .08); color: var(--theme-color, #6C3AED) !important; } .theme-dark .whr-store-country:hover { background: rgba(108, 58, 237, .2); } .whr-store-country .whr-flag { font-size: 16px; line-height: 1; width: 18px; text-align: center; flex-shrink: 0; } .whr-store-country .whr-country-name { flex: 1; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; } /* Featured = pleine largeur, plus mis en avant */ .whr-store-featured .whr-store-country { background: linear-gradient(135deg, rgba(108, 58, 237, .08), rgba(108, 58, 237, .03)); font-weight: 600; padding: 9px 10px; } .theme-dark .whr-store-featured .whr-store-country { background: linear-gradient(135deg, rgba(108, 58, 237, .25), rgba(108, 58, 237, .1)); } /* Message "aucun résultat" */ .whr-store-empty { text-align: center; padding: 20px 12px; font-size: 12px; color: #999; font-style: italic; } .theme-dark .whr-store-empty { color: #aaa; } /* Item caché par la recherche */ .whr-store-country.is-hidden { display: none; } /* Responsive : sur mobile, 1 colonne et largeur ajustée */ @media (max-width: 575.98px) { .whr-store-dropdown { width: calc(100vw - 32px); max-width: 360px; } .whr-store-grid { grid-template-columns: 1fr; } } /* Colonnes */ .whr-footer .whr-foot-col h4 { font-size: 13px; font-weight: 700; margin: 0 0 14px 0; color: inherit; text-transform: uppercase; letter-spacing: .3px; } .whr-footer .whr-foot-col ul { list-style: none; padding: 0; margin: 0; font-size: 13px; } .whr-footer .whr-foot-col ul li { margin-bottom: 10px; } .whr-footer .whr-foot-col a { color: inherit; opacity: .75; text-decoration: none; transition: opacity .2s ease, color .2s ease; } .whr-footer .whr-foot-col a:hover { opacity: 1; color: var(--theme-color, #6C3AED); } .whr-footer .whr-foot-empty { font-size: 12px; opacity: .5; font-style: italic; } .whr-footer .whr-foot-action-links a { display: inline-flex; align-items: center; gap: 8px; } .whr-footer .whr-foot-action-links a i { font-size: 14px; opacity: .7; width: 16px; text-align: center; } .whr-footer .whr-foot-col .whr-city-link { display: inline-flex; align-items: center; gap: 6px; } .whr-footer .whr-foot-col .whr-city-link .whr-city-icon { font-size: 14px; line-height: 1; display: inline-block; width: 18px; text-align: center; opacity: .85; } .whr-footer .whr-foot-grid { display: grid; gap: 28px; grid-template-columns: 1fr; } @media (min-width: 576px) { .whr-footer .whr-foot-grid { grid-template-columns: 1fr 1fr; } } @media (min-width: 992px) { .whr-footer .whr-foot-grid { grid-template-columns: repeat(5, 1fr); gap: 32px; } } .whr-footer .whr-foot-bottom { margin-top: 32px; padding-top: 20px; border-top: 1px solid rgba(0,0,0,.08); display: flex; flex-direction: column; gap: 14px; align-items: center; text-align: center; } .theme-dark .whr-footer .whr-foot-bottom { border-top-color: rgba(255,255,255,.1); } @media (min-width: 768px) { .whr-footer .whr-foot-bottom { flex-direction: row; justify-content: space-between; text-align: left; } } .whr-footer .whr-foot-copy { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; opacity: .7; margin: 0; } .whr-footer .whr-foot-copy img.whr-favicon { width: 18px; height: 18px; border-radius: 4px; flex-shrink: 0; } .whr-footer .whr-foot-legal { display: flex; flex-wrap: wrap; gap: 6px 16px; justify-content: center; font-size: 12px; } .whr-footer .whr-foot-legal a { color: inherit; opacity: .75; text-decoration: none; } .whr-footer .whr-foot-legal a:hover { opacity: 1; } .whr-footer .whr-foot-legal .whr-admin-link { color: #e74c3c !important; opacity: 1; } .whr-footer .whr-foot-social { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; padding: 0; margin: 0; } .whr-footer .whr-foot-social a { width: 32px; height: 32px; border-radius: 8px; background: #fff; display: inline-flex; align-items: center; justify-content: center; color: #2c2c46; text-decoration: none !important; transition: background .2s ease, color .2s ease, transform .15s ease; box-shadow: 0 1px 2px rgba(0,0,0,.04); } .whr-footer .whr-foot-social a:hover { background: var(--theme-color, #6C3AED); color: #fff; transform: translateY(-1px); } .theme-dark .whr-footer .whr-foot-social a { background: #34344a; color: #fff; box-shadow: none; } .whr-footer .whr-foot-social i { font-size: 14px; } @media (max-width: 575.98px) { .whr-footer { padding: 24px 18px 20px; margin-left: 8px; margin-right: 8px; } .whr-store-dropdown { min-width: 220px; max-width: 90vw; } }</style><footer class="whr-footer" role="contentinfo"> {# === Grille principale 5 colonnes === #} <div class="whr-foot-grid"> {# ===== Col 1 : Mon compte / Commencer ici ===== #} <div class="whr-foot-col whr-foot-col-action"> {% if connectUser %} <h4>{{ 'layout.footer.my_account'|trans({}, 'whr-public')|default('Mon compte') }}</h4> {% else %} <h4>{{ 'layout.footer.start_here'|trans({}, 'whr-public')|default('Commencer ici') }}</h4> {% endif %} <div class="whr-stores"> {# === Dropdown unifié (FR & EN) — la version FR aura FR en featured, la EN aura US === #} {# -- Bouton App Store + dropdown -- #} {% set _hasIos = false %} {% for c in _storePrimary %}{% if c.ios %}{% set _hasIos = true %}{% endif %}{% endfor %} {% for c in _storeOthers %}{% if c.ios %}{% set _hasIos = true %}{% endif %}{% endfor %} {% if _hasIos %} <div class="whr-store-wrap" data-whr-store="ios"> <button type="button" class="whr-store-link" aria-haspopup="true" aria-expanded="false" aria-label="App Store - Choose your country"> <svg width="18" height="18" viewBox="0 0 24 24" fill="#fff" aria-hidden="true"> <path d="M18.71 19.5C17.88 20.74 17 21.95 15.66 21.97C14.32 22 13.89 21.18 12.37 21.18C10.84 21.18 10.37 21.95 9.09997 22C7.78997 22.05 6.79997 20.68 5.95997 19.47C4.24997 17 2.93997 12.45 4.69997 9.39C5.56997 7.87 7.12997 6.91 8.81997 6.88C10.1 6.86 11.32 7.75 12.11 7.75C12.89 7.75 14.37 6.68 15.92 6.84C16.57 6.87 18.39 7.1 19.56 8.82C19.47 8.88 17.39 10.1 17.41 12.63C17.44 15.65 20.06 16.66 20.09 16.67C20.06 16.74 19.67 18.11 18.71 19.5ZM13 3.5C13.73 2.67 14.94 2.04 15.94 2C16.07 3.17 15.6 4.35 14.9 5.19C14.21 6.04 13.07 6.7 11.95 6.61C11.8 5.46 12.36 4.26 13 3.5Z"/> </svg> <span> <small>{{ 'layout.download_on'|trans({}, 'whr-public')|default('Download on') }}</small> <strong>App Store</strong> </span> <span class="whr-store-chevron" aria-hidden="true">▲</span> </button> <div class="whr-store-dropdown" role="menu"> {# Search bar (n'apparaît que si > 20 pays "others") #} {% set _iosOthersCount = 0 %} {% for c in _storeOthers %}{% if c.ios %}{% set _iosOthersCount = _iosOthersCount + 1 %}{% endif %}{% endfor %} {% if _iosOthersCount > 20 %} <div class="whr-store-search-wrap"> <input type="text" class="whr-store-search" placeholder="{{ 'layout.search_country'|trans({}, 'whr-public')|default('Search country...') }}" aria-label="Search country" autocomplete="off"> </div> {% endif %} {# Featured (pinné, pas dans le scroll) #} {% set _iosPrimaryCount = 0 %} {% for c in _storePrimary %}{% if c.ios %}{% set _iosPrimaryCount = _iosPrimaryCount + 1 %}{% endif %}{% endfor %} {% if _iosPrimaryCount > 0 %} <div class="whr-store-featured"> <div class="whr-store-dropdown-header"> {{ 'layout.featured'|trans({}, 'whr-public')|default('Featured') }} </div> {% for code, country in _storePrimary %} {% if country.ios %} <a href="{{ country.ios }}" class="whr-store-country" data-search="{{ country.label|lower }} {{ code|lower }}" target="_blank" rel="noopener" role="menuitem"> {% if country.flag %}<span class="whr-flag">{{ country.flag }}</span>{% endif %} <span class="whr-country-name">{{ country.label }}</span> </a> {% endif %} {% endfor %} </div> {% endif %} {# Other regions (grille 2 colonnes, scrollable) #} {% if _storeOthers is not empty %} <div class="whr-store-others"> <div class="whr-store-dropdown-header"> {{ 'layout.other_regions'|trans({}, 'whr-public')|default('Other regions') }} </div> <div class="whr-store-grid"> {% for code, country in _storeOthers %} {% if country.ios %} <a href="{{ country.ios }}" class="whr-store-country" data-search="{{ country.label|lower }} {{ code|lower }}" target="_blank" rel="noopener" role="menuitem"> {% if country.flag %}<span class="whr-flag">{{ country.flag }}</span>{% endif %} <span class="whr-country-name">{{ country.label }}</span> </a> {% endif %} {% endfor %} </div> <div class="whr-store-empty" style="display: none;"> {{ 'layout.no_country_found'|trans({}, 'whr-public')|default('No country found') }} </div> </div> {% endif %} </div> </div> {% endif %} {# -- Bouton Google Play + dropdown -- #} {% set _hasAndroid = false %} {% for c in _storePrimary %}{% if c.android %}{% set _hasAndroid = true %}{% endif %}{% endfor %} {% for c in _storeOthers %}{% if c.android %}{% set _hasAndroid = true %}{% endif %}{% endfor %} {% if _hasAndroid %} <div class="whr-store-wrap" data-whr-store="android"> <button type="button" class="whr-store-link" aria-haspopup="true" aria-expanded="false" aria-label="Google Play - Choose your country"> <svg width="18" height="18" viewBox="0 0 512 512" aria-hidden="true"> <path style="fill:#3A9BC8;" d="M225.656,256.052L14.016,485.451l-6.442,7.052c-4.005-5.919-6.704-12.972-7.313-20.806C0.087,470.305,0,468.91,0,467.518V44.499c0-9.488,2.873-18.02,7.574-24.987L225.656,256.052z"/> <path style="fill:#9BCD83;" d="M320.811,152.8l-95.155,103.253L7.574,19.512C19.936,1.405,45.183-6.342,66.6,6.02L320.811,152.8z"/> <path style="fill:#EEB84C;" d="M455.056,257.27c-0.348,14.453-7.748,28.904-22.113,37.174l-112.132,64.771l-95.155-103.163L320.811,152.8l70.518,40.745l41.614,24.026C448.178,226.366,455.579,241.861,455.056,257.27z"/> <path style="fill:#B43F70;" d="M7.591,492.492c12.368,18.116,37.599,25.838,58.976,13.496L320.775,359.22l-95.156-103.209L7.591,492.492z"/> </svg> <span> <small>{{ 'layout.available_on'|trans({}, 'whr-public')|default('Available on') }}</small> <strong>Google Play</strong> </span> <span class="whr-store-chevron" aria-hidden="true">▲</span> </button> <div class="whr-store-dropdown" role="menu"> {# Search bar (n'apparaît que si > 20 pays "others") #} {% set _androidOthersCount = 0 %} {% for c in _storeOthers %}{% if c.android %}{% set _androidOthersCount = _androidOthersCount + 1 %}{% endif %}{% endfor %} {% if _androidOthersCount > 20 %} <div class="whr-store-search-wrap"> <input type="text" class="whr-store-search" placeholder="{{ 'layout.search_country'|trans({}, 'whr-public')|default('Search country...') }}" aria-label="Search country" autocomplete="off"> </div> {% endif %} {# Featured (pinné) #} {% set _androidPrimaryCount = 0 %} {% for c in _storePrimary %}{% if c.android %}{% set _androidPrimaryCount = _androidPrimaryCount + 1 %}{% endif %}{% endfor %} {% if _androidPrimaryCount > 0 %} <div class="whr-store-featured"> <div class="whr-store-dropdown-header"> {{ 'layout.featured'|trans({}, 'whr-public')|default('Featured') }} </div> {% for code, country in _storePrimary %} {% if country.android %} <a href="{{ country.android }}" class="whr-store-country" data-search="{{ country.label|lower }} {{ code|lower }}" target="_blank" rel="noopener" role="menuitem"> {% if country.flag %}<span class="whr-flag">{{ country.flag }}</span>{% endif %} <span class="whr-country-name">{{ country.label }}</span> </a> {% endif %} {% endfor %} </div> {% endif %} {# Other regions (grille 2 colonnes) #} {% if _storeOthers is not empty %} <div class="whr-store-others"> <div class="whr-store-dropdown-header"> {{ 'layout.other_regions'|trans({}, 'whr-public')|default('Other regions') }} </div> <div class="whr-store-grid"> {% for code, country in _storeOthers %} {% if country.android %} <a href="{{ country.android }}" class="whr-store-country" data-search="{{ country.label|lower }} {{ code|lower }}" target="_blank" rel="noopener" role="menuitem"> {% if country.flag %}<span class="whr-flag">{{ country.flag }}</span>{% endif %} <span class="whr-country-name">{{ country.label }}</span> </a> {% endif %} {% endfor %} </div> <div class="whr-store-empty" style="display: none;"> {{ 'layout.no_country_found'|trans({}, 'whr-public')|default('No country found') }} </div> </div> {% endif %} </div> </div> {% endif %} </div> <ul class="whr-foot-action-links"> <li> <a href="{{ path('whileresume_homepage') }}"> <i class="feather-flag"></i> English </a> </li> <li> <a href="{{ path('locale_whileresume_homepage',{'_locale':'fr'}) }}"> <i class="feather-flag"></i> Français </a> </li> </ul> </div> {# ===== Col 2 : Articles récents (featured) ===== #} <div class="whr-foot-col"> <h4>{{ 'layout.footer.latest_articles'|trans({}, 'whr-public')|default('Articles récents') }}</h4> {% if footerArticles is not empty %} <ul> {% for article in footerArticles %} <li> <a href="{% if _isFr %}{{ path('locale_cvs_website_article', {'_locale': _locale, 'slug': article.slug}) }}{% else %}{{ path('cvs_website_article', {'slug': article.slug}) }}{% endif %}" title="{{ article.title }}"> {{ article.shortTitle ?: cleanSubstr(article.title, 45) }} </a> </li> {% endfor %} </ul> {% else %} <p class="whr-foot-empty">{{ 'layout.footer.coming_soon'|trans({}, 'whr-public')|default('Bientôt disponible') }}</p> {% endif %} </div> {# ===== Col 3 : Emplois par ville ===== #} <div class="whr-foot-col"> <h4>{{ 'layout.footer.jobs_by_city'|trans({}, 'whr-public')|default('Emplois par ville') }}</h4> {% if footerJobsCities is not empty %} <ul> {% for city in footerJobsCities %} <li> <a class="whr-city-link" href="{% if _isFr %}{{ path('locale_cvs_application_jobs_filter', {'_locale': _locale, 'slug': city.slug}) }}{% else %}{{ path('cvs_application_jobs_filter', {'slug': city.slug}) }}{% endif %}" title="{{ city.shortTitle ?: city.label }}"> {% if city.icon %} <span class="whr-city-icon">{{ city.icon }}</span> {% else %} <i class="feather-map-pin whr-city-icon"></i> {% endif %} <span>{{ city.label }}</span> </a> </li> {% endfor %} </ul> {% else %} <p class="whr-foot-empty">{{ 'layout.footer.coming_soon'|trans({}, 'whr-public')|default('Bientôt disponible') }}</p> {% endif %} </div> {# ===== Col 4 : Entreprises par ville ===== #} <div class="whr-foot-col"> <h4>{{ 'layout.footer.companies_by_city'|trans({}, 'whr-public')|default('Entreprises par ville') }}</h4> {% if footerEnterprisesCities is not empty %} <ul> {% for city in footerEnterprisesCities %} <li> <a class="whr-city-link" href="{% if _isFr %}{{ path('locale_cvs_application_companies_filter', {'_locale': _locale, 'slug': city.slug}) }}{% else %}{{ path('cvs_application_companies_filter', {'slug': city.slug}) }}{% endif %}" title="{{ city.shortTitle ?: city.label }}"> {% if city.icon %} <span class="whr-city-icon">{{ city.icon }}</span> {% else %} <i class="feather-map-pin whr-city-icon"></i> {% endif %} <span>{{ city.label }}</span> </a> </li> {% endfor %} </ul> {% else %} <p class="whr-foot-empty">{{ 'layout.footer.coming_soon'|trans({}, 'whr-public')|default('Bientôt disponible') }}</p> {% endif %} </div> {# ===== Col 5 : Pages SEO (LandingJobs featured) ===== #} <div class="whr-foot-col"> <h4>{{ 'layout.footer.featured_pages'|trans({}, 'whr-public')|default('À découvrir') }}</h4> {% if footerLandingJobs is not empty %} <ul> {% for landing in footerLandingJobs %} <li> <a href="{% if _isFr %}{{ path('locale_whileresume_homepage_landing', {'_locale': _locale, 'slug': landing.slug}) }}{% else %}{{ path('whileresume_homepage_landing', {'slug': landing.slug}) }}{% endif %}"> {{ landing.title }} </a> </li> {% endfor %} </ul> {% endif %} </div> </div> {# === Bas du footer === #} <div class="whr-foot-bottom"> <p class="whr-foot-copy"> {% if favicon %} <img src="{{ favicon }}" alt="" class="whr-favicon" /> {% endif %} <span>© {{ "now"|date('Y') }} {{ websitename }}. {{ 'layout.rights_reserved'|trans({}, 'whr-public')|default('Tous droits réservés.') }}</span> </p> <div class="whr-foot-legal"> {% set menuFooter = getMenuWebsiteLocaleArray(_locale, "footer", connectUser) %} {% if menuFooter is not empty %} {% for m in menuFooter %} <a href="{{ m.link }}" aria-label="{{ m.title }}" title="{{ m.title }}" {% if m.targetBlank == 1 %}target="_blank" rel="noreferrer"{% endif %}> {{ m.title }} </a> {% endfor %} {% endif %} {% if app.user is not null and is_granted("ROLE_SUPER_ADMIN") %} <a href="{{ path('backoffice_dashboard') }}" class="whr-admin-link" title="Administration"> <i class="feather-settings"></i> Administration </a> {% endif %} </div> <ul class="whr-foot-social"> {% if facebook %} <li><a href="{{ facebook }}" target="_blank" rel="noopener" aria-label="Facebook"><i class="feather-facebook"></i></a></li> {% endif %} {% if twitter %} <li><a href="{{ twitter }}" target="_blank" rel="noopener" aria-label="X / Twitter"><i class="feather-twitter"></i></a></li> {% endif %} {% if instagram %} <li><a href="{{ instagram }}" target="_blank" rel="noopener" aria-label="Instagram"><i class="feather-instagram"></i></a></li> {% endif %} {% if linkedin %} <li><a href="{{ linkedin }}" target="_blank" rel="noopener" aria-label="LinkedIn"><i class="feather-linkedin"></i></a></li> {% endif %} {% if youtube %} <li><a href="{{ youtube }}" target="_blank" rel="noopener" aria-label="YouTube"><i class="feather-youtube"></i></a></li> {% endif %} </ul> </div></footer>{# ====== JS dropdown stores (vanilla, autonome, pas de dépendance) ====== #}<script> (function() { 'use strict'; function closeAllDropdowns() { document.querySelectorAll('.whr-store-wrap.is-open').forEach(function(w) { w.classList.remove('is-open'); var b = w.querySelector('.whr-store-link'); if (b) b.setAttribute('aria-expanded', 'false'); // Reset search à la fermeture var input = w.querySelector('.whr-store-search'); if (input) { input.value = ''; applyFilter(w, ''); } }); } function applyFilter(wrap, query) { query = (query || '').trim().toLowerCase(); var items = wrap.querySelectorAll('.whr-store-country'); var othersWrap = wrap.querySelector('.whr-store-others'); var emptyMsg = wrap.querySelector('.whr-store-empty'); var grid = wrap.querySelector('.whr-store-grid'); var visibleInOthers = 0; items.forEach(function(item) { var searchData = item.dataset.search || ''; var matches = query === '' || searchData.indexOf(query) !== -1; if (matches) { item.classList.remove('is-hidden'); // Compter uniquement les items dans la grille "others" (pas le featured) if (grid && grid.contains(item)) { visibleInOthers++; } } else { item.classList.add('is-hidden'); } }); // Afficher le message "aucun résultat" si rien ne matche dans others if (emptyMsg && grid) { if (query !== '' && visibleInOthers === 0) { grid.style.display = 'none'; emptyMsg.style.display = 'block'; } else { grid.style.display = ''; emptyMsg.style.display = 'none'; } } } function initWhrStoreDropdowns() { var wraps = document.querySelectorAll('.whr-store-wrap'); if (!wraps.length) return; wraps.forEach(function(wrap) { var btn = wrap.querySelector('.whr-store-link'); if (!btn || btn.dataset.whrInit === '1') return; btn.dataset.whrInit = '1'; // === Toggle au clic sur le bouton === btn.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); var isOpen = wrap.classList.contains('is-open'); closeAllDropdowns(); if (!isOpen) { wrap.classList.add('is-open'); btn.setAttribute('aria-expanded', 'true'); // Auto-focus sur la search à l'ouverture (desktop seulement, // pour éviter le clavier qui pop sur mobile) var input = wrap.querySelector('.whr-store-search'); if (input && window.innerWidth >= 768) { setTimeout(function() { input.focus(); }, 50); } } }); // === Filtrage live sur la search === var input = wrap.querySelector('.whr-store-search'); if (input) { input.addEventListener('input', function() { applyFilter(wrap, this.value); }); // Empêcher la fermeture du dropdown quand on clique dans le champ input.addEventListener('click', function(e) { e.stopPropagation(); }); // Échap dans le champ → vider la recherche d'abord, puis fermer input.addEventListener('keydown', function(e) { if (e.key === 'Escape') { if (this.value !== '') { this.value = ''; applyFilter(wrap, ''); e.stopPropagation(); } } }); } }); // === Listeners globaux (un seul fois) === if (!document.body.dataset.whrStoreOutsideInit) { document.body.dataset.whrStoreOutsideInit = '1'; // Click outside → close document.addEventListener('click', function(e) { if (!e.target.closest('.whr-store-wrap')) { closeAllDropdowns(); } }); // ESC → close document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { closeAllDropdowns(); } }); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initWhrStoreDropdowns); } else { initWhrStoreDropdowns(); } })();</script>