templates/home/search.html.twig line 1

  1. {% extends 'base_search.html.twig' %}
  2. {% block title %}{{ 'search.title'|trans }}{% endblock %}
  3. {% block body %}
  4. <!-- Contenu principal -->
  5. <div class="flex justify-center">
  6.     <!-- Formulaire de recherche -->
  7.     <form id="search-form" method="GET" action="{{ path('advanced_search') }}" class="space-y-4 w-full max-w-4xl"> <br/>
  8.         <!-- Champs de recherche -->
  9.         <div class="flex flex-col md:flex-row gap-4">
  10.           <!-- Où allez-vous ? (+ rayon) -->
  11.           <div class="flex flex-col relative w-full md:w-1/2">
  12.             <input
  13.               id="address"
  14.               type="text"
  15.               name="city"
  16.               value="{{ app.request.query.get('city') }}"
  17.               placeholder="{{ 'tenant.search_placeholder'|trans }}"
  18.               class="px-4 py-2 w-full border border-gray-300 rounded-lg">
  19.           </div>
  20.           <!-- Champs cachés pour lat et lng -->
  21.           <input type="hidden" name="lat" id="lat" value="{{ app.request.query.get('lat') }}">
  22.           <input type="hidden" name="lng" id="lng" value="{{ app.request.query.get('lng') }}">
  23.           <!-- Type de logement -->
  24.           <div class="flex flex-col relative w-full md:w-1/2">
  25.             <select
  26.                     id="housing-type-search"
  27.                     name="type"
  28.                     class="border border-gray-300 rounded-lg px-4 py-2 w-full text-base">
  29.                     <option value="" {% if not app.request.query.get('type') %}selected{% endif %}>{{ 'search.housing_type_search'|trans }}</option>
  30.                     <option value="Appartement" {% if app.request.query.get('type') == 'Appartement' %}selected{% endif %}>{{ 'search.housing_type_apartment'|trans }}</option>
  31.                     <option value="Maison" {% if app.request.query.get('type') == 'Maison' %}selected{% endif %}>{{ 'search.housing_type_house'|trans }}</option>
  32.                     <option value="Chambre privée" {% if app.request.query.get('type') == 'Chambre privée' %}selected{% endif %}>{{ 'search.housing_type_private_room'|trans }}</option>
  33.                 </select>
  34.           </div>
  35.         </div>
  36.         <!-- Budget and Surface Inputs -->
  37.         <div class="flex flex-col md:flex-row gap-4 mt-4">
  38.           <div class="flex flex-col relative w-full md:w-1/4">
  39.             <input
  40.               id="min-price"
  41.               type="number"
  42.               name="minPrice"
  43.               placeholder="{{ 'tenant.min_price'|trans }}"
  44.               value="{{ app.request.query.get('minPrice') }}"
  45.               class="px-4 py-2 w-full border border-gray-300 rounded-lg"
  46.               min="0">
  47.           </div>
  48.           <!-- Budget maximum -->
  49.           <div class="flex flex-col relative w-full md:w-1/4">
  50.             <input
  51.               id="max-price"
  52.               type="number"
  53.               name="maxPrice"
  54.               placeholder="{{ 'tenant.max_price'|trans }}"
  55.               value="{{ app.request.query.get('maxPrice') }}"
  56.               class="px-4 py-2 w-full border border-gray-300 rounded-lg"
  57.               min="0">
  58.           </div>
  59.           <!-- Surface minimum -->
  60.           <div class="flex flex-col relative w-full md:w-1/4">
  61.             <input
  62.               id="min-surface"
  63.               type="number"
  64.               name="minSurface"
  65.               placeholder="{{ 'tenant.min_surface'|trans }}"
  66.               value="{{ app.request.query.get('minSurface') }}"
  67.               class="px-4 py-2 w-full border border-gray-300 rounded-lg"
  68.               min="0">
  69.           </div>
  70.           <!-- Surface maximum -->
  71.           <div class="flex flex-col relative w-full md:w-1/4">
  72.             <input
  73.               id="max-surface"
  74.               type="number"
  75.               name="maxSurface"
  76.               placeholder="{{ 'tenant.max_surface'|trans }}"
  77.               value="{{ app.request.query.get('maxSurface') }}"
  78.               class="px-4 py-2 w-full border border-gray-300 rounded-lg"
  79.               min="0">
  80.           </div>
  81.         </div>
  82.         <!-- Affiner les critères de recherche -->
  83.         <div class="mt-6">
  84.           <h4 class="text-lg font-semibold text-gray-900 text-center">{{ 'tenant.refine_search'|trans }}</h4>
  85.         </div>
  86.         <div class="flex flex-wrap justify-center gap-4 mt-4">
  87.           <!-- Colocation / Coliving -->
  88.           <div class="flex items-center space-x-2">
  89.             <label class="flex items-center space-x-1">
  90.               <input
  91.                 type="checkbox"
  92.                 name="isShared"
  93.                 value="1"
  94.                 {% if app.request.query.get('isShared') == '1' %}checked{% endif %}
  95.                 class="form-checkbox text-blue-500">
  96.               <span>{{ 'tenant.shared_accommodation'|trans }}</span>
  97.             </label>
  98.           </div>
  99.           <!-- Logement meublé -->
  100.           <div class="flex items-center space-x-2">
  101.             <label class="flex items-center space-x-1">
  102.               <input
  103.                 type="checkbox"
  104.                 name="isFurnished"
  105.                 value="1"
  106.                 {% if app.request.query.get('isFurnished') == '1' %}checked{% endif %}
  107.                 class="form-checkbox text-blue-500">
  108.               <span>{{ 'tenant.furnished'|trans }}</span>
  109.             </label>
  110.           </div>
  111.           <!-- Salle de bain privée -->
  112.           <div class="flex items-center space-x-2">
  113.             <label class="flex items-center space-x-1">
  114.               <input
  115.                 type="checkbox"
  116.                 name="bathroomType"
  117.                 value="private"
  118.                 id="bathroom-private"
  119.                 {% if app.request.query.get('bathroomType') == 'private' %}checked{% endif %}
  120.                 class="form-checkbox text-purple-500">
  121.               <span>{{ 'tenant.bathroom'|trans }}</span>
  122.             </label>
  123.           </div>
  124.           <!-- Filles uniquement -->
  125.           <div class="flex items-center space-x-2">
  126.             <label class="flex items-center space-x-1">
  127.               <input
  128.                 type="checkbox"
  129.                 name="girlsOnly"
  130.                 value="1"
  131.                 {% if app.request.query.get('girlsOnly') == '1' %}checked{% endif %}
  132.                 class="form-checkbox text-purple-500">
  133.               <span>{{ 'houseRules.fille'|trans }}</span>
  134.             </label>
  135.           </div>
  136.           <!-- Garçons uniquement -->
  137.           <div class="flex items-center space-x-2">
  138.             <label class="flex items-center space-x-1">
  139.               <input
  140.                 type="checkbox"
  141.                 name="boysOnly"
  142.                 value="1"
  143.                 {% if app.request.query.get('boysOnly') == '1' %}checked{% endif %}
  144.                 class="form-checkbox text-purple-500">
  145.               <span>{{ 'houseRules.garcon'|trans }}</span>
  146.             </label>
  147.           </div>
  148.           <!-- Fumeur autorisé -->
  149.           <div class="flex items-center space-x-2">
  150.             <label class="flex items-center space-x-1">
  151.               <input
  152.                 type="checkbox"
  153.                 name="smokingAllowed"
  154.                 value="1"
  155.                 {% if app.request.query.get('smokingAllowed') == '1' %}checked{% endif %}
  156.                 class="form-checkbox text-purple-500">
  157.               <span>{{ 'houseRules.fume'|trans }}</span>
  158.             </label>
  159.           </div>
  160.         </div>
  161.         <div class="mt-4 flex justify-center">
  162.           <div id="dpe-buttons" class="flex gap-2 flex-wrap">
  163.             <!-- Boutons A à G -->
  164.             {% for grade in ['A', 'B', 'C', 'D', 'E', 'F', 'G'] %}
  165.               <button type="button"
  166.                 data-grade="{{ grade }}"
  167.                 class="dpe-btn px-3 py-1 rounded-full border-2 font-semibold text-gray-700 border-gray-300 hover:bg-gray-100">
  168.                 {{ grade }}
  169.               </button>
  170.             {% endfor %}
  171.             <button type="button"
  172.               data-grade="Vierge"
  173.               class="dpe-btn px-3 py-1 rounded-full border-2 font-semibold text-gray-700 border-gray-300 hover:bg-gray-100">
  174.               {{ 'search.vierge'|trans }}
  175.             </button>
  176.           </div>
  177.         </div>
  178.         <!-- Bouton de soumission -->
  179.         <div class="mt-4 flex justify-center">
  180.           <button type="submit" class="text-black bg-[#ffcc00] hover:bg-[#ffcc00] focus:ring-4 focus:outline-none focus:ring-yellow-300 font-medium rounded-full text-sm px-5 py-2.5 text-center w-full md:w-auto">
  181.             {{ 'nav.trouverlogement'|trans }}
  182.           </button>
  183.         </div>
  184.       </form>
  185. </div>
  186. <br/>
  187. <script src="https://unpkg.com/flowbite@1.4.0/dist/flowbite.js"></script>
  188. <style>
  189.     #map {
  190.         height: 400px;
  191.         width: 100%;
  192.         filter: blur(0px);
  193.         transition: filter 0.3s ease-in-out;
  194.     }
  195.     .image-container {
  196.         position: relative;
  197.     }
  198.     .pagination-button {
  199.         background-color: #ffcc00; /* Couleur jaune */
  200.         color: black; /* Couleur du texte */
  201.         padding: 8px 16px; /* Espacement intérieur */
  202.         border-radius: 4px; /* Coins arrondis */
  203.         text-decoration: none; /* Supprimer le soulignement */
  204.         border: none; /* Supprimer la bordure */
  205.     }
  206.     .pagination-button:hover {
  207.         background-color: #e6b800; /* Couleur jaune légèrement plus foncée au survol */
  208.     }
  209. </style>
  210. <div class="container mx-auto">
  211.     <h1 class="text-2xl font-bold mb-4">{{ 'search.search_results'|trans }} {{ city }}</h1>
  212.     <br><br>
  213.     <div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-4">
  214.         {% if selectedBuildings is not empty %}
  215.             {% for building in selectedBuildings %}
  216.                 {% set filteredFiles = building.buildingDocuments|filter(item => item.name starts with 'file') %}
  217.                 <div class="flex flex-col">
  218.                     <a href="{{ path('detail_building', {id : building.id}) }}" class="building-link">
  219.                         {% if filteredFiles is not empty %}
  220.                             <div id="default-carousel" class="relative z-0" data-carousel="static">
  221.                                 <div class="overflow-hidden relative h-[14rem] md:h-[10rem] lg:h-[14rem]">
  222.                                     {% for bd in filteredFiles %}
  223.                                         <a href="{{ path('detail_building', {id : building.id}) }}" class="building-link">
  224.                                             <div class="rounded-xl max-h-[300px] bg-[url({{ asset('images/files/' ~ bd.imageFile) }})] bg-cover bg-no-repeat bg-center hidden duration-700 ease-in-out {% if loop.first %}active{% endif %}" data-carousel-item>
  225.                                             </div>
  226.                                         </a>
  227.                                     {% endfor %}
  228.                                 </div>
  229.                                 <div class="flex absolute border-black bottom-5 left-1/2 z-30 space-x-3 -translate-x-1/2">
  230.                                     {% for document in building.buildingDocuments %}
  231.                                         {% if loop.index0 <= 2 %}
  232.                                             <button type="button" style="border: 1px grey solid;" class="w-3 h-3 rounded-full border border-black" aria-current="false" aria-label="Slide {{building.id}}" data-carousel-slide-to="{{building.id}}"></button>
  233.                                         {% endif %}
  234.                                     {% endfor %}
  235.                                 </div>
  236.                                 {% if building.buildingDocuments|length > 1 %}
  237.                                     <button type="button" class="flex absolute top-0 left-0 z-30 justify-center items-center px-4 h-full cursor-pointer group focus:outline-none" data-carousel-prev>
  238.                                         <span class="inline-flex justify-center items-center w-8 h-8 rounded-full sm:w-10 sm:h-10 bg-white/30 group-hover:bg-white/50 group-focus:ring-4 group-focus:ring-white group-focus:outline-none">
  239.                                             <svg class="w-5 h-5 text-white sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg>
  240.                                             <span class="hidden">Previous</span>
  241.                                         </span>
  242.                                     </button>
  243.                                     <button type="button" class="flex absolute top-0 right-0 z-30 justify-center items-center px-4 h-full cursor-pointer group focus:outline-none" data-carousel-next>
  244.                                         <span class="inline-flex justify-center items-center w-8 h-8 rounded-full sm:w-10 sm:h-10 bg-white/30 group-hover:bg-white/50 group-focus:ring-4 group-focus:ring-white group-focus:outline-none">
  245.                                             <svg class="w-5 h-5 text-white sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
  246.                                             <span class="hidden">Next</span>
  247.                                         </span>
  248.                                     </button>
  249.                                 {% endif %}
  250.                             </div>
  251.                         {% endif %}
  252.                     </a>
  253.                     <div class="row mt-4">
  254.                         <div class="grid grid-cols-2 gap-4">
  255.                             <a href="{{ path('detail_building', {id : building.id}) }}" class="cursor-pointer text-sm font-bold">{{ building.cityEntity.city }}, {{ building.cityEntity.country }}</a>
  256.                         </div>
  257.                         <div>
  258.                             <a href="{{ path('detail_building', {id : building.id}) }}" class="cursor-pointer text-sm font-bold">{{ building.rent / 100 }} €</a>
  259.                             {{ 'accueil.parmois'|trans }}<br>
  260.                             <a href="{{ path('detail_building', {id : building.id}) }}" class="cursor-pointer text-gray-500 text-sm">{{ 'accueil.add'|trans }}{{ building.createdAt|date('d/m/y') }}<br></a>
  261.                             {% if building.status == 'Disponible' %}
  262.                                 {% if building.dateStartAt %}
  263.                                     <p class="text-gray-500 text-sm">{{ 'accueil.availableDate'|trans }} {{ building.dateStartAt|date('d/m/y') }}</p>
  264.                                 {% else %}
  265.                                     <p class="text-gray-500 text-sm">{{ 'accueil.availableDateNow'|trans }}</p>
  266.                                 {% endif %}
  267.                             {% elseif building.dateStartAt %}
  268.                                 <p class="text-gray-500 text-sm">{{ 'accueil.dateStartAt'|trans }} {{ building.dateStartAt|date('d/m/y') }}</p>
  269.                             {% endif %}
  270.                         </div>
  271.                     </div>
  272.                 </div>
  273.             {% endfor %}
  274.         {% else %}
  275.         <style>
  276.             .no-wrap {
  277.             white-space: nowrap;
  278.             }
  279.         </style>
  280.         <p class="no-wrap">{{ 'Aucun bien disponible dans cette ville actuellement'|trans }}</p>
  281.         {% endif %}
  282.     </div> <br/>
  283.     <!-- Contrôles de pagination -->
  284.     <div class="flex justify-center space-x-2">
  285.     {# Affiche "Précédent" uniquement si on est au moins à la page 2 #}
  286.     {% if currentPage > 1 %}
  287.         <a href="{{ path('advanced_search', query|merge({'page': currentPage - 1})) }}" class="pagination-button">
  288.             {{ 'search.previous'|trans }}
  289.         </a>
  290.     {% endif %}
  291.     {# Déterminer les pages à afficher (max 5) #}
  292.     {% set startPage = currentPage > 3 ? currentPage - 2 : 1 %}
  293.     {% set endPage = (startPage + 4) > pagesCount ? pagesCount : startPage + 4 %}
  294.     {# Réajuster startPage si on est proche de la fin #}
  295.     {% if endPage - startPage < 4 and pagesCount >= 5 %}
  296.         {% set startPage = endPage - 4 > 0 ? endPage - 4 : 1 %}
  297.     {% endif %}
  298.     {# Boucle sur les pages à afficher #}
  299.     {% for page in startPage..endPage %}
  300.         {% if page != 0 %}
  301.         <a href="{{ path('advanced_search', query|merge({'page': page})) }}"
  302.            class="pagination-button {{ page == currentPage ? 'bg-blue-500 text-white' : '' }}">
  303.             {{ page }}
  304.         </a>
  305.         {% endif %}
  306.     {% endfor %}
  307.     {# Affiche "Suivant" uniquement si on n'est pas à la dernière page #}
  308.     {% if currentPage < pagesCount %}
  309.         <a href="{{ path('advanced_search', query|merge({'page': currentPage + 1})) }}" class="pagination-button">
  310.             {{ 'search.next'|trans }}
  311.         </a>
  312.     {% endif %}
  313. </div>
  314.     <br><br>
  315.     <div id="map" style="height: 600px;"></div>
  316.     <br><br>
  317. </div>
  318. {% set googleMapsApiKey = app.request.server.get('GOOGLEMAP_KEY') %}
  319.     <script>
  320.         const googleMapsApiKey = "{{ googleMapsApiKey }}";
  321.         var iconMap = "{{ asset('/images/icons/Bons Plans.png') }}";
  322.         var selectedBuildingsMap = {{ selectedBuildingsMap|json_encode|raw }};
  323.         async function initMap() {
  324.             const map = new google.maps.Map(document.getElementById("map"), {
  325.                 mapId: "b47cb966043d1a05",
  326.                 center: {
  327.                     lat: {{ lat }},
  328.                     lng: {{ lng }}
  329.                 },
  330.                 zoom: 12
  331.             });
  332.             const pinSvgString = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30px" height="34px" viewBox="0 0 30 40" version="1.1">
  333.                             <defs>
  334.                             <filter id="alpha" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
  335.                             <feColorMatrix type="matrix" in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
  336.                             </filter>
  337.                             <mask id="mask0">
  338.                             <g filter="url(#alpha)">
  339.                             <rect x="0" y="0" width="30" height="40" style="fill:rgb(0%,0%,0%);fill-opacity:0.996078;stroke:none;"/>
  340.                             </g>
  341.                             </mask>
  342.                             <clipPath id="clip1">
  343.                             <rect x="0" y="0" width="30" height="40"/>
  344.                             </clipPath>
  345.                             <g id="surface5" clip-path="url(#clip1)">
  346.                             <path style=" stroke:none;fill-rule:evenodd;fill:rgb(99.607843%,80.392157%,0%);fill-opacity:1;" d="M 14.472656 0.429688 C 18.484375 0.265625 21.949219 1.511719 24.871094 4.164062 C 28.933594 7.972656 30.359375 12.582031 29.152344 17.984375 C 28.730469 19.613281 28.15625 21.183594 27.425781 22.703125 C 26.023438 25.640625 24.378906 28.429688 22.492188 31.066406 C 20.523438 33.816406 18.417969 36.464844 16.179688 39.019531 C 15.96875 39.238281 15.730469 39.414062 15.457031 39.550781 C 15.1875 39.574219 14.917969 39.574219 14.648438 39.550781 C 14.339844 39.378906 14.066406 39.167969 13.820312 38.914062 C 11.074219 35.8125 8.558594 32.539062 6.273438 29.105469 C 4.929688 27.042969 3.71875 24.894531 2.644531 22.667969 C 1.714844 20.746094 1.066406 18.738281 0.703125 16.644531 C 0.132812 12.804688 1.015625 9.328125 3.347656 6.214844 C 6.113281 2.582031 9.820312 0.65625 14.472656 0.429688 Z M 14.472656 0.429688 "/>
  347.                             </g>
  348.                             </defs>
  349.                             <g id="surface1">
  350.                             <use xlink:href="#surface5" mask="url(#mask0)"/>
  351.                             <path style=" stroke:none;fill-rule:evenodd;fill:rgb(7.45098%,7.843137%,8.627451%);fill-opacity:1;" d="M 14.257812 7.695312 C 15.882812 7.558594 17.367188 7.757812 18.984375 8.296875 C 20.640625 8.976562 21.609375 10.1875 21.890625 11.925781 C 22.273438 14.070312 21.621094 15.84375 19.933594 17.246094 C 19.6875 17.445312 19.429688 17.628906 19.160156 17.796875 C 18.753906 18.105469 18.699219 18.46875 19 18.882812 C 20.109375 20.59375 21.199219 22.316406 22.28125 24.042969 C 22.476562 24.546875 22.351562 24.957031 21.910156 25.265625 C 21.496094 25.585938 21.023438 25.746094 20.5 25.75 C 20.308594 25.6875 20.148438 25.578125 20.023438 25.421875 C 18.710938 23.203125 17.417969 20.980469 16.144531 18.742188 C 16.097656 18.542969 16.132812 18.359375 16.25 18.191406 C 16.613281 17.933594 16.984375 17.6875 17.363281 17.453125 C 18.5625 16.527344 19.171875 15.316406 19.195312 13.820312 C 19.253906 12.777344 18.953125 11.847656 18.296875 11.03125 C 17.738281 10.5 17.074219 10.148438 16.304688 9.984375 C 15.792969 9.886719 15.273438 9.816406 14.753906 9.777344 C 14.714844 9.300781 14.605469 8.835938 14.417969 8.382812 C 14.335938 8.246094 14.253906 8.105469 14.171875 7.96875 C 14.136719 7.855469 14.167969 7.765625 14.257812 7.695312 Z M 14.257812 7.695312 "/>
  352.                             <path style=" stroke:none;fill-rule:evenodd;fill:rgb(7.45098%,7.843137%,8.627451%);fill-opacity:1;" d="M 11.617188 7.726562 C 12.667969 7.652344 13.367188 8.101562 13.714844 9.070312 C 13.890625 9.921875 13.628906 10.605469 12.921875 11.117188 C 11.960938 11.558594 11.179688 11.359375 10.574219 10.515625 C 10.011719 9.496094 10.195312 8.644531 11.121094 7.953125 C 11.285156 7.867188 11.449219 7.792969 11.617188 7.726562 Z M 11.617188 7.726562 "/>
  353.                             <path style=" stroke:none;fill-rule:evenodd;fill:rgb(7.45098%,7.843137%,8.627451%);fill-opacity:1;" d="M 11.582031 12.132812 C 12.0625 12.101562 12.53125 12.152344 12.992188 12.289062 C 13.125 12.359375 13.210938 12.46875 13.253906 12.617188 C 13.265625 13.429688 13.277344 14.246094 13.289062 15.058594 C 13.320312 15.238281 13.417969 15.359375 13.589844 15.421875 C 14.53125 15.421875 15.472656 15.445312 16.410156 15.492188 C 16.589844 15.550781 16.65625 15.671875 16.605469 15.851562 C 16.511719 16.046875 16.375 16.214844 16.199219 16.351562 C 15.34375 16.9375 14.390625 17.246094 13.34375 17.28125 C 12.695312 17.304688 12.050781 17.304688 11.402344 17.28125 C 11.003906 17.261719 10.761719 17.058594 10.679688 16.679688 C 10.65625 15.324219 10.65625 13.96875 10.730469 12.617188 C 10.730469 12.5 10.808594 12.402344 10.910156 12.324219 C 11.128906 12.234375 11.351562 12.167969 11.582031 12.132812 Z M 11.582031 12.132812 "/>
  354.                             <path style=" stroke:none;fill-rule:evenodd;fill:rgb(7.45098%,7.843137%,8.627451%);fill-opacity:1;" d="M 8.441406 13.167969 C 8.796875 13.160156 9.148438 13.167969 9.5 13.183594 C 9.621094 13.222656 9.710938 13.296875 9.765625 13.40625 C 9.789062 14.589844 9.789062 15.773438 9.765625 16.953125 C 9.71875 17.101562 9.621094 17.1875 9.464844 17.210938 C 9.085938 17.242188 8.710938 17.230469 8.335938 17.175781 C 8.027344 17.046875 7.835938 16.824219 7.753906 16.507812 C 7.730469 15.609375 7.730469 14.714844 7.753906 13.820312 C 7.886719 13.5 8.117188 13.285156 8.441406 13.167969 Z M 8.441406 13.167969 "/>
  355.                             <path style=" stroke:none;fill-rule:evenodd;fill:rgb(7.45098%,7.843137%,8.627451%);fill-opacity:1;" d="M 11.441406 18.191406 C 11.816406 18.1875 12.191406 18.191406 12.566406 18.210938 C 12.894531 18.234375 13.125 18.390625 13.253906 18.675781 C 13.277344 20.5 13.277344 22.324219 13.253906 24.148438 C 13.21875 24.523438 13.046875 24.828125 12.742188 25.058594 C 12.265625 25.433594 11.726562 25.667969 11.121094 25.765625 C 10.886719 25.761719 10.742188 25.644531 10.679688 25.421875 C 10.65625 23.195312 10.65625 20.96875 10.679688 18.742188 C 10.71875 18.601562 10.792969 18.480469 10.910156 18.382812 C 11.082031 18.296875 11.257812 18.234375 11.441406 18.191406 Z M 11.441406 18.191406 "/>
  356.                             </g>
  357.                             </svg>`
  358.             const encodedPins = 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(pinSvgString);
  359.             const icon = {
  360.                 url: encodedPins,
  361.                 scaledSize: new google.maps.Size(30, 40),
  362.             };
  363.             //markers pour chaque bâtiment
  364.             for (let i = 0; i < selectedBuildingsMap.length; i++) {
  365.                 let building  = selectedBuildingsMap[i];
  366.                 let lat = parseFloat(selectedBuildingsMap[i].latitude);
  367.                 let lng = parseFloat(selectedBuildingsMap[i].longitude);
  368.                 map.setCenter({ lat: parseFloat(selectedBuildingsMap[0].latitude), lng: parseFloat(selectedBuildingsMap[0].longitude) });
  369.                 if (lat && lng) {
  370.                     let marker = new google.maps.Marker({
  371.                         position: new google.maps.LatLng(lat, lng),
  372.                         map,
  373.                         icon,
  374.                     });
  375.                     const urlTemplate = '{{ path('detail_building', { id: 'idBuilding' }) }}';
  376.                     let urlDetailBuilding = urlTemplate.replace('idBuilding', selectedBuildingsMap[i].id);
  377.                     marker.addListener("click", ()=> { window.location.href = urlDetailBuilding});
  378.                 }
  379.             }
  380.             initAutocomplete();
  381.     }
  382.     window.initMap = initMap;
  383.     </script>
  384.     {% block scripts %}
  385.     <script async src="{{ 'https://maps.googleapis.com/maps/api/js' ~ '?key=' ~ googleMapsApiKey ~ '&callback=initMap&v=beta&libraries=places,geometry,marker' }}"></script>
  386.     <script>
  387.     var buildings = {{ buildingsMap|json_encode|raw }};
  388.     document.addEventListener('DOMContentLoaded', function () {
  389.         initMap();
  390.         const toggleFiltersButton = document.getElementById('toggle-filters');
  391.         const filterOptions = document.getElementById('filter-options');
  392.         // Toggle visibility des filtres
  393.         toggleFiltersButton.addEventListener('click', function (event) {
  394.             event.preventDefault();
  395.             filterOptions.classList.toggle('hidden');
  396.         });
  397.         // Validation du formulaire avant l'envoi
  398.         const form = document.querySelector('form');
  399.         const addressInput = document.getElementById('address');
  400.         const latInput = document.getElementById('lat');
  401.         const lngInput = document.getElementById('lng');
  402.         const errorMessage = document.createElement('div');
  403.         errorMessage.style.color = 'red';
  404.         errorMessage.style.marginTop = '10px';
  405.         errorMessage.style.display = 'none';
  406.         errorMessage.textContent = "{{ 'Indiquez au moins la ville de votre recherche.'|trans }}";
  407.         addressInput.parentElement.appendChild(errorMessage);
  408.         form.addEventListener('submit', function(event) {
  409.             const city = addressInput.value.trim();
  410.             const lat = latInput.value.trim();
  411.             const lng = lngInput.value.trim();
  412.             console.log("City:", city, "Lat:", lat, "Lng:", lng); // Ajout de logs pour le débogage
  413.             if (!city || !lat || !lng) {
  414.                 event.preventDefault();  // Empêcher l'envoi du formulaire
  415.                 errorMessage.style.display = 'block';  // Afficher le message d'erreur
  416.             } else {
  417.                 errorMessage.style.display = 'none';  // Masquer le message d'erreur si le champ est rempli
  418.             }
  419.         });
  420.         // Gestion des cases à cocher pour la salle de bain
  421.         const privateBathroomCheckbox = document.getElementById('bathroom-private');
  422.         const sharedBathroomCheckbox = document.getElementById('bathroom-shared');
  423.         privateBathroomCheckbox.addEventListener('change', function () {
  424.             if (this.checked) {
  425.                 sharedBathroomCheckbox.checked = false;
  426.             }
  427.         });
  428.         sharedBathroomCheckbox.addEventListener('change', function () {
  429.             if (this.checked) {
  430.                 privateBathroomCheckbox.checked = false;
  431.             }
  432.         });
  433.     });
  434.     var autocomplete;
  435.     function initAutocomplete() {
  436.         var input = document.getElementById('address');
  437.         var options = {
  438.             types: ['(cities)'],  // Limiter aux villes
  439.             componentRestrictions: { country: 'fr' }  // Limiter aux villes en France
  440.         };
  441.         // Initialiser l'autocomplétion
  442.         autocomplete = new google.maps.places.Autocomplete(input, options);
  443.         // Ajouter un écouteur d'événements pour récupérer les données de l'adresse
  444.         autocomplete.addListener('place_changed', function () {
  445.             var place = autocomplete.getPlace();
  446.             var city = "";
  447.             // Récupérer les coordonnées latitude et longitude
  448.             if (place.geometry) {
  449.                 document.getElementById('lat').value = place.geometry.location.lat();
  450.                 document.getElementById('lng').value = place.geometry.location.lng();
  451.                 initMap()
  452.             }
  453.             // Extraire uniquement le nom de la ville
  454.             place.address_components.forEach(component => {
  455.                 if (component.types.includes("locality")) {
  456.                     city = component.long_name;
  457.                 }
  458.             });
  459.             // Mettre à jour l'input avec le nom de la ville
  460.             document.getElementById('address').value = city;
  461.             const form = input.closest('form');
  462.             if (form) {
  463.                 form.submit();
  464.             }
  465.         });
  466.     }
  467.     window.initMap = initMap;
  468.     </script>
  469.     {% endblock %}
  470. {% endblock %}