templates/application/whileresume/website/components/footer.html.twig line 41

Open in your IDE?
  1. {# =========================================================
  2.    FOOTER WhileResume — thème Sociala (v4 — routes vérifiées)
  3.    Colonnes :
  4.      1. Mon compte / Commencer ici (stores + liens action)
  5.      2. Articles récents (featured ArticlesRepository::getLast)
  6.      3. Emplois par ville (JobsFilters type=city)
  7.      4. Entreprises par ville (EnterprisesFilters type=city)
  8.      5. Pages SEO (LandingJobs featured)
  9.    ⚠️ Routes utilisées (vérifiées contre routes.yml) :
  10.      ✓ whileresume_homepage / locale_whileresume_homepage
  11.      ✓ cvs_website_article / locale_cvs_website_article
  12.      ✓ cvs_application_jobs_filter / locale_cvs_application_jobs_filter
  13.      ✓ cvs_application_companies_filter / locale_cvs_application_companies_filter
  14.      ✓ cvs_application_job_new / locale_cvs_application_job_new (= /post-a-job)
  15.      ✓ whileresume_jobs_list / locale_whileresume_jobs_list
  16.      ✓ whileresume_companies_list / locale_whileresume_companies_list
  17.      ✓ app_logout
  18.      ⚠️ À CONFIRMER (pas dans routes.yml uploadé — sans doute dans whileresume_resume/whileresume_business) :
  19.      - app_login / locale_app_login → bouton login
  20.      - cvs_gestion_candidates_register / locale_… → inscription candidat
  21.      - cvs_gestion_enterprises_register / locale_… → inscription pro
  22.      - cvs_application_cv_builder / locale_… → créateur de CV
  23.      - cvs_gestion_candidates_profile_profile → profil candidat connecté
  24.      - cvs_gestion_enterprises_profile_profile → profil entreprise connecté
  25.      - cvs_gestion_enterprises_settings → settings entreprise
  26.      - cvs_application_landing_jobs_show → page d'une LandingJobs (slug)
  27.    👉 Si une route n'existe pas, remplace-la directement dans ce fichier
  28.       (un seul endroit à modifier par lien).
  29.    ========================================================= #}
  30. {% set _locale = app.request.locale %}
  31. {% set _isFr = _locale == 'fr' %}
  32. {# Données dynamiques #}
  33. {% set footerArticles = getFooterArticles(_locale, 5) %}
  34. {% set footerLandingJobs = getFooterFeaturedLandingJobs(_locale, 5) %}
  35. {% set footerJobsCities = getFooterJobsCities(_locale, 6) %}
  36. {% set footerEnterprisesCities = getFooterEnterprisesCities(_locale, 6) %}
  37. <style>
  38.     /* ---------- Footer WhileResume ---------- */
  39.     .whr-footer {
  40.         margin-top: 32px;
  41.         padding: 36px 24px 24px;
  42.         background: #F9FAFD;
  43.         border-radius: 16px;
  44.         color: #2c2c46;
  45.     }
  46.     .theme-dark .whr-footer {
  47.         background: #2a2a3c;
  48.         color: #e9e9ef;
  49.     }
  50.     /* Stores en haut de la col 1 */
  51.     .whr-footer .whr-stores {
  52.         display: flex;
  53.         flex-direction: column;
  54.         gap: 8px;
  55.         margin-bottom: 18px;
  56.     }
  57.     .whr-footer .whr-store-link {
  58.         display: inline-flex;
  59.         align-items: center;
  60.         gap: 10px;
  61.         padding: 8px 14px;
  62.         background: #111;
  63.         color: #fff !important;
  64.         border-radius: 10px;
  65.         font-size: 12px;
  66.         font-weight: 600;
  67.         text-decoration: none !important;
  68.         line-height: 1.2;
  69.         transition: transform .15s ease, background .2s ease;
  70.         max-width: 170px;
  71.     }
  72.     .whr-footer .whr-store-link:hover {
  73.         background: #2c2c46;
  74.         transform: translateY(-1px);
  75.     }
  76.     .whr-footer .whr-store-link small {
  77.         display: block;
  78.         font-weight: 400;
  79.         font-size: 10px;
  80.         opacity: .7;
  81.     }
  82.     .whr-footer .whr-store-link strong { font-size: 13px; display: block; }
  83.     /* Colonnes */
  84.     .whr-footer .whr-foot-col h4 {
  85.         font-size: 13px;
  86.         font-weight: 700;
  87.         margin: 0 0 14px 0;
  88.         color: inherit;
  89.         text-transform: uppercase;
  90.         letter-spacing: .3px;
  91.     }
  92.     .whr-footer .whr-foot-col ul {
  93.         list-style: none;
  94.         padding: 0;
  95.         margin: 0;
  96.         font-size: 13px;
  97.     }
  98.     .whr-footer .whr-foot-col ul li { margin-bottom: 10px; }
  99.     .whr-footer .whr-foot-col a {
  100.         color: inherit;
  101.         opacity: .75;
  102.         text-decoration: none;
  103.         transition: opacity .2s ease, color .2s ease;
  104.     }
  105.     .whr-footer .whr-foot-col a:hover { opacity: 1; color: var(--theme-color, #6C3AED); }
  106.     .whr-footer .whr-foot-empty {
  107.         font-size: 12px;
  108.         opacity: .5;
  109.         font-style: italic;
  110.     }
  111.     /* Liste avec icônes (col 1) */
  112.     .whr-footer .whr-foot-action-links a {
  113.         display: inline-flex;
  114.         align-items: center;
  115.         gap: 8px;
  116.     }
  117.     .whr-footer .whr-foot-action-links a i {
  118.         font-size: 14px;
  119.         opacity: .7;
  120.         width: 16px;
  121.         text-align: center;
  122.     }
  123.     /* Mini-icône ville pour cols 3 et 4 */
  124.     .whr-footer .whr-foot-col .whr-city-link {
  125.         display: inline-flex;
  126.         align-items: center;
  127.         gap: 6px;
  128.     }
  129.     .whr-footer .whr-foot-col .whr-city-link .whr-city-icon {
  130.         font-size: 14px;
  131.         line-height: 1;
  132.         display: inline-block;
  133.         width: 18px;
  134.         text-align: center;
  135.         opacity: .85;
  136.     }
  137.     /* Grille principale : 1 col → 2 cols → 5 cols */
  138.     .whr-footer .whr-foot-grid {
  139.         display: grid;
  140.         gap: 28px;
  141.         grid-template-columns: 1fr;
  142.     }
  143.     @media (min-width: 576px) {
  144.         .whr-footer .whr-foot-grid { grid-template-columns: 1fr 1fr; }
  145.     }
  146.     @media (min-width: 992px) {
  147.         .whr-footer .whr-foot-grid {
  148.             grid-template-columns: repeat(5, 1fr);
  149.             gap: 32px;
  150.         }
  151.     }
  152.     /* Bottom bar */
  153.     .whr-footer .whr-foot-bottom {
  154.         margin-top: 32px;
  155.         padding-top: 20px;
  156.         border-top: 1px solid rgba(0,0,0,.08);
  157.         display: flex;
  158.         flex-direction: column;
  159.         gap: 14px;
  160.         align-items: center;
  161.         text-align: center;
  162.     }
  163.     .theme-dark .whr-footer .whr-foot-bottom { border-top-color: rgba(255,255,255,.1); }
  164.     @media (min-width: 768px) {
  165.         .whr-footer .whr-foot-bottom {
  166.             flex-direction: row;
  167.             justify-content: space-between;
  168.             text-align: left;
  169.         }
  170.     }
  171.     .whr-footer .whr-foot-copy {
  172.         display: inline-flex;
  173.         align-items: center;
  174.         gap: 8px;
  175.         font-size: 12px;
  176.         opacity: .7;
  177.         margin: 0;
  178.     }
  179.     .whr-footer .whr-foot-copy img.whr-favicon {
  180.         width: 18px;
  181.         height: 18px;
  182.         border-radius: 4px;
  183.         flex-shrink: 0;
  184.     }
  185.     .whr-footer .whr-foot-legal {
  186.         display: flex;
  187.         flex-wrap: wrap;
  188.         gap: 6px 16px;
  189.         justify-content: center;
  190.         font-size: 12px;
  191.     }
  192.     .whr-footer .whr-foot-legal a {
  193.         color: inherit;
  194.         opacity: .75;
  195.         text-decoration: none;
  196.     }
  197.     .whr-footer .whr-foot-legal a:hover { opacity: 1; }
  198.     .whr-footer .whr-foot-legal .whr-admin-link { color: #e74c3c !important; opacity: 1; }
  199.     .whr-footer .whr-foot-social {
  200.         display: flex;
  201.         flex-wrap: wrap;
  202.         gap: 6px;
  203.         list-style: none;
  204.         padding: 0;
  205.         margin: 0;
  206.     }
  207.     .whr-footer .whr-foot-social a {
  208.         width: 32px; height: 32px;
  209.         border-radius: 8px;
  210.         background: #fff;
  211.         display: inline-flex;
  212.         align-items: center;
  213.         justify-content: center;
  214.         color: #2c2c46;
  215.         text-decoration: none !important;
  216.         transition: background .2s ease, color .2s ease, transform .15s ease;
  217.         box-shadow: 0 1px 2px rgba(0,0,0,.04);
  218.     }
  219.     .whr-footer .whr-foot-social a:hover {
  220.         background: var(--theme-color, #6C3AED);
  221.         color: #fff;
  222.         transform: translateY(-1px);
  223.     }
  224.     .theme-dark .whr-footer .whr-foot-social a {
  225.         background: #34344a;
  226.         color: #fff;
  227.         box-shadow: none;
  228.     }
  229.     .whr-footer .whr-foot-social i { font-size: 14px; }
  230.     .middle-sidebar-left .whr-footer { width: 100%; }
  231.     @media (max-width: 575.98px) {
  232.         .whr-footer { padding: 24px 18px 20px; }
  233.     }
  234. </style>
  235. <footer class="whr-footer" role="contentinfo">
  236.     {# === Grille principale 5 colonnes === #}
  237.     <div class="whr-foot-grid">
  238.         {# ===== Col 1 : Mon compte / Commencer ici ===== #}
  239.         {% if _isFr %}
  240.             {% set _ios = ios_fr %}
  241.             {% set _android = android_fr %}
  242.         {% else %}
  243.             {% set _ios = ios_us %}
  244.             {% set _android = android_us %}
  245.         {% endif %}
  246.         <div class="whr-foot-col whr-foot-col-action">
  247.             {% if connectUser %}
  248.                 <h4>{{ 'layout.footer.my_account'|trans({}, 'whr-public')|default('Mon compte') }}</h4>
  249.             {% else %}
  250.                 <h4>{{ 'layout.footer.start_here'|trans({}, 'whr-public')|default('Commencer ici') }}</h4>
  251.             {% endif %}
  252.             <div class="whr-stores">
  253.                 {% if _ios %}
  254.                     <a href="{{ _ios }}" class="whr-store-link" target="_blank" rel="noopener" aria-label="App Store">
  255.                         <svg width="18" height="18" viewBox="0 0 24 24" fill="#fff" aria-hidden="true">
  256.                             <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"/>
  257.                         </svg>
  258.                         <span>
  259.                             <small>{{ 'layout.download_on'|trans({}, 'whr-public')|default('Télécharger sur') }}</small>
  260.                             <strong>App Store</strong>
  261.                         </span>
  262.                     </a>
  263.                 {% endif %}
  264.                 {% if _android %}
  265.                     <a href="{{ _android }}" class="whr-store-link" target="_blank" rel="noopener" aria-label="Google Play">
  266.                         <svg width="18" height="18" viewBox="0 0 512 512" aria-hidden="true">
  267.                             <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"/>
  268.                             <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"/>
  269.                             <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"/>
  270.                             <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"/>
  271.                         </svg>
  272.                         <span>
  273.                             <small>{{ 'layout.available_on'|trans({}, 'whr-public')|default('Disponible sur') }}</small>
  274.                             <strong>Google Play</strong>
  275.                         </span>
  276.                     </a>
  277.                 {% endif %}
  278.             </div>
  279.             <ul class="whr-foot-action-links">
  280.                 {% if connectUser %}
  281.                     {% if isCandidateUser %}
  282.                         <li>
  283.                             <a href="{% if _isFr %}{{ path('locale_cvs_gestion_candidates_profile_profile', {'_locale': _locale}) }}{% else %}{{ path('cvs_gestion_candidates_profile_profile') }}{% endif %}">
  284.                                 <i class="feather-user"></i>
  285.                                 {{ 'layout.footer.my_profile'|trans({}, 'whr-public')|default('Mon profil') }}
  286.                             </a>
  287.                         </li>
  288.                     {% else %}
  289.                         <li>
  290.                             <a href="{% if _isFr %}{{ path('locale_cvs_gestion_enterprises_profile_profile', {'_locale': _locale}) }}{% else %}{{ path('cvs_gestion_enterprises_profile_profile') }}{% endif %}">
  291.                                 <i class="feather-user"></i>
  292.                                 {{ 'layout.footer.my_profile'|trans({}, 'whr-public')|default('Mon profil') }}
  293.                             </a>
  294.                         </li>
  295.                         <li>
  296.                             <a href="{% if _isFr %}{{ path('locale_cvs_gestion_enterprises_settings', {'_locale': _locale}) }}{% else %}{{ path('cvs_gestion_enterprises_settings') }}{% endif %}">
  297.                                 <i class="feather-settings"></i>
  298.                                 {{ 'layout.footer.settings'|trans({}, 'whr-public')|default('Paramètres') }}
  299.                             </a>
  300.                         </li>
  301.                     {% endif %}
  302.                     <li>
  303.                         <a href="{{ path('app_logout') }}">
  304.                             <i class="feather-log-out"></i>
  305.                             {{ 'layout.footer.logout'|trans({}, 'whr-public')|default('Déconnexion') }}
  306.                         </a>
  307.                     </li>
  308.                 {% else %}
  309.                     {# Pas connecté : on pousse vers les CTA principaux du site #}
  310.                     <li>
  311.                         <a href="{% if _isFr %}{{ path('locale_whileresume_jobs_list', {'_locale': _locale}) }}{% else %}{{ path('whileresume_jobs_list') }}{% endif %}">
  312.                             <i class="feather-briefcase"></i>
  313.                             {{ 'layout.footer.browse_jobs'|trans({}, 'whr-public')|default('Voir les offres') }}
  314.                         </a>
  315.                     </li>
  316.                     <li>
  317.                         <a href="{% if _isFr %}{{ path('locale_whileresume_companies_list', {'_locale': _locale}) }}{% else %}{{ path('whileresume_companies_list') }}{% endif %}">
  318.                             <i class="feather-grid"></i>
  319.                             {{ 'layout.footer.browse_companies'|trans({}, 'whr-public')|default('Voir les entreprises') }}
  320.                         </a>
  321.                     </li>
  322.                     <li>
  323.                         <a href="{% if _isFr %}{{ path('locale_cvs_application_job_new', {'_locale': _locale}) }}{% else %}{{ path('cvs_application_job_new') }}{% endif %}">
  324.                             <i class="feather-plus-circle"></i>
  325.                             {{ 'layout.footer.post_job'|trans({}, 'whr-public')|default('Publier une offre') }}
  326.                         </a>
  327.                     </li>
  328.                 {% endif %}
  329.             </ul>
  330.         </div>
  331.         {# ===== Col 2 : Articles récents (featured) ===== #}
  332.         <div class="whr-foot-col">
  333.             <h4>{{ 'layout.footer.latest_articles'|trans({}, 'whr-public')|default('Articles récents') }}</h4>
  334.             {% if footerArticles is not empty %}
  335.                 <ul>
  336.                     {% for article in footerArticles %}
  337.                         <li>
  338.                             <a href="{% if _isFr %}{{ path('locale_cvs_website_article', {'_locale': _locale, 'slug': article.slug}) }}{% else %}{{ path('cvs_website_article', {'slug': article.slug}) }}{% endif %}"
  339.                                title="{{ article.title }}">
  340.                                 {{ article.shortTitle ?: cleanSubstr(article.title, 45) }}
  341.                             </a>
  342.                         </li>
  343.                     {% endfor %}
  344.                 </ul>
  345.             {% else %}
  346.                 <p class="whr-foot-empty">{{ 'layout.footer.coming_soon'|trans({}, 'whr-public')|default('Bientôt disponible') }}</p>
  347.             {% endif %}
  348.         </div>
  349.         {# ===== Col 3 : Emplois par ville ===== #}
  350.         <div class="whr-foot-col">
  351.             <h4>{{ 'layout.footer.jobs_by_city'|trans({}, 'whr-public')|default('Emplois par ville') }}</h4>
  352.             {% if footerJobsCities is not empty %}
  353.                 <ul>
  354.                     {% for city in footerJobsCities %}
  355.                         <li>
  356.                             <a class="whr-city-link"
  357.                                href="{% if _isFr %}{{ path('locale_cvs_application_jobs_filter', {'_locale': _locale, 'slug': city.slug}) }}{% else %}{{ path('cvs_application_jobs_filter', {'slug': city.slug}) }}{% endif %}"
  358.                                title="{{ city.shortTitle ?: city.label }}">
  359.                                 {% if city.icon %}
  360.                                     <span class="whr-city-icon">{{ city.icon }}</span>
  361.                                 {% else %}
  362.                                     <i class="feather-map-pin whr-city-icon"></i>
  363.                                 {% endif %}
  364.                                 <span>{{ city.label }}</span>
  365.                             </a>
  366.                         </li>
  367.                     {% endfor %}
  368.                 </ul>
  369.             {% else %}
  370.                 <p class="whr-foot-empty">{{ 'layout.footer.coming_soon'|trans({}, 'whr-public')|default('Bientôt disponible') }}</p>
  371.             {% endif %}
  372.         </div>
  373.         {# ===== Col 4 : Entreprises par ville ===== #}
  374.         <div class="whr-foot-col">
  375.             <h4>{{ 'layout.footer.companies_by_city'|trans({}, 'whr-public')|default('Entreprises par ville') }}</h4>
  376.             {% if footerEnterprisesCities is not empty %}
  377.                 <ul>
  378.                     {% for city in footerEnterprisesCities %}
  379.                         <li>
  380.                             <a class="whr-city-link"
  381.                                href="{% if _isFr %}{{ path('locale_cvs_application_companies_filter', {'_locale': _locale, 'slug': city.slug}) }}{% else %}{{ path('cvs_application_companies_filter', {'slug': city.slug}) }}{% endif %}"
  382.                                title="{{ city.shortTitle ?: city.label }}">
  383.                                 {% if city.icon %}
  384.                                     <span class="whr-city-icon">{{ city.icon }}</span>
  385.                                 {% else %}
  386.                                     <i class="feather-map-pin whr-city-icon"></i>
  387.                                 {% endif %}
  388.                                 <span>{{ city.label }}</span>
  389.                             </a>
  390.                         </li>
  391.                     {% endfor %}
  392.                 </ul>
  393.             {% else %}
  394.                 <p class="whr-foot-empty">{{ 'layout.footer.coming_soon'|trans({}, 'whr-public')|default('Bientôt disponible') }}</p>
  395.             {% endif %}
  396.         </div>
  397.         {# ===== Col 5 : Pages SEO (LandingJobs featured) =====
  398.              ⚠️ Route 'cvs_application_landing_jobs_show' non trouvée dans tes
  399.              routes.yml (peut-être dans whileresume_resume.yml ?). Adapte si besoin. #}
  400.         <div class="whr-foot-col">
  401.             <h4>{{ 'layout.footer.featured_pages'|trans({}, 'whr-public')|default('À découvrir') }}</h4>
  402.             {% if footerLandingJobs is not empty %}
  403.                 <ul>
  404.                     {% for landing in footerLandingJobs %}
  405.                         <li>
  406.                             <a href="{% if _isFr %}{{ path('locale_whileresume_homepage_landing', {'_locale': _locale, 'slug': landing.slug}) }}{% else %}{{ path('whileresume_homepage_landing', {'slug': landing.slug}) }}{% endif %}">
  407.                                 {{ landing.title }}
  408.                             </a>
  409.                         </li>
  410.                     {% endfor %}
  411.                 </ul>
  412.             {% endif %}
  413.         </div>
  414.     </div>
  415.     {# === Bas du footer === #}
  416.     <div class="whr-foot-bottom">
  417.         <p class="whr-foot-copy">
  418.             {% if favicon %}
  419.                 <img src="{{ favicon }}" alt="" class="whr-favicon" />
  420.             {% endif %}
  421.             <span>&copy; {{ "now"|date('Y') }} {{ websitename }}. {{ 'layout.rights_reserved'|trans({}, 'whr-public')|default('Tous droits réservés.') }}</span>
  422.         </p>
  423.         <div class="whr-foot-legal">
  424.             {% set menuFooter = getMenuWebsiteLocaleArray(_locale, "footer", connectUser) %}
  425.             {% if menuFooter is not empty %}
  426.                 {% for m in menuFooter %}
  427.                     <a href="{{ m.link }}"
  428.                        aria-label="{{ m.title }}"
  429.                        title="{{ m.title }}"
  430.                        {% if m.targetBlank == 1 %}target="_blank" rel="noreferrer"{% endif %}>
  431.                         {{ m.title }}
  432.                     </a>
  433.                 {% endfor %}
  434.             {% endif %}
  435.             {% if app.user is not null and is_granted("ROLE_SUPER_ADMIN") %}
  436.                 <a href="{{ path('backoffice_dashboard') }}" class="whr-admin-link" title="Administration">
  437.                     <i class="feather-settings"></i> Administration
  438.                 </a>
  439.             {% endif %}
  440.         </div>
  441.         <ul class="whr-foot-social">
  442.             {% if facebook %}
  443.                 <li><a href="{{ facebook }}" target="_blank" rel="noopener" aria-label="Facebook"><i class="feather-facebook"></i></a></li>
  444.             {% endif %}
  445.             {% if twitter %}
  446.                 <li><a href="{{ twitter }}" target="_blank" rel="noopener" aria-label="X / Twitter"><i class="feather-twitter"></i></a></li>
  447.             {% endif %}
  448.             {% if instagram %}
  449.                 <li><a href="{{ instagram }}" target="_blank" rel="noopener" aria-label="Instagram"><i class="feather-instagram"></i></a></li>
  450.             {% endif %}
  451.             {% if linkedin %}
  452.                 <li><a href="{{ linkedin }}" target="_blank" rel="noopener" aria-label="LinkedIn"><i class="feather-linkedin"></i></a></li>
  453.             {% endif %}
  454.             {% if youtube %}
  455.                 <li><a href="{{ youtube }}" target="_blank" rel="noopener" aria-label="YouTube"><i class="feather-youtube"></i></a></li>
  456.             {% endif %}
  457.         </ul>
  458.     </div>
  459. </footer>