1import {get} from "../api/get.16.1.js"; 2import {post} from "../api/post.16.1.js"; 3import {getCars} from "../api/getCars.16.1.js"; 4import {updateTextForDropDowns} from "../leasing-list/leasing-list.16.1.js"; 5import {updateQueryStringOnFilter, getLangCode} from "../filters/filters.16.1.js"; 6import {getBrandTileData} from "../utils/templates.16.1.js"; 7import {makeActive, removeActive} from "../utils/utility.16.1.js"; 8 9let brandList = []; 10let brandDetail = []; 11let brandModels = []; 12let markers = ""; 13let markersDefault = ""; 14let privateCars = []; 15 16//let carCont = $(".manufacturer-details"); 17 18//const manufacturerSection = $("#manufacture-list-container"); 19//const mobileManufacturerSection = $("#mobile-manufacture-list-container"); 20//const configuratorListContainer = $("#configurator-list-container"); 21 22(async function () { 23 brandList = await get("manufactures"); 24 sessionStorage.setItem("manufacturerBrand", JSON.stringify(brandList)); 25})(); 26 27// Refactored RK 28export const configuratorBrands = async () => { 29 //Clear any preselected value onLoad of this page. OR we can improve it to read it from preselected vaue 30 // sessionStorage.removeItem("selectedCarBrand"); 31 // sessionStorage.removeItem("selectedVehicleType"); 32 //const brandListDefault = await get("manufactures"); 33 34 // const brandListDefault = JSON.parse(sessionStorage.getItem("manufacturerBrand")); 35 // const selectedCarBrandLS = sessionStorage.getItem("selectedCarBrand"); 36 // const carToSelect = brandListDefault.find((item) => item.brandName === JSON.parse(selectedCarBrandLS)?.carName); 37 38 try { 39 // Attempt to retrieve the brand list from sessionStorage 40 let brandListDefault = JSON.parse(sessionStorage.getItem("manufacturerBrand")); 41 42 // If not found in sessionStorage, fetch it from the server or source 43 if (!brandListDefault) { 44 brandListDefault = await get("manufactures"); // Assuming get() fetches the data 45 sessionStorage.setItem("manufacturerBrand", JSON.stringify(brandListDefault)); 46 } 47 48 // Proceed only if brandListDefault is a valid array 49 if (!Array.isArray(brandListDefault) || brandListDefault.length === 0) { 50 console.error("Brand list is empty or not available."); 51 return; 52 } 53 54 const selectedCarBrandLS = sessionStorage.getItem("selectedCarBrand"); 55 const carToSelect = brandListDefault.find((item) => item.brandName === JSON.parse(selectedCarBrandLS)?.carName); 56 57 const $selectedFilterSectionImg = $(".selected-filter-section img"); 58 // console.log("Brand logo selection:" + selectedCarBrandLS); 59 let brandSelectedLS = selectedCarBrandLS ? JSON.parse(selectedCarBrandLS) : null; 60 if (carToSelect && brandSelectedLS && Object.keys(brandSelectedLS).length) { 61 $selectedFilterSectionImg.attr({ 62 src: carToSelect?.src, 63 alt: carToSelect?.brandName, 64 "data-tid": carToSelect?.id, 65 "data-order": carToSelect?.order, 66 }); 67 } else { 68 $selectedFilterSectionImg.attr({ 69 src: brandListDefault[0]["src"], 70 alt: brandListDefault[0]["brandName"], 71 "data-tid": brandListDefault[0]["id"], 72 "data-order": brandListDefault[0]["order"], 73 }); 74 } 75 }catch (error) { 76 console.error("An error occurred while configuring brands:", error); 77 } 78}; 79 80// car filteration based on vehicle Type RK 81export const getCarsByType = (carTypes) => { 82 return brandList.filter((el) => { 83 return carTypes.some((f) => { 84 return f?.name?.toLowerCase() === el?.brandName?.toLowerCase(); 85 }); 86 }); 87}; 88 89// replace the whole configuratorSlider function with this 90export const configuratorSlider = async () => { 91 const $configuratorTitle = $("#configurator-slider-container .configurator-title"); 92 const $container = $("#configurator-slider-container"); 93 94 // vehicle type (private/commercial) 95 const optionType = 96 sessionStorage.getItem("selectedVehicleType") || 97 $('input[name="inlineRadioOptions"]:checked').val() || 98 "private"; 99 100 const selectedCarBrandLS = JSON.parse(sessionStorage.getItem("selectedCarBrand")); 101 102 // 1) Make sure we REALLY have manufacturerBrand (avoid race with top IIFE) 103 let brandListDefault = JSON.parse(sessionStorage.getItem("manufacturerBrand")); 104 105 if (!Array.isArray(brandListDefault) || !brandListDefault.length) { 106 brandListDefault = await get("manufactures"); 107 sessionStorage.setItem("manufacturerBrand", JSON.stringify(brandListDefault)); 108 } 109 110 if (!Array.isArray(brandListDefault) || !brandListDefault.length) { 111 console.warn("No manufacturers available"); 112 return; 113 } 114 115 // 2) Decide from which brand to start (selectedCarBrand if exists, else first) 116 let startIndex = 0; 117 118 if (selectedCarBrandLS?.carName) { 119 const idx = brandListDefault.findIndex( 120 (b) => 121 String(b.brandName).toLowerCase() === 122 String(selectedCarBrandLS.carName).toLowerCase() 123 ); 124 if (idx !== -1) { 125 startIndex = idx; 126 } 127 } 128 129 // helper to call /models for a brand 130 const fetchModelsForBrand = async (brand) => { 131 const payload = { 132 manufacturers: [{ id: String(brand.id), name: brand.brandName }], 133 type: optionType, 134 }; 135 return post("models", payload); 136 }; 137 138 // 3) Try brands in order until we find one with models (skip ABARTH if [] is returned) 139 let chosenBrand = null; 140 let models = []; 141 142 for (let i = 0; i < brandListDefault.length; i++) {
143 const brand = brandListDefault[(startIndex + i) % brandListDefault.length]; 144 const resp = await fetchModelsForBrand(brand); 145 const arr = resp?.[0] || []; 146 147 if (arr.length) { 148 chosenBrand = brand; 149 models = arr; 150 break; 151 } 152 } 153 154 if (!chosenBrand) { 155 console.warn("No models found for any brand for type:", optionType); 156 return; 157 } 158 159 // 4) Sync sessionStorage + selected logo with the brand that actually has models 160 sessionStorage.setItem( 161 "selectedCarBrand", 162 JSON.stringify({ carId: String(chosenBrand.id), carName: chosenBrand.brandName }) 163 ); 164 165 const $selectedFilterSectionImg = $(".selected-filter-section img"); 166 $selectedFilterSectionImg.attr({ 167 src: chosenBrand.src, 168 alt: chosenBrand.brandName, 169 "data-tid": chosenBrand.id, 170 "data-order": chosenBrand.order, 171 }); 172 173 // 5) Build slider with the models of the first "valid" brand 174 $container.find(".swiper-wrapper").remove(); 175 176 const sliderWrapper = document.createElement("div"); 177 $(sliderWrapper).addClass("swiper-wrapper"); 178 179 models.forEach((response) => { 180 const cardTemplate = getSliderContent( 181 response["manufacturer_name"], 182 response["modelKey"], 183 response["name"] 184 ); 185 $(sliderWrapper).append(cardTemplate); 186 187 $configuratorTitle 188 .html(response["name"]) 189 .attr({ 190 "data-make": response["manufacturer_name"], 191 "data-modelfamily": response["modelKey"], 192 }); 193 }); 194 195 $container.append(sliderWrapper); 196 initializeConfiguratorSlider(); 197}; 198 199 200 201 202// const getCardMobileManufacturer = (data, leasingData) => { 203// let html = ""; 204// let carSrc = data["carImage"].replace(/&/g, "&"); 205// html += `<div class="swiper-slide col-12 h-100 "> 206// <div class="card px-3 py-4"> 207// <div class="card-body px-0 pt-0 pb-3 d-flex flex-column align-items-center justify-content-center topDealsClick" 208// data-node-id="${data["Id"]}" data-url="${data["url"]}" id="clickCardMobileManufacture-${data["Id"]}"> 209// <div> 210// <h6>${data["brandName"]}</h6> 211// <div class="text-body-regular text-avis-faded-grey">${data["subtitle"]}</div> 212// </div> 213// <img src="${carSrc}" class="image-fluid" alt="${data["brandName"]}" loading="lazy"> 214// <div> 215// <div class="d-flex"> 216// <h5 style="line-height: 17px;">${data["offerPrice"]}â¬</h5> 217// <h6>/`+Drupal.t("month")+`</h6> 218// </div> 219// <div class="text-disclaimer text-avis-faded-grey">`+Drupal.t('VAT')+` 24% ${data["offerPriceWithTax"]}â¬</div> 220// </div> 221// </div>`; 222// const items = leasingData; 223// html += `<div class="card-footer pt-3 car-info-action"> 224// <div class="d-flex d-lg-none align-items-center flex-wrap gap-2">`; 225// if (Array.isArray(items)) { 226// items.forEach((item) => { 227// if (item[0]) { 228// html += `<button type="button" data-type="${ 229// item[0].name ? item[0].name : "" 230// }" 231// data-desc="${item[0].description__value}" 232// data-icon="${ 233// item[0].field_leasing_icon ? item[0].field_leasing_icon : "" 234// }" 235// class="info-btn easy-leasing-modal border-0 rounded-pill p-2 text-bg-avis-powder-grey d-flex align-items-center justify-content-center"> 236// <img src="${ 237// item[0].field_leasing_icon 238// ? item[0].field_leasing_icon 239// : "#" 240// }" class="d-inline" alt="${ 241// item[0].name ? item[0].name : "img" 242// }" /> 243// </button>`; 244// } 245// }); 246// } 247// html += ` <button type="button" data-bs-toggle="modal" data-bs-target="#leasingInfoModal" data-type="info-circle-modal" 248// class="info-btn info-circle-modal bg-transparent rounded-pill p-2 d-flex align-items-center justify-content-center"> 249// <img src='/themes/custom/avis2024/images/svg/infocircle.svg' class="d-inline" alt="info-icon" /> 250// </button></div></div></div></div>`; 251// return html; 252// }; 253 254// const getCardManufacturer = (data, leasingData) => { 255// let src = data["carImage"].replace(/&/g, "&"); 256// let html = ""; 257// html += `<div class="product-list-view col-12 col-sm-12 col-md-12 col-lg-4"> 258// <div class="card h-100 manufacturer-list-card border-0"> 259// <div class="card-body p-0 topDealsClick" data-node-id="${data["Id"]}" data-url="${data["url"]}" id="clickCardManufacturer-${data["Id"]}"> 260// <img src='${src}' alt='${data["brandName"]}' class="img-responsive"> 261// <div class="d-flex justify-content-between py-3"> 262// <div class="d-flex flex-column car-title-col col-md-8"> 263// <h5>${data["brandName"]}</h5> 264// <div>${data["subtitle"]}</div> 265// </div> 266// <div class="d-flex flex-column col-md-4">
267// <span><b>${data["offerPrice"]}â¬</b> /`+Drupal.t("month")+`</span> 268// <span>VAT 24% ${data["offerPriceWithTax"]}â¬</span> 269// </div> 270// </div> 271// </div>`; 272// const items = leasingData; 273// html += `<div class="card-footer p-0 bg-transparent d-flex flex-column gap-3"> 274// <div class="d-flex align-items-center justify-content-center flex-wrap py-3 gap-2">`; 275// if (Array.isArray(items) && items.length > 0) { 276// items.forEach((item) => { 277// if (item[0]) { 278// html += `<a role='button' tabindex="0" class="footer-btn-popover" data-bs-trigger="click" 279// data-bs-toggle="popover" 280// data-type="${item[0].name ? item[0].name : ""}" 281// data-desc="${ 282// item[0].description__value ? item[0].description__value : "" 283// }" 284// data-icon="${ 285// item[0].field_leasing_icon ? item[0].field_leasing_icon : "" 286// }"> 287// <span class="badge"> 288// <img src="${ 289// item[0].field_leasing_icon 290// ? item[0].field_leasing_icon 291// : "#" 292// }" class="d-inline pe-2" alt="" /> 293// ${item[0].name ? item[0].name : ""} 294// </span> 295// </a>`; 296// } 297// }); 298// } 299// html += `</div></div></div></div>`; 300// return html; 301// }; 302 303export const handleSelectedCarBrand = async () => { 304 const selectBrandImg = $(".brand-item.selected .brand-image");
305 const brand = selectBrandImg.attr("alt"); 306 const $selectedFilterSectionImg = $(".selected-filter-section img"); 307 const $vehicleOptionSelected = $('input[name="inlineRadioOptions"]:checked').val(); 308 309 // Setting the value of current vehicle option if not selected 310 if (sessionStorage.getItem("selectedVehicleType") === null) { 311 sessionStorage.setItem("selectedVehicleType", $vehicleOptionSelected); 312 } 313 314 $selectedFilterSectionImg.attr({ 315 src: selectBrandImg.attr("src"), 316 alt: selectBrandImg.attr("alt"), 317 "data-tid": selectBrandImg.attr("data-tid"), 318 "data-order": selectBrandImg.attr("data-order"), 319 }); 320 321 //brand-container 322 const manufactureId = $selectedFilterSectionImg.attr("data-order"); 323 const manufactureName = $selectedFilterSectionImg.attr("alt"); 324 if (manufactureId && manufactureName) { 325 sessionStorage.setItem("selectedCarBrand", JSON.stringify({carId: manufactureId, carName: manufactureName})); 326 } 327 markers = { 328 manufacturers: [{id: manufactureId, name: manufactureName}], 329 type: $vehicleOptionSelected, 330 }; 331 332 markersDefault = { 333 manufacturers: [{id: 1, name: "ABARTH"}], 334 type: $vehicleOptionSelected, 335 }; 336 if (window.location.pathname.indexOf("top-deals") < 0) { 337 if (brand != null) { 338 brandModels = await post("models", markers); 339 } else { 340 brandModels = await post("models", markersDefault); 341 } 342 const sliderWrapperContainer = $("#configurator-slider-container .swiper-wrapper"); 343 if (sliderWrapperContainer.length) { 344 sliderWrapperContainer.empty(); 345 $("#configurator-slider-container .configurator-title").empty(); 346 brandModels[0].forEach((response) => { 347 $("#configurator-slider-container .configurator-title").html(response["name"]); 348 $("#configurator-slider-container .configurator-title").attr("data-modelfamily", response["modelKey"]); 349 $("#configurator-slider-container .configurator-title").attr("data-make", response["manufacturer_name"]); 350 351 const cardTemplate = getSliderContent(response["manufacturer_name"], response["modelKey"], response["name"]); 352 $(sliderWrapperContainer).append(cardTemplate); 353 }); 354 } 355 } 356 $("#brandModalConfigurator").modal("hide"); 357 if (typeof configuratorNavSlider !== 'undefined' && configuratorNavSlider.update) { 358 configuratorNavSlider.update(); 359 } 360}; 361 362let configuratorNavSlider; 363 364// Slider configuration 365const initializeConfiguratorSlider = () => { 366 configuratorNavSlider = new Swiper("#configurator-slider-container", { 367 loop: true, 368 centeredSlides: true, 369 slidesPerView: 2.3, 370 speed: 750, 371 breakpoints: { 372 0: { slidesPerView: 1 }, 373 992: { slidesPerView: 2.2 }, 374 1400:{ slidesPerView: 2.3 }, 375 }, 376 navigation: { 377 nextEl: ".swiper-button-prev", 378 prevEl: ".swiper-button-next", 379 }, 380 on: { 381 afterInit: function (swiper) { 382 const $currentSlideTitle = $("#configurator-slider-container .configurator-title"); 383 const slides = swiper.slides; 384 385 if (!slides || !slides.length) { 386 $currentSlideTitle.empty(); 387 return; 388 } 389 390 const slide = slides[swiper.activeIndex]; 391 if (!slide || !slide.dataset) { 392 $currentSlideTitle.empty(); 393 return; 394 } 395 396 $currentSlideTitle 397 .empty() 398 .text(slide.dataset.modelname) 399 .attr({ 400 "data-make": slide.dataset.make, 401 "data-modelfamily": slide.dataset.modelfamily, 402 }); 403 }, 404 405 slideChange: function (swiper) { 406 $("#configureNow").attr("disabled", true); 407 const $currentSlideTitle = $("#configurator-slider-container .configurator-title"); 408 $currentSlideTitle.empty(); 409 410 const slides = swiper.slides; 411 if (!slides || !slides.length) { 412 return; 413 } 414 415 const slide = slides[swiper.activeIndex]; 416 if (!slide || !slide.dataset) { 417 return; 418 } 419 420 $currentSlideTitle 421 .text(slide.dataset.modelname) 422 .attr({ 423 "data-make": slide.dataset.make, 424 "data-modelfamily": slide.dataset.modelfamily, 425 }); 426 427 $("#configureNow").attr("disabled", false); 428 }, 429 }, 430 }); 431}; 432 433 434const getSliderContent = (manufacturer, modelKey, modelName) => { 435 //let url = `https://cdn.imagin.studio/getImage?customer=avis-gr&make=${manufacturer}&modelFamily=${modelKey}&modelYear=2024&width=357&aspectRatio=16:10&angle=05&zoomtype=fullscreen&groundPlaneAdjustment=-0.10`; 436 let url = `https://cdn.imagin.studio/getImage?customer=avis-gr&make=${manufacturer}&modelFamily=${modelKey}&width=357&aspectRatio=16:10&angle=05&zoomtype=fullscreen&groundPlaneAdjustment=-0.10`; 437 let result = url.replace(/&/g, "&"); 438 return `<div class="swiper-slide" data-make="${manufacturer}" data-modelfamily="${modelKey}" id="${modelName}" data-modelname="${modelName}"> 439 <div class="d-flex flex-column align-items-center justify-content-center slider-content"> 440 <img src="${result}" class="img-fluid" alt="${modelName}" /> 441 <h4 class="title">${modelName}</h4> 442 </div> 443 </div>`; 444}; 445 446$("#configureNow").click(async (e) => { 447 e.preventDefault(); 448 const lang = getLangCode() || ""; 449 const make = $("#configurator-slider-container .configurator-title").attr("data-make"); 450 const modelfamily = $("#configurator-slider-container .configurator-title").attr("data-modelfamily"); 451 const orderId = $(".selected-filter-section img").attr("data-order"); 452 const makeTitle = $("#configurator-slider-container .configurator-title").text(); 453 let optionType = sessionStorage.getItem("selectedVehicleType") || $('input[name="inlineRadioOptions"]:checked').val(); 454 var configMakers = { 455 manufacturers: [{id: orderId, name: make}], 456 models: [{manufacturer_name: make, modelKey: modelfamily, name: makeTitle}], 457 bluetooth: false, 458 fuelType: [], 459 parkingSensors: false, 460 transmission: false, 461 sunroof: false, 462 priceMin: 80, 463 priceMax: 4500, 464 vehicleType: optionType, 465 }; 466 window.location.href = lang + "/configurator-list?searchargs=" + JSON.stringify(configMakers); 467}); 468 469// Triggering brand selection modal 470$("#brand-filter-button").click(async () => { 471 let currentSelectTab = "private"; 472 const vehicalType = sessionStorage.getItem("selectedVehicleType"); 473 if (vehicalType === "private" || vehicalType === "commercial") { 474 currentSelectTab = vehicalType; 475 } 476 $("input[name='inlineRadioOptions']") 477 .filter('[value="' + currentSelectTab + '"]') 478 .attr("checked", true); 479 const carData = await getCars("manufacturers/" + currentSelectTab, ""); 480 const filteredBrands = getCarsByType(carData?.[0]); 481 renderAvailableCars(filteredBrands); 482 $("#" + currentSelectTab).prop("checked", true); 483 const selectedCarBrandLS = JSON.parse(sessionStorage.getItem("selectedCarBrand")); // Parse JSON 484 let brandSelected = false;
485 // Try selecting based on sessionStorage 486 if (selectedCarBrandLS && selectedCarBrandLS.carName) { 487 // Normalize the stored brand name to lowercase 488 const storedBrandName = selectedCarBrandLS.carName.toLowerCase(); 489 const $targetBrand = $('.brand-container .brand-item[data-brandname="' + storedBrandName + '"]'); 490 if ($targetBrand.length) { 491 $targetBrand.addClass("selected"); 492 brandSelected = true; 493 } 494 } 495 // If no brand selected from storage or storage brand not found, select the first one 496 if (!brandSelected) { 497 $(".brand-container > div:first-of-type").find(".brand-item").addClass("selected"); 498 } 499 // Ensure save button is always enabled 500 $("#filter-brand-save-button").removeAttr("disabled"); 501}); 502 503const renderAvailableCars = (filteredBrands) => { 504 $("#brandModalConfigurator").modal("show"); 505 const modalBody = $("#brandModalConfigurator .modal-body"); 506 const cardListRow = document.createElement("div"); 507 $(cardListRow).addClass("brand-container row g-3 scrollbar-style-large"); 508 filteredBrands?.forEach((data) => { 509 const brandCard = getBrandTileData(data); 510 $(cardListRow).append(brandCard); 511 }); 512 modalBody.html(cardListRow); 513 // $(".brand-container .brand-item").removeClass('selected'); 514 // $('.brand-container > div:first-of-type').find(".brand-item").removeClass('selected'); 515 const currentSelectedBrand = JSON.parse(sessionStorage.getItem("selectedCarBrand")); 516 currentSelectedBrand && $('.brand-container .brand-item[data-brandname="' + currentSelectedBrand.carName + '"]').addClass("selected"); 517}; 518 519export const updateBrandSelection = (event) => { 520 if (!$(event.currentTarget).parents().hasClass("filter-brand-container")) { 521 removeActive(); 522 makeActive(event.currentTarget); 523 } else { 524 if ($(event.currentTarget).hasClass("selected")) { 525 $(event.currentTarget).removeClass("selected"); 526 } else { 527 // Ensure only one is selected 528 $('.brand-container .brand-item').removeClass('selected'); 529 makeActive(event.currentTarget); 530 } 531 // If after deselecting, nothing is selected, re-select the first one 532 if ($('.brand-container .brand-item.selected').length === 0 && $('.brand-container .brand-item').length > 0) { 533 $(".brand-container > div:first-of-type").find(".brand-item").addClass("selected"); 534 } 535 // Ensure save button is always enabled 536 $("#filter-brand-save-button").removeAttr("disabled"); 537 538 } 539}; 540 541$("input[name='inlineRadioOptions']").change(async function () { 542 var currentCarType = $(this).val(); 543 let typeCars = []; 544 typeCars = await getCars("manufacturers/" + currentCarType, ""); 545 const filteredCarsBrands = getCarsByType(typeCars?.[0]); 546 renderAvailableCars(filteredCarsBrands); // renderAvailableCars now handles selecting the first if needed 547 sessionStorage.setItem("selectedVehicleType", currentCarType); 548 // Double-check selection after render (might be redundant but safe) 549 if ($('.brand-container .brand-item.selected').length === 0 && $('.brand-container .brand-item').length > 0) { 550 $(".brand-container > div:first-of-type").find(".brand-item").addClass("selected"); 551 } 552 $("#filter-brand-save-button").removeAttr("disabled"); // Ensure button enabled after type change 553});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.