1const promises_form_fac = []; 2let isModalOpen = false; 3document.addEventListener("DOMContentLoaded", async function () { 4 // Sync (non bloquants) 5 if (document.querySelectorAll(".JS_table_panier_parts form").length) add_basket(); 6 if (document.querySelector("#table_panier_shop form")) add_basket(); 7 if (document.getElementById("panier_select_vehicule")) basket_switch_vehicule(); 8 if (document.querySelector("#modif_adresse")) modif_adresse(); 9 if (document.querySelector("#modif_adresse_facturation")) modif_adresse_facturation(); 10 if (document.querySelector("#modif_info")) modif_info(); 11 if (document.querySelector("#modif_comm")) modif_comm(); 12 if (document.querySelector("#check_differente_adresse")) check_differente_adresse(); 13 if (document.querySelector(".modal_supp")) action_delete_line_basket(); 14 if (document.querySelector(".qty-input")) action_update_line_basket(); 15 if (document.querySelector("#form_basket_save")) save_basket(); 16 if (document.querySelector("#form_card_payment")) await set_transaction_on_progress(); 17 // if (document.querySelector("#form_card_payment")) check_transaction_on_progress(); 18 if (document.querySelectorAll(".form_transform_devis").length > 0) { 19 transform_devis(); 20 delete_devis(); 21 } 22 if (document.querySelectorAll(".btn-payment ").length > 0) { 23 collapse_elements_payment(); 24 // select_elements_payment(); // à toi de voir si tu le réactives 25 } 26 if (document.querySelector("#checkbox_condition_vente")) { 27 document.getElementById("checkbox_condition_vente").addEventListener("change", function () { 28 if (this.checked && document.getElementById("cgv_error")) removeError("cgv_error"); 29 }); 30 } 31 32 // Promo : Prétraitement spécial 33 if (document.querySelector("#form_promo")) { 34 const elements = document.querySelectorAll(".JS_cart_ref_part"); 35 elements.forEach(el => { 36 if (el.textContent.trim() === "FRPG") set_free_delivery("FRPG"); 37 }); 38 39 const promoSupp = document.querySelector("#form_panier_supp_code_promo"); 40 if (promoSupp) { 41 const promoForm = document.querySelector("#form_promo"); 42 const code = promoSupp.querySelector("[name=code_promo]").value; 43 promoForm.querySelector("#code_promo").value = code; 44 document.querySelector("#JS_collapse_code_promo").innerHTML = 45 promoForm.querySelector(`[value*="${code}"]`).innerHTML; 46 } 47 } 48 49 // Async en parallèle (indépendants) 50 await Promise.all([ 51 (async () => { if (document.querySelector("#form_panier_commentaire")) await form_panier_commentaire(); })(), 52 (async () => { if (document.querySelector("#form_panier_information")) await form_panier_information(); })(), 53 (async () => { if (document.querySelector("#form_adr_liv")) { 54 await form_adr_liv(); 55 await cache_current_delivery_address(); 56 }})(), 57 (async () => { if (document.querySelector("#form_basket_add_code_promo")) await form_promo(); })(), 58 (async () => { if (document.querySelector("#form_basket_delete_code_promo")) await form_delete_promo(); })(), 59 (async () => { if (document.querySelector("#form_adr_fact")) await form_adr_fac(); })(), 60 (async () => { if (document.querySelector("#form_basket_login")) await form_login(); })(), 61 62 (async () => { if (document.querySelectorAll('.choix_pts_relais').length) await choix_pts_relais(); })(), 63 (async () => { if (document.querySelector("#view_step_basket") || document.querySelector("#empty_basket")) await getBasketInformations(); })(), 64 65 ]); 66 67 // await check_basket_errors(); 68 69 70 if (document.querySelector("#form_panier_commentaire")) { 71 submit_panier_commentaire(); 72 } 73 74 if (document.querySelector("#pays_facturation")) { 75 await check_country_is_valid(document.querySelector("#pays_facturation").value); 76 document.querySelector("#pays_facturation").addEventListener("change", async function () { 77 show_ajax_loader(); 78 try { 79 const promises = []; 80 const pays = jQuery('#pays_facturation').val(); // valeur du pays après changement 81 82 // Recheck des champs specifiques. 83 let pro = false 84 if (document.querySelector("#entreprise_facturation").value.trim() !== "") { 85 pro = true; 86 } 87 await get_basket_facturation_option(pays,pro) 88 89 // si TVA est requise 90 const list_pays_TVA = getInputRequired("TVA"); 91 const num_intracom_facturation = document.querySelector("#num_intracom_facturation"); 92 if (list_pays_TVA && list_pays_TVA.includes(pays)) { 93 num_intracom_facturation.setAttribute('required', 'required'); 94 } else { 95 num_intracom_facturation.removeAttribute('required'); 96 } 97 98 if (num_intracom_facturation && num_intracom_facturation.value !== "") { 99 await check_tva_intracom(this.form, "facturation"); 100 } 101 102 // promises.push(get_vat_changed_info()); 103 // promises.push(check_country_is_valid(this.value)); 104 promises.push(set_prefix_by_coutry(pays, "facturation")); 105 106 await Promise.all(promises); 107 pays_auto_province(this.form); 108 } catch (error) { 109 logDebug('Erreur lors du changement de pays :', error); 110 } finally { 111 hide_ajax_loader(); 112 } 113 }); 114 } 115 116 117 if (document.querySelector("#form_panier_mobile_coliship")) { 118 await form_panier_mobile_coliship(); 119 } 120 121 if (document.querySelector("#form_panier_payment")) { 122 await form_panier_payment(document.querySelector("#form_panier_payment")); 123 } 124 125 if (document.querySelector("#entreprise_facturation")) { 126 let timeout; 127 document.querySelector("#entreprise_facturation").addEventListener("input", function() { 128 clearTimeout(timeout); 129 130 timeout = setTimeout(async () => { 131 let pro = false 132 if (this.value.trim() !== "") { 133 pro = true; 134 } 135 await get_basket_facturation_option(false, pro); 136 }, 250); 137 }); 138 } 139 140 // FORMULAIRES ADRESSES // 141 if (document.querySelector("#collapse_basket_facturation") && document.querySelector("#collapse_basket_livraison")) { 142 gestion_collapse_adresse("facturation"); 143 gestion_collapse_adresse("livraison"); 144 } 145}); 146 147 148 149function gestion_collapse_adresse(type) { 150 let adresseElement = document.getElementById(`basket_${type}_adresse`); 151 let collapseElement = document.getElementById(`basket_form_${type}`); 152 if (!collapseElement) { 153 return; 154 } 155 let bsCollapseElement = new bootstrap.Collapse(collapseElement, {toggle: false}); 156 let otherType = type === "facturation" ? "livraison" : "facturation"; 157 let otherCollapseElement = document.getElementById(`basket_form_${otherType}`); 158 let bsOtherCollapseElement = new bootstrap.Collapse(otherCollapseElement, {toggle: false}); 159 160 161 adresseElement.addEventListener('click', async function () { 162 163 164 if (!otherCollapseElement.classList.contains('show') && !collapseElement.classList.contains('show')) { 165 166 if (type === "livraison") { 167 await get_cache_current_delivery_address(); 168 await unset_delivery_mode(); 169 disabled_inputs_form_adresse_livraison(false); 170 await check_pts_relais(); 171 await update_form_adresse_livraison(); 172 document.getElementById("check_differente_adresse").checked = false; 173 } 174 175 var infosForm = {"collapse": true}; 176 177 // Appeler les deux fonctions d'update et attendre qu'elles se terminent 178 await update_both_labels_info(infosForm, infosForm); 179 bsCollapseElement.show(); 180 bsOtherCollapseElement.hide(); 181 182 document.getElementById("basket_facturation_adresse").classList.remove("bg-disabled"); 183 document.getElementById("basket_livraison_adresse").classList.remove("bg-disabled");
184 if (bsCollapseElement._element.id === "basket_form_facturation") { 185 document.getElementById("basket_livraison_adresse").classList.add("bg-disabled"); 186 } else if (bsCollapseElement._element.id === "basket_form_livraison") { 187 document.getElementById("basket_facturation_adresse").classList.add("bg-disabled"); 188 } 189 } 190 }); 191 192} 193 194function basket_switch_vehicule() { 195 document.getElementById("panier_select_vehicule").addEventListener("change", async function () { 196 await get_vehicule(); 197 }); 198} 199 200async function form_adr_fac() { 201 document.querySelector("#form_adr_fact").addEventListener("submit", async function (event) { 202 203 event.preventDefault(); // Empêche l'envoi du formulaire 204 await check_tva_intracom( this, "facturation"); 205 await check_cp(this, "facturation"); 206 // await check_form_code_fiscal(this, "facturation"); 207 this.classList.remove('was-validated'); // Ajoute la classe pour afficher les erreurs 208 if (!this.checkValidity()) { 209 event.stopPropagation(); // Stoppe la propagation de l'événement 210 this.classList.add('was-validated'); // Ajoute la classe pour afficher les erreurs 211 return; // Sort de la fonction pour éviter de continuer l'exécution 212 } 213 214 show_ajax_loader(); 215 const is_valid = validate_form(this); 216 if (is_valid) { 217 // Initialisation des objets pour les données du formulaire 218 const formData = new FormData(); 219 const infos_form = {}; 220 let infos_form_livraison = {}; 221 // Sélection des inputs visibles et non masqués 222 document.querySelectorAll("#form_adr_fact input, #form_adr_fact select").forEach(element => { 223 const parent = element.closest('.input-group') || element; 224 if (!parent.classList.contains('d-none') && !element.classList.contains('d-none')) { 225 formData.append(element.name, element.value); 226 } 227 }); 228 229 // Conversion de FormData en un objet JavaScript 230 formData.forEach((value, key) => { 231 if (key.endsWith('_v3')) { 232 key = key.replace('_v3', ''); 233 } 234 if (key.endsWith('_facturation')) { 235 key = key.replace('_facturation', ''); 236 } 237 infos_form[key] = value; 238 }); 239 240 const params = new URLSearchParams(); 241 params.append('csrf_test_name', document.querySelector("[name=csrf_test_name]").value); 242 params.append('adresse', JSON.stringify(infos_form)); 243 try { 244 const response = await fetch(get_protocol_domain_name() + "/panier_v3/save_adresse_facturation", { 245 method: 'POST', headers: { 246 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 247 }, body: params, 248 mode: 'cors', 249 credentials: 'same-origin' 250 }); 251 252 if (response.ok) { 253 const data = await response.text(); 254 var valid = JSON.parse(data); 255 if (valid["status"] === "success") { 256 const promises = []; 257 var other_pays = false; 258 infos_form["collapse"] = false; 259 260 if (infos_form["pays"] !== document.querySelector("#pays_livraison").value) { 261 other_pays = true; 262 promises.push(set_identic_livraison_to_facturation()); 263 infos_form_livraison = infos_form; 264 } 265 266 promises.push(update_both_labels_info(infos_form,infos_form_livraison)); 267 promises.push(get_navigation()); 268 promises.push(get_vat_changed_info()); 269 await Promise.all(promises); 270 await check_country_is_valid(document.querySelector("#pays_facturation").value); 271 var myCollapse_2 = document.querySelector("#basket_form_facturation"); 272 var bsCollapse_2 = new bootstrap.Collapse(myCollapse_2, { 273 toggle: false 274 }); 275 bsCollapse_2.hide(); 276 removeError("adr_errors") 277 278 if (other_pays) { 279 await get_basket_message(infos_form["pays_i"]); 280 } 281 await get_basket_footer_message(); 282 await get_recapitulatif_basket_view(); 283 await check_pts_relais(); 284 } else { 285 await valid_form_ajax(valid.errors, document.querySelector("#form_adr_fact"),"facturation"); 286 } 287 288 } else { 289 throw new Error('Response not OK'); 290 } 291 } catch (error) { 292 logDebug('Erreur lors de la requête :', error); 293 } finally { 294 hide_ajax_loader(); 295 } 296 } 297 }); 298} 299 300async function form_adr_liv() { 301 document.querySelector("#form_adr_liv").addEventListener("submit", async function (event) { 302 event.preventDefault(); 303 await check_cp(this, "livraison"); 304 305 if (!this.checkValidity()) { 306 event.stopPropagation(); // Stoppe la propagation de l'événement 307 this.classList.add('was-validated'); // Ajoute la classe pour afficher les erreurs 308 return; // Sort de la fonction pour éviter de continuer l'exécution 309 } 310 311 show_ajax_loader(); 312 validate_form(this); 313 try { 314 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 315 316 var fields = { 317 "nom": "nom", 318 "prenom": "prenom", 319 "entreprise": "entreprise", 320 "ad": "ad", 321 "ad1": "complement_adresse", 322 "cp": "cp", 323 "ville": "ville", 324 "telephone": "telephone", 325 "pays_livraison": "pays" 326 }; 327 328 var infos_form = {}; 329 330 for (var key in fields) { 331 var input = this.querySelector("[name=" + fields[key] + "]"); 332 if (input) { 333 infos_form[key] = input.value; 334 } 335 } 336 337 if (document.querySelector("#province_livraison")) { 338 infos_form["province"] = document.querySelector("#province_livraison").value; 339 } 340 341 const params = new URLSearchParams(); 342 params.append('csrf_test_name', csrf_test_name); 343 Object.entries(infos_form).forEach(([key, value]) => { 344 params.append(key, value); 345 }); 346 347 await save_address_livraison(infos_form, params); 348 349 350 } catch (error) { 351 logDebug('Erreur lors de la requête :', error); 352 } finally { 353 hide_ajax_loader(); 354 } 355 }); 356} 357 358async function save_address_livraison(infos_form, params, by_selected_pts_relais = false) { 359 const response = await fetch(get_protocol_domain_name() + "/panier_v3/save_adresse_livraison", { 360 method: 'POST', headers: { 361 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'
362 }, body: params, 363 mode: 'cors', 364 credentials: 'same-origin' 365 }); 366 367 if (response.ok) { 368 const data = await response.json(); 369 if (data.status === 'success') { 370 if (!by_selected_pts_relais) { 371 await check_pts_relais(); 372 } 373 infos_form.identic = data.identic; 374 infos_form.collapse = false; 375 await update_both_labels_info([], infos_form); 376 377 var myCollapse_2 = document.querySelector("#basket_form_livraison"); 378 var bsCollapse_2 = new bootstrap.Collapse(myCollapse_2, {toggle: false}); 379 bsCollapse_2.hide(); 380 removeError("adr_errors") 381 await cache_current_delivery_address(); 382 await get_recapitulatif_basket_view(); 383 384 } else { 385 await valid_form_ajax(data.errors, document.querySelector("#form_adr_liv"), ""); 386 } 387 remove_button_loader(document.querySelector("#btn_adresse")); 388 } else { 389 throw new Error('Response not OK'); 390 } 391} 392 393async function cache_current_delivery_address(telephone) { 394 try { 395 const form = document.querySelector("#form_adr_liv"); 396 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 397 const infos_form = { 398 "nom": form.querySelector("[name=nom]").value, 399 "prenom": form.querySelector("[name=prenom]").value, 400 "entreprise": form.querySelector("[name=entreprise]").value, 401 "ad": form.querySelector("[name=ad]").value, 402 "complement_adresse": form.querySelector("[name=complement_adresse]").value, 403 "cp": form.querySelector("[name=cp]").value, 404 "ville": form.querySelector("[name=ville]").value, 405 "telephone": telephone ?? form.querySelector("[name=telephone]").value, 406 "pays_livraison": form.querySelector("[name=pays]").value 407 }; 408 409 if (form.querySelector("[name=province]")) { 410 infos_form["province"] = form.querySelector("[name=province]").value; 411 } 412 413 infos_form["is_pts_relais"] = false; 414 if (document.querySelectorAll(".delivery-domicile").length > 0) { 415 document.querySelectorAll(".delivery-domicile").forEach(function (el) { 416 if (el.classList.contains("show") && el.parentElement.classList.contains("show")) { 417 infos_form["is_pts_relais"] = true; 418 } 419 }); 420 } 421 422 const params = new URLSearchParams(); 423 params.append('csrf_test_name', csrf_test_name); 424 Object.entries(infos_form).forEach(([key, value]) => { 425 params.append(key, value); 426 }); 427 428 await fetch(get_protocol_domain_name() + "/panier_v3/cache_current_delivery_address", { 429 method: 'POST', headers: { 430 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 431 }, body: params, mode: 'cors', credentials: 'same-origin' 432 }); 433 434 } catch (error) { 435 logDebug('Erreur lors de la requête :', error); 436 } 437} 438 439async function get_cache_current_delivery_address() { 440 try { 441 show_ajax_loader(); 442 const response = await fetch(get_protocol_domain_name() + "/panier_v3/get_cache_current_delivery_address", { 443 method: 'GET', 444 headers: { 445 'Content-Type': 'application/json', 446 'X-Requested-With': 'XMLHttpRequest' 447 }, 448 mode: 'cors', 449 credentials: 'same-origin' 450 }); 451 452 if (response.ok) { 453 const data = await response.json(); 454 // Reformatage des données pour correspondre à ton `infos_form` 455 const infos_form = { 456 nom: data.nom || "", 457 prenom: data.prenom || "", 458 entreprise: data.societe || "", // ici c'est "societe" côté PHP 459 ad: data.adresse_1 || "", 460 complement_adresse: data.adresse_2 || "", 461 cp: data.code_postal || "", 462 ville: data.ville || "", 463 telephone: data.telephone || "", 464 pays_livraison: data.pays || "" 465 }; 466 467 if (data.province) { 468 infos_form.province = data.province; 469 } 470 471 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 472 473 const params = new URLSearchParams(); 474 params.append('csrf_test_name', csrf_test_name); 475 Object.entries(infos_form).forEach(([key, value]) => { 476 params.append(key, value); 477 }); 478 await save_address_livraison(infos_form, params, true); 479 480 } 481 } catch (error) { 482 logDebug('Erreur lors de la requête :', error); 483 } finally { 484 hide_ajax_loader(); 485 } 486} 487 488async function get_vat_changed_info() { 489 const csrfToken = document.querySelector("[name=csrf_test_name]")?.value; 490 const paysFournisseur = document.querySelector("#pays_fournisseur")?.value; 491 const paysClient = document.querySelector("#pays_facturation")?.value || document.querySelector("#pays_client")?.value; 492 493 if (!csrfToken || !paysFournisseur || !paysClient) { 494 logDebug("Certains champs requis sont manquants."); 495 return; 496 } 497 498 const params = new URLSearchParams({ 499 csrf_test_name: csrfToken, 500 pays_fournisseur: paysFournisseur, 501 pays_client: paysClient 502 }); 503 504 try { 505 const response = await fetchWithRetries(get_protocol_domain_name() + "/panier_v3/get_basket_vat_changed", { 506 method: 'POST', headers: { 507 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'
508 }, body: params, mode: 'cors', credentials: 'same-origin' 509 }); 510 511 const infoElement = document.querySelector("#basket_vat_changed_info"); 512 513 if (!infoElement) return; 514 515 if (response.ok) { 516 const result = await response.text(); 517 infoElement.classList.toggle("d-block", Boolean(result)); 518 infoElement.classList.toggle("d-none", !result); 519 } 520 } catch (error) { 521 logDebug('Erreur lors de la requête :', error); 522 throw error; // Rejeter l'erreur pour la gérer à l'extérieur si nécessaire 523 } 524} 525 526async function form_panier_information() { 527 document.querySelector("#form_panier_information").addEventListener("submit", function (event) { 528 if (!event.target.checkValidity()) { 529 event.preventDefault(); // Empêche l'envoi du formulaire si invalide 530 event.stopPropagation(); 531 } 532 event.target.classList.add('was-validated'); // Ajoute une classe pour montrer l'état de validation 533 }, false) 534} 535 536async function form_panier_commentaire() { 537 document.querySelector("#form_panier_commentaire").addEventListener("submit", function (event) { 538 if (!event.target.checkValidity()) { 539 event.preventDefault(); // Empêche l'envoi du formulaire si invalide 540 event.stopPropagation(); 541 } 542 event.target.classList.add('was-validated'); // Ajoute une classe pour montrer l'état de validation 543 }, false); 544} 545 546async function form_promo() { 547 if (document.querySelector("#form_basket_add_code_promo")) { 548 document.querySelector("#form_basket_add_code_promo").addEventListener("submit", async function (event) { 549 event.preventDefault(); // Empêche l'envoi du formulaire si invalide 550 show_ajax_loader(); 551 try { 552 const csrf_test_name = this.querySelector("[name=csrf_test_name]").value; 553 const code_promo = this.querySelector("[name=input_basket_code_promo]").value; 554 if (code_promo) { 555 const infos_form = { 556 "code_promo": code_promo, 557 }; 558 559 const params = new URLSearchParams(); 560 params.append('csrf_test_name', csrf_test_name); 561 Object.entries(infos_form).forEach(([key, value]) => { 562 params.append(key, value); 563 }); 564 565 const response = await fetch(get_protocol_domain_name() + "/panier_v3/add_code_promo", { 566 method: 'POST', headers: { 567 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 568 }, body: params, 569 mode: 'cors', 570 credentials: 'same-origin' 571 }); 572 573 if (response.ok) { 574 const data = await response.json(); 575 if (data.status === 'success') { 576 await get_recapitulatif_basket_view(); 577 if (document.querySelector(".panier-tab")) { 578 await get_tables_baskets() 579 } 580 if (document.querySelector("#delivery_area_all")) { 581 await get_delivery_mod_view(); 582 await load_choix_livr(); 583 await choix_pts_relais(); 584 } 585 } else { 586 if (data.redirect) { 587 window.location.href = data.redirect; // Redirection vers la confirmation 588 } 589 document.querySelector("#input_basket_code_promo_error").classList.add("d-block"); 590 document.querySelector("#input_basket_code_promo_error").innerText = data.message; 591 } 592 } else { 593 throw new Error('Response not OK'); 594 } 595 } else { 596 if (document.querySelector("#input_basket_code_promo_error").classList.contains("d-block")) { 597 document.querySelector("#input_basket_code_promo_error").classList.remove("d-block"); 598 document.querySelector("#input_basket_code_promo_error").innerText = ""; 599 } 600 } 601 } catch (error) { 602 logDebug('Erreur lors de la requête :', error); 603 } finally { 604 hide_ajax_loader(); 605 } 606 }); 607 } 608 609} 610 611async function form_delete_promo() { 612 if (document.querySelector("#form_basket_delete_code_promo")) { 613 document.querySelector("#form_basket_delete_code_promo").addEventListener("submit", async function (event) { 614 event.preventDefault(); // Empêche l'envoi du formulaire si invalide 615 show_ajax_loader(); 616 try { 617 const csrf_test_name = this.querySelector("[name=csrf_test_name]").value; 618 619 const params = new URLSearchParams(); 620 params.append('csrf_test_name', csrf_test_name); 621 622 const response = await fetch(get_protocol_domain_name() + "/panier_v3/delete_code_promo", { 623 method: 'POST', headers: { 624 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'
625 }, body: params, 626 mode: 'cors', 627 credentials: 'same-origin' 628 }); 629 630 if (response.ok) { 631 const data = await response.json(); 632 if (data.status === 'success') { 633 await get_recapitulatif_basket_view(); 634 if (document.querySelector(".panier-tab")) { 635 await get_tables_baskets() 636 } 637 if (document.querySelector("#delivery_area_all")) { 638 await get_delivery_mod_view(); 639 await load_choix_livr(); 640 await choix_pts_relais(); 641 } 642 } else { 643 if (data.redirect) { 644 window.location.href = data.redirect; // Redirection vers la confirmation 645 } 646 } 647 } else { 648 throw new Error('Response not OK'); 649 } 650 } catch (error) { 651 logDebug('Erreur lors de la requête :', error); 652 } finally { 653 hide_ajax_loader(); 654 } 655 }); 656 657 } 658} 659 660async function form_panier_mobile_coliship() { 661 const form = document.querySelector("#form_panier_mobile_coliship"); 662 if (!form) return; 663 664 form.addEventListener("submit", async function (e) { 665 e.preventDefault(); 666 show_ajax_loader(); 667 668 const input = this.querySelector("#choix_livraison_mobile"); 669 const reason = document.querySelector("#paiement_valider_reason_mobile"); 670 input.setCustomValidity(""); 671 reason?.classList.add("d-none"); 672 673 try { 674 const params = new URLSearchParams(); 675 params.append("csrf_test_name", this.querySelector("[name=csrf_test_name]")?.value || ""); 676 params.append("mobile_coliship", input.value); 677 678 const response = await fetch(get_protocol_domain_name() + "/panier_v3/add_mobile_coliship", { 679 method: "POST", 680 headers: { 681 "Content-Type": "application/x-www-form-urlencoded", 682 "X-Requested-With": "XMLHttpRequest", 683 "Accept": "application/json", 684 }, 685 body: params.toString(), 686 mode: "cors", 687 credentials: "same-origin", 688 }); 689 690 if (!response.ok) throw new Error("Response not OK"); 691 const data = await response.json(); 692 if (data.success) { 693 const mobile = input.value.replace(/^0(?=[67]\d{8}$)/, ""); 694 await cache_current_delivery_address(mobile); 695 await update_form_adresse_livraison(); 696 697 var infos_form = { 698 "nom": document.querySelector("#nom_livraison").value, 699 "prenom": document.querySelector("#prenom_livraison").value, 700 "societe": document.querySelector("#entreprise_livraison").value, 701 "adresse_1": document.querySelector("#ad_livraison").value, 702 "adresse_2": document.querySelector("#complement_adresse_livraison").value, 703 "code_postal": document.querySelector("#cp_livraison").value, 704 "ville": document.querySelector("#ville_livraison").value, 705 "telephone": mobile, 706 "pays": document.querySelector("#pays_livraison").value, 707 }; 708 infos_form["province"] = (document.querySelector("#province_livraison")) ? document.querySelector("#province_livraison").value : ""; 709 710 await update_both_labels_info([], infos_form); 711 712 document.querySelector("#div_info_livraison")?.classList.add("d-none"); 713 } else { 714 input.setCustomValidity(await trad("_MISSMATCH_MOBILE")); 715 reason?.classList.remove("d-none"); 716 input.reportValidity(); 717 } 718 } catch (err) { 719 input.setCustomValidity(await trad("_MISSMATCH_MOBILE")); 720 input.reportValidity(); 721 } finally { 722 hide_ajax_loader(); 723 } 724 }); 725} 726 727 728async function form_panier_payment(form) { 729 removeError("payment"); 730 731 let payment_mod = false; 732 if (form) { 733 payment_mod = form.querySelector("[name=choix_payment]:checked")?.value || ""; 734 } 735 // Vérifie si un mode de paiement est sélectionné 736 if (!payment_mod || !form) { 737 addError("payment", await trad("_PAYMENT_NO_SELECTED")); 738 hide_ajax_loader(); 739 return false; // â Ne pas continuer si aucun paiement n'est sélectionné 740 } 741 742 return true; 743} 744 745// async function check_payment_conditions(form, maxRetries = 5, retries = 0) { 746// const csrf = form.querySelector("[name=csrf_test_name]").value; 747// const payment_mod = form.querySelector("[name=choix_payment]:checked").value; 748// const pays = form.querySelector("[name=pays]")?.value || ""; 749// const pro = form.querySelector("[name=pro]").value; 750// 751// show_ajax_loader(); 752// try { 753// const params = new URLSearchParams(); 754// params.append('csrf_test_name', encodeURIComponent(csrf)); 755// params.append('payment_name', encodeURIComponent(payment_mod));
756// params.append('pays', encodeURIComponent(pays)); 757// params.append('pro', encodeURIComponent(pro)); 758// 759// const response = await fetch(get_protocol_domain_name() + "/panier_v3/get_payment_conditions", { 760// method: 'POST', 761// headers: { 762// 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 763// }, 764// body: params, 765// mode: 'cors', 766// credentials: 'same-origin' 767// }); 768// 769// if (response.ok) { 770// const result = await response.json(); 771// if (result["card_max_amount"] > 0) { 772// 773// } 774// debugger; 775// } else { 776// throw new Error('Réponse non valide'); 777// } 778// } catch (error) { 779// if (retries < maxRetries) { 780// return check_payment_conditions(form, maxRetries, retries + 1); 781// } 782// } finally { 783// // Cache toujours le loader après l'exécution (succès ou échec) 784// hide_ajax_loader(); 785// } 786// } 787 788// Fonction auxiliaire pour les retries avec fetch 789 790 791async function set_identic_livraison_to_facturation(identic = true) { 792 const csrf_test_name = encodeURIComponent(document.querySelector("[name=csrf_test_name]").value); 793 const replace_adresse = encodeURIComponent(document.querySelector("[name=replace_adresse]").value); 794 795 const params = new URLSearchParams(); 796 params.append('csrf_test_name', csrf_test_name); 797 params.append('replace_adresse', replace_adresse); 798 799 try { 800 show_ajax_loader(); 801 const response = await fetchWithRetries(get_protocol_domain_name() + "/panier_v3/save_adresse_livraison_identic_to_facturation", { 802 method: 'POST', headers: { 803 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 804 }, body: params, 805 mode: 'cors', 806 credentials: 'same-origin' 807 }); 808 809 if (response.ok) { 810 const responseData = await response.json(); 811 if (responseData.error) { 812 logDebug("Error"); 813 } else { 814 815 var infos_form = { 816 "nom": document.querySelector("#nom_facturation").value, 817 "prenom": document.querySelector("#prenom_facturation").value, 818 "societe": document.querySelector("#entreprise_facturation").value, 819 "adresse_1": document.querySelector("#ad_facturation").value, 820 "adresse_2": document.querySelector("#ad1_facturation").value, 821 "code_postal": document.querySelector("#cp_facturation").value, 822 "ville": document.querySelector("#ville_facturation").value, 823 "telephone": document.querySelector("#telephone_facturation").value, 824 "pays": document.querySelector("#pays_facturation").value, 825 "identic": identic 826 }; 827 infos_form["province"] = (document.querySelector("#province_facturation")) ? document.querySelector("#province_facturation").value : ""; 828 829 const promises = []; 830 promises.push(update_both_labels_info([], infos_form)); 831 promises.push(update_form_adresse_livraison()); 832 await Promise.all(promises); 833 834 // Attention la mise en cache de l'adresse de livraison doit impérativement être faites APRES update_form_adresse_livraison 835 // Dans le Promises.all rien n'assure que ce soit le cas. 836 await cache_current_delivery_address(); 837 838 check_differente_adresse(); 839 840 // PROVINCE 841 if (document.querySelector("#province")) { 842 document.querySelector("#province_div").innerHTML = ""; 843 } 844 if (document.querySelector("#province_facturation") && document.querySelector("#province_facturation").value !== "") { 845 await get_provinces_html(document.querySelector("#pays_facturation").value, document.querySelector("#province_facturation").value, "facturation", document.querySelector("#pays_facturation").form); 846 jQuery('.province_toggle').show(); 847 } 848 //// 849 } 850 hide_ajax_loader(); 851 } else { 852 hide_ajax_loader(); 853 } 854 } catch (error) { 855 hide_ajax_loader(); 856 logDebug('Erreur lors de la requête :', error); 857 } 858} 859function submit_panier_commentaire() { 860 let typingTimer; // Identifiant du timer, maintenant scoper à cette fonction 861 const doneTypingInterval = 1500; // Temps d'attente en millisecondes (1.30 secondes) 862 863 // Fonction pour enregistrer le commentaire 864 async function saveComment() { 865 const formulaire = document.querySelector("#form_panier_commentaire"); 866 if (!validate_form(formulaire)) { 867 logDebug("Erreurs de validation du formulaire"); 868 return false; 869 } 870 871 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 872 const commentaire_basket = document.querySelector("#commentaire_basket") ? document.querySelector("#commentaire_basket").value : ""; 873 874 const params = new URLSearchParams(); 875 params.append('csrf_test_name', csrf_test_name); 876 params.append('commentaire_basket', commentaire_basket); 877 878 try { 879 const response = await fetch(get_protocol_domain_name() + "/panier_v3/save_basket_commentary", { 880 method: 'POST', 881 headers: { 882 'Content-Type': 'application/x-www-form-urlencoded', 883 'X-Requested-With': 'XMLHttpRequest'
884 }, 885 body: params.toString(), 886 mode: 'cors', 887 credentials: 'same-origin' 888 }); 889 890 if (response.ok) { 891 return true; // Retourner true pour indiquer le succès 892 } else { 893 return false; 894 } 895 } catch (error) { 896 logDebug('Erreur lors de la requête :', error); 897 return false; 898 } 899 } 900 901 // Ãvénement pour détecter la saisie dans le textarea 902 const textarea = document.querySelector("#commentaire_basket"); 903 if (textarea) { 904 textarea.addEventListener("keyup", () => { 905 clearTimeout(typingTimer); // Réinitialiser le timer 906 typingTimer = setTimeout(() => { 907 saveComment(); // Appeler la fonction après 2 secondes d'inactivité 908 }, doneTypingInterval); 909 }); 910 911 textarea.addEventListener("keydown", () => { 912 clearTimeout(typingTimer); // Réinitialiser le timer si une touche est enfoncée 913 }); 914 } 915} 916 917async function submit_panier_information(maxRetries = 5, retries = 0) { 918 919 var formulaire = document.querySelector("#form_panier_information"); 920 if (!validate_form(formulaire)) { 921 logDebug("Erreurs de validation du formulaire"); 922 return false; 923 } 924 925 let csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 926 let type_carte_grise = document.getElementById("type_carte_grise") ? document.querySelector("#type_carte_grise").value : ""; 927 let numero_serie = document.getElementById("numero_serie") ? document.querySelector("#numero_serie").value : ""; 928 let couleur_moto = document.getElementById("couleur_moto") ? document.querySelector("#couleur_moto").value : ""; 929 930 let ask_for_verif = document.getElementById("flexCheckDefault") ? (document.querySelector("#flexCheckDefault").checked ? 1 : 0) : 0; 931 932 let params = new URLSearchParams(); 933 params.append('csrf_test_name', csrf_test_name); 934 params.append('type_carte_grise', type_carte_grise); 935 params.append('numero_serie', numero_serie); 936 params.append('couleur_moto', couleur_moto); 937 params.append('ask_for_verif', ask_for_verif); 938 if (document.querySelector("#numero_serie") && document.querySelector("#numero_serie").getAttribute("minlength")) { 939 params.append('numero_serie_required', true); 940 } 941 942 try { 943 const response = await fetch_with_retries(get_protocol_domain_name() + "/panier_v3/save_basket_information", { 944 method: 'POST', headers: { 945 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 946 }, body: params.toString(), 947 mode: 'cors', 948 credentials: 'same-origin' 949 }); 950 if (response.ok) { 951 return response.ok; 952 } else { 953 throw new Error('Nombre maximal de tentatives atteint'); 954 955 } 956 957 } catch (error) { 958 logDebug('Erreur lors de la requête :', error); 959 return false; 960 } 961} 962 963async function submit_panier_cgv() { 964 965 var formulaire = document.querySelector("#form_panier_cgv"); 966 if (!validate_form(formulaire)) { 967 logDebug("Erreurs de validation du formulaire"); 968 return false; 969 } 970 971 let csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 972 let cgv = document.getElementById("checkbox_condition_vente").checked ? true : false; 973 974 let params = new URLSearchParams(); 975 params.append('csrf_test_name', csrf_test_name); 976 params.append('cgv', cgv); 977 try { 978 const response = await fetch_with_retries(get_protocol_domain_name() + "/panier_v3/save_basket_cgv", { 979 method: 'POST', headers: { 980 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 981 }, body: params.toString(), 982 mode: 'cors', 983 credentials: 'same-origin' 984 }); 985 if (response.ok) { 986 const result = await response.json(); 987 if (result.url) { 988 window.location.href = result.url; // Redirection vers la confirmation 989 } else { 990 return result.res; 991 } 992 } else { 993 994 } 995 996 } catch (error) { 997 logDebug('Erreur lors de la requête :', error); 998 return false; 999 } 1000} 1001 1002async function update_both_labels_info(facturationInfos, livraisonInfos) { 1003 // show_ajax_loader(); 1004 const [facturationResponse, livraisonResponse] = await Promise.all([update_labels_info_adresses("/panier_v3/get_basket_facturation_view", facturationInfos), update_labels_info_adresses("/panier_v3/get_basket_livraison_view", livraisonInfos)]); 1005 // Mettre à jour le DOM après avoir reçu les deux réponses 1006 if (livraisonResponse && facturationResponse) { 1007 // Exemple d'utilisation d'innerHTML pour mettre à jour le DOM 1008 document.querySelector("#collapse_basket_livraison").innerHTML = livraisonResponse; 1009 document.querySelector("#collapse_basket_facturation").innerHTML = facturationResponse; 1010 1011 // Réinitialiser les collapses après mise à jour du DOM 1012 gestion_collapse_adresse("facturation"); 1013 gestion_collapse_adresse("livraison"); 1014 } else { 1015 window.location.href = "/" + await trad('_ROUTE_PANIER_AFFICHER') 1016 } 1017} 1018 1019async function update_labels_info_adresses(url, infos_form) { 1020 var csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 1021 1022 const params = new URLSearchParams(); 1023 params.append('csrf_test_name', csrf_test_name); 1024 1025 if (infos_form) { 1026 const field = url.includes("facturation") ? 'adresse_facturation' : 'adresse_livraison'; 1027 params.append(field, JSON.stringify(infos_form)); // encodé automatiquement 1028 } 1029 1030 try { 1031 const response = await fetchWithRetries(get_protocol_domain_name() + url, { 1032 method: 'POST', headers: { 1033 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'
1034 }, body: params, 1035 mode: 'cors', 1036 credentials: 'same-origin' 1037 }); 1038 1039 if (response.ok) { 1040 return await response.text(); 1041 } 1042 } catch (error) { 1043 // Gérer les erreurs 1044 logDebug('Erreur lors de la requête :', error); 1045 throw error; 1046 } 1047} 1048 1049async function update_labels_info_adresse_livraison(infos_form) { 1050 var csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 1051 var params = 'csrf_test_name=' + encodeURIComponent(csrf_test_name); 1052 if (infos_form) { 1053 params += '&adresse_livraison=' + JSON.stringify(infos_form); 1054 } 1055 try { 1056 const response = await fetchWithRetries(get_protocol_domain_name() + "/panier_v3/get_basket_livraison_view", { 1057 method: 'POST', headers: { 1058 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 1059 }, body: params, 1060 mode: 'cors', 1061 credentials: 'same-origin' 1062 }); 1063 1064 if (response.ok) { 1065 const data = await response.text(); 1066 if (data == "false") { 1067 window.location.href = "/" + await trad('_ROUTE_PANIER_AFFICHER') 1068 } else { 1069 document.getElementById("collapse_basket_livraison").innerHTML = data; 1070 gestion_collapse_adresse("livraison"); 1071 } 1072 } else { 1073 window.location.href = "/" + await trad('_ROUTE_PANIER_AFFICHER') 1074 } 1075 } catch (error) { 1076 // Gérer les erreurs 1077 logDebug('Erreur lors de la requête :', error); 1078 } 1079} 1080 1081async function update_delivery_area_info_adresse_livraison(num_panier, maxRetries = 5, retries = 0) { 1082 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 1083 1084 const params = new URLSearchParams(); 1085 params.append('csrf_test_name', csrf_test_name); 1086 params.append('num_panier', num_panier); 1087 1088 try { 1089 const response = await fetch(get_protocol_domain_name() + "/panier_v3/get_adresse_livraison_view", { 1090 method: 'POST', headers: { 1091 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 1092 }, body: params, 1093 mode: 'cors', 1094 credentials: 'same-origin' 1095 }); 1096 1097 if (response.ok) { 1098 const data = await response.text(); 1099 document.getElementById("views_panier_livraison_" + num_panier).innerHTML = data; 1100 } else { 1101 if (retries < maxRetries) { 1102 retries++; 1103 logDebug("Tentative " + retries + " de " + maxRetries); 1104 // Réessayer la requête 1105 return update_delivery_area_info_adresse_livraison(num_panier, maxRetries, retries); 1106 } else { 1107 throw new Error('Nombre maximal de tentatives atteint'); 1108 } 1109 } 1110 } catch (error) { 1111 // Gérer les erreurs 1112 logDebug('Erreur lors de la requête :', error); 1113 } 1114} 1115 1116async function update_form_adresse_livraison(maxRetries = 5, retries = 0) { 1117 var csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 1118 var params = 'csrf_test_name=' + encodeURIComponent(csrf_test_name); 1119 1120 try { 1121 const response = await fetch(get_protocol_domain_name() + "/panier_v3/get_form_adresse_livraison_view", { 1122 method: 'POST', headers: { 1123 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 1124 }, body: params, 1125 mode: 'cors', 1126 credentials: 'same-origin' 1127 }); 1128 1129 if (response.ok) { 1130 const data = await response.text(); 1131 document.getElementById("basket_form_livraison").innerHTML = data; 1132 set_prefix_by_coutry(document.querySelector("#pays_livraison").value, "livraison") 1133 1134 document.querySelector("#cp_livraison").addEventListener("change", async function () { 1135 document.querySelector("#cp_livraison").value = document.querySelector("#cp_livraison").value.trim(); 1136 document.querySelector("#cp_livraison").value = document.querySelector("#cp_livraison").value.toUpperCase(); 1137 await check_cp(document.getElementById("basket_form_livraison"), "livraison"); 1138 }); 1139 1140 if (document.querySelector("#check_differente_adresse")) check_differente_adresse(); 1141 1142 await form_adr_liv(); 1143 } else { 1144 if (retries < maxRetries) { 1145 retries++; 1146 logDebug("Tentative " + retries + " de " + maxRetries); 1147 // Réessayer la requête 1148 return update_form_adresse_livraison(maxRetries, retries); 1149 } else { 1150 throw new Error('Nombre maximal de tentatives atteint'); 1151 } 1152 } 1153 } catch (error) { 1154 // Gérer les erreurs 1155 logDebug('Erreur lors de la requête :', error); 1156 } 1157} 1158 1159function disabled_inputs_form_adresse_livraison(disabled = true) { 1160 document.getElementById("ad_livraison").disabled = disabled; 1161 document.getElementById("complement_adresse_livraison").disabled = disabled; 1162 document.getElementById("cp_livraison").disabled = disabled; 1163 document.getElementById("ville_livraison").disabled = disabled; 1164 document.getElementById("check_differente_adresse").checked = false; 1165} 1166 1167/////////////////////////////// 1168 1169function check_differente_adresse() { 1170 document.querySelector("#check_differente_adresse").addEventListener("change", async function () { 1171 if (this.checked) { 1172 var myCollapse_2 = document.querySelector("#basket_form_livraison"); 1173 var bsCollapse_2 = new bootstrap.Collapse(myCollapse_2, {toggle: false}); 1174 bsCollapse_2.hide(); 1175 var infos_form = []; 1176 1177 infos_form["collapse"] = false; 1178 // const promises = []; 1179 1180 // promises.push(set_identic_livraison_to_facturation()); 1181 await set_identic_livraison_to_facturation(); 1182 // promises.push(update_both_labels_info(infos_form)); 1183 // 1184 // await Promise.all(promises); 1185 } 1186 }); 1187} 1188 1189// async function verif_is_pts_relais() { 1190// if (document.getElementById("is_pts_relais").value === "true") { 1191// return false; 1192// } 1193// } 1194 1195/////////////// 1196// Fonction pour ajouter un élément au panier 1197 1198function add_basket() { 1199 document.querySelectorAll(".JS_table_panier_parts form").forEach(function (form) { 1200 form.addEventListener("submit", function (event) { 1201 event.preventDefault(); 1202 addToBasket(form); 1203 }); 1204 }); 1205 1206 document.querySelectorAll("#table_panier_shop form").forEach(function (form) { 1207 form.addEventListener("submit", function (event) { 1208 event.preventDefault(); 1209 addToBasket(form); 1210 }); 1211 }); 1212} 1213 1214function addToBasket(form) { 1215 show_ajax_loader(); 1216 var csrf_test_name = getInputValue(form, 'input[name=csrf_test_name]'); 1217 1218 var type_add_basket = getInputValue(form, 'input[name=type_add_basket]'); 1219 var params = new URLSearchParams(); 1220 params.append('csrf_test_name', csrf_test_name); 1221 params.append('type_add_basket', type_add_basket); 1222 1223 params.append('recherche', getInputValue(form, 'input[name=id]')); 1224 params.append('libelle_piece', getInputValue(form, 'input[name=libelle_piece]')); 1225 1226 const unite_de_vente = getInputValue(form, 'input[name=unite_de_vente]') || 1; 1227 1228 params.append('unite_de_vente', unite_de_vente); 1229 1230 switch(type_add_basket) { 1231 case "stop_affaire": 1232 params = addToBasketStopAffaire(form,params); 1233 break; 1234 case "parts": 1235 params = addToBasketParts(form,params); 1236 break; 1237 case "shop": 1238 params = addToBasketShop(form,params); 1239 break; 1240 case "classic_red": 1241 params = addToBasketClassicRed(form,params); 1242 break; 1243 1244 } 1245 1246 1247 fetch(get_protocol_domain_name() + "/panier_v3/add_basket", { 1248 method: "POST", 1249 headers: { 1250 'Content-Type': 'application/x-www-form-urlencoded', 1251 'X-Requested-With': 'XMLHttpRequest'
1252 }, 1253 body: params 1254 }) 1255 .then(response => response.text()) 1256 .then(data => { 1257 const response = JSON.parse(data); 1258 if (response["stop_here"]) { 1259 updateBasketModal(csrf_test_name, response); 1260 } else { 1261 document.querySelectorAll('.resultat_ajout_panier').forEach(function (element) { 1262 element.innerHTML = data; 1263 }); 1264 updateBasketModal(csrf_test_name, params); 1265 } 1266 1267 }) 1268 .catch(error => logDebug("Erreur lors de l'ajout au panier:", error)).finally(hide_ajax_loader); 1269 1270} 1271 1272function addToBasketTarifPortSupp(form,params) { 1273 return params; 1274 1275} 1276function addToBasketParts(form,params) { 1277 if (getInputValue(form, 'input[name=qte_table_parts]')) { 1278 params.append('quantite', getInputValue(form, 'input[name=qte_table_parts]')); 1279 } else { 1280 params.append('quantite', getInputValue(form, 'input[name=qty_shop]')); 1281 } 1282 return params; 1283} 1284 1285function addToBasketTarif(form,params) { 1286 params.append('vehicule', getInputValue(form, 'input[name=vehicule]')); 1287 params.append('id_v', getInputValue(form, 'input[name=id_v]')); 1288 params.append('v', getInputValue(form, 'input[name=v]')); 1289 params.append('v_n', getInputValue(form, 'input[name=v_n]')); 1290 params.append('quantite', getInputValue(form, 'input[name=qty_shop]')); 1291 return params; 1292 1293} 1294 1295function addToBasketShop(form,params) { 1296 params.append('id_prod', getInputValue(form, 'input[name=id_prod]')); 1297 params.append('codecat', getInputValue(form, 'input[name=codecat]')); 1298 params.append('type_commande', getInputValue(form, 'input[name=type_commande]')); 1299 params.append('quantite', getInputValue(form, 'input[name=qty_shop]')); 1300 1301 return params; 1302 1303} 1304 1305function addToBasketClassicRed(form,params) { 1306 params.append('quantite', getInputValue(form, 'input[name=qty]')); 1307 params.append('id_prod', getInputValue(form, 'input[name=id_prod]')); 1308 params.append('codecat', getInputValue(form, 'input[name=codecat]')); 1309 params.append('type_commande', getInputValue(form, 'input[name=type_commande]')); 1310 params.append('prix_achat', getInputValue(form, 'input[name=prix_achat]')); 1311 1312 return params; 1313 1314} 1315 1316function addToBasketStopAffaire(form,params) { 1317 params.append('quantite', getInputValue(form, 'input[name=qty_shop-sa]')); 1318 return params; 1319} 1320 1321function updateBasketModal(csrf_test_name,params) { 1322 if (!(params instanceof URLSearchParams)) { 1323 params = new URLSearchParams(params); 1324 } 1325 params.append("csrf_test_name",csrf_test_name); 1326 1327 fetch(get_protocol_domain_name() + "/panier_v3/panier_modal", { 1328 method: "POST", 1329 headers: { 1330 "Content-Type": "application/x-www-form-urlencoded" 1331 }, 1332 body: params 1333 }) 1334 .then(response => response.text()) 1335 .then(data => { 1336 if (document.getElementById('panier_modal')) { 1337 document.getElementById('panier_modal').innerHTML = data; 1338 showModal('basket_modal_add_items'); 1339 } 1340 1341 }) 1342 .catch(error => logDebug("Erreur lors de la mise à jour du panier:", error)); 1343} 1344 1345// Fonction principale pour ajouter un écouteur d'événement sur chaque formulaire de panier 1346function action_update_line_basket() { 1347 const qtyMinusButtons = document.querySelectorAll('.qty-count-panier--minus');
1348 const qtyPlusButtons = document.querySelectorAll('.qty-count-panier--add'); 1349 const qtyInputs = document.querySelectorAll('.product-qty-panier'); 1350 1351 let updateTimer; 1352 const debounceDelay = 300; // Délai avant mise à jour 1353 1354 // Fonction pour mettre à jour la quantité 1355 function updateQuantity(input, newQty) { 1356 input.value = newQty; 1357 input.dataset.previousQty = newQty; 1358 } 1359 1360 // Fonction de debounce pour gérer la mise à jour 1361 function handleUpdate(input) { 1362 clearTimeout(updateTimer); 1363 1364 const priceElements =[]; 1365 1366 let priceElement = input.closest('.tr-panier').querySelector('.basket_price'); 1367 1368 if (priceElement && !priceElement.classList.contains('spinner-border')) { 1369 priceElements.push(priceElement); 1370 } 1371 1372 // Ajouter la classe placeholder pour tous les éléments de priceElements 1373 priceElements.forEach(el => addSpinner(el)); 1374 toggleQtyButtons(input, true); 1375 1376 updateTimer = setTimeout(() => { 1377 1378 const form = input.closest('form'); 1379 update_line_basket(form).then(() => { 1380 setTimeout(() => { 1381 priceElements.forEach(el => removeSpinner(el)); 1382 toggleQtyButtons(input, false); 1383 }, 200); 1384 }).catch(error => { 1385 logDebug("Erreur de mise à jour:", error); 1386 priceElements.forEach(el => removeSpinner(el)); 1387 toggleQtyButtons(input, false); 1388 }); 1389 }, debounceDelay); 1390 } 1391 1392 function toggleQtyButtons(input, disabled) { 1393 const container = input.closest('.qty-input'); 1394 if (!container) return; 1395 1396 const minusBtn = container.querySelector('.qty-count-panier--minus'); 1397 const plusBtn = container.querySelector('.qty-count-panier--add'); 1398 1399 if (minusBtn) minusBtn.disabled = disabled; 1400 if (plusBtn) plusBtn.disabled = disabled; 1401 } 1402 1403 function addSpinner(element) { 1404 const spinnerHTML = `<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>`; 1405 const priceContent = element.textContent; // Sauvegarder le texte actuel 1406 1407 // Ajouter un data attribut pour conserver l'ancien texte 1408 element.setAttribute('data-original-content', priceContent.trim()); 1409 element.innerHTML = spinnerHTML; // Remplacer par le spinner 1410 } 1411 1412 // Fonction pour enlever le spinner et restaurer le contenu original 1413 function removeSpinner(element) { 1414 const originalContent = element.getAttribute('data-original-content'); 1415 if (originalContent !== null) { 1416 element.textContent = originalContent; // Restaurer le texte original 1417 element.removeAttribute('data-original-content'); // Supprimer l'attribut temporaire 1418 } 1419 } 1420 1421 1422 // Ajouter les écouteurs d'événements pour les boutons - 1423 qtyMinusButtons.forEach(button => { 1424 button.addEventListener('click', function () { 1425 const input = this.nextElementSibling; 1426 // récupération de la valeur du pas d'incrementation 1427 const increment = parseInt(this.parentElement.dataset.unite) || 1; 1428 let currentQty = parseInt(input.value) || 0; 1429 1430 if (currentQty >= increment) { 1431 currentQty -= increment; 1432 updateQuantity(input, currentQty); 1433 if(document.getElementById('view_step_basket')) handleUpdate(input); 1434 } 1435 1436 if (currentQty === 0) { 1437 const id = input.id.split('_').pop(); 1438 const form = input.closest('form'); 1439 1440 const onConfirm = () => delete_line_basket(form); 1441 const onCancel = () => { 1442 updateQuantity(input, currentQty + increment); 1443 if(document.getElementById('view_step_basket')) handleUpdate(input) 1444 } 1445 1446 open_modal_delete_line_basket(id, onConfirm, onCancel); 1447 } 1448 }); 1449 }); 1450 1451 // Ajouter les écouteurs d'événements pour les boutons + 1452 qtyPlusButtons.forEach(button => { 1453 button.addEventListener('click', function () { 1454 const input = this.previousElementSibling; 1455 // récupération de la valeur du pas d'incrementation 1456 const increment = parseInt(this.parentElement.dataset.unite) || 1; 1457 let currentQty = parseInt(input.value) || 0; 1458 const maxQty = parseInt(input.getAttribute('max')); 1459 1460 if (isNaN(maxQty) || currentQty < maxQty) { 1461 currentQty += increment; 1462 updateQuantity(input, currentQty); 1463 if(document.getElementById('view_step_basket')) handleUpdate(input); 1464 } 1465 }); 1466 }); 1467 1468 // Ãcouteurs pour les inputs de quantité
1469 qtyInputs.forEach(input => { 1470 let previousQty = input.value; 1471 1472 input.addEventListener('focus', function () { 1473 previousQty = this.value; 1474 }); 1475 1476 input.addEventListener('keydown', function (event) { 1477 if (event.key === 'Enter') { 1478 event.preventDefault(); 1479 handleUpdate(this); 1480 } 1481 }); 1482 1483 input.addEventListener('change', function () { 1484 const currentQty = parseInt(this.value) || 0; 1485 1486 if (currentQty === 0) { 1487 const id = this.id.split('_').pop(); 1488 const form = this.closest('form'); 1489 1490 const onConfirm = () => delete_line_basket(form); 1491 const onCancel = () => updateQuantity(this, previousQty); 1492 1493 open_modal_delete_line_basket(id, onConfirm, onCancel); 1494 } else { 1495 updateQuantity(this, currentQty); 1496 handleUpdate(this); 1497 } 1498 }); 1499 1500 // Empêche la soumission du formulaire parent si défini 1501 const form = input.closest('form'); 1502 if (form) { 1503 form.addEventListener('submit', event => event.preventDefault()); 1504 } 1505 }); 1506} 1507 1508function open_modal_delete_line_basket(id, onConfirm, onCancel) { 1509 1510 if (isModalOpen) { 1511 return; 1512 } 1513 const modal = document.getElementById('modal_supp_' + id); 1514 const modalInstance = bootstrap.Modal.getOrCreateInstance(modal); 1515 1516 isModalOpen = true; 1517 1518 modal.querySelector('.btn-confirm').onclick = () => { 1519 onConfirm(); 1520 modalInstance.hide(); 1521 }; 1522 1523 modal.querySelector('.btn-cancel').onclick = () => { 1524 onCancel(); 1525 modalInstance.hide(); 1526 }; 1527 1528 // Ãcouter l'événement de fermeture du modal 1529 modal.addEventListener('hidden.bs.modal', () => { 1530 isModalOpen = false; 1531 onCancel(); 1532 modalInstance.hide(); 1533 1534 }); 1535 1536 modalInstance.show(); 1537} 1538 1539function action_delete_line_basket() { 1540 var modals_supp = document.querySelectorAll(".modal_supp"); 1541 var form_modal_delete = ""; 1542 for (var x = 0; x < modals_supp.length; x++) { 1543 form_modal_delete = modals_supp[x].querySelector("[name=form_panier_supp]"); 1544 form_modal_delete.addEventListener("submit", async function (event) { 1545 event.preventDefault(); 1546 await delete_line_basket(this); 1547 }); 1548 } 1549 1550} 1551 1552async function delete_line_basket(form) { 1553 var params = new URLSearchParams(); 1554 params.append('csrf_test_name', document.querySelector("[name=csrf_test_name]").value); 1555 1556 if (form.querySelector("[name=id_ligne]")) { 1557 params.append('id_ligne', form.querySelector("[name=id_ligne]").value); 1558 params.append('id_entete', form.querySelector("[name=id_entete]").value); 1559 } 1560 1561 if (form.querySelector("[name=code_promo]")) { 1562 params.append('code_promo', form.querySelector("[name=code_promo]").value); 1563 if (document.querySelector("#JS_collapse_code_promo")) { 1564 document.querySelector("#JS_collapse_code_promo").innerHTML = await trad("_FORM_PANIER_CODE_PROMO_MISSING"); 1565 } 1566 } 1567 1568 fetch(get_protocol_domain_name() + "/panier_v3/supprimer_panier_ligne", { 1569 method: 'POST', headers: { 1570 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 1571 }, body: params, mode: 'cors', // Optionally set the CORS mode 1572 credentials: 'same-origin' // Include cookies in the request (if any) 1573 }).then(function (response) { 1574 return response.json(); 1575 }).then(function (res) { 1576 if (res["nb_ligne"] == 0 && res["url"]) { 1577 window.location.href = res["url"]; 1578 } else { 1579 var promise_get_tables_basket = get_tables_baskets(form.closest(".div_panier_table"), true); 1580 promise_get_tables_basket.then(function () { 1581 1582 }).catch(function (error) { 1583 logDebug(error); 1584 }); 1585 1586 refresh_compteur_panier(res["nb_ligne"]); 1587 1588 // check_pts_rts_relais(); 1589 var modal = bootstrap.Modal.getOrCreateInstance(document.getElementById("modal_supp_" + params.get('id_ligne'))); 1590 modal.hide(); 1591 1592 if (form.querySelector("[name=code_promo]")) { 1593 unset_free_delivery(); 1594 } 1595 } 1596 }).catch(function (error) { 1597 logDebug('Error:', error); 1598 }); 1599 1600} 1601 1602function update_line_basket(form) { 1603 var params = new URLSearchParams(); 1604 params.append('csrf_test_name', document.querySelector("[name=csrf_test_name]").value); 1605 1606 if (form.querySelector("[name=id_ligne]")) { 1607 params.append('id_ligne', form.querySelector("[name=id_ligne]").value); 1608 params.append('id_entete', form.querySelector("[name=id_entete]").value); 1609 params.append('qty', form.querySelector("[name=product-qty]").value); 1610 } 1611 1612 var qty = parseInt(params.get('qty'), 10); 1613 if (qty === 0) { 1614 const onConfirm = () => { 1615 delete_line_basket(form); 1616 }; 1617 1618 const onCancel = () => { 1619 return Promise.resolve(); 1620 }; 1621 1622 open_modal_delete_line_basket(params.get('id_ligne'), onConfirm, onCancel); 1623 return Promise.resolve(); 1624 } else { 1625 return fetch(get_protocol_domain_name() + "/panier_v3/update_panier_ligne", { 1626 method: 'POST', headers: { 1627 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'
1628 }, body: params, mode: 'cors', // Optionally set the CORS mode 1629 credentials: 'same-origin' // Include cookies in the request (if any) 1630 }).then(function (response) { 1631 return response.json(); 1632 }).then(function (res) { 1633 if (res["nb_ligne"] == 0 && res["url"]) { 1634 location.href = res["url"]; 1635 } else { 1636 return get_tables_baskets(form.closest(".div_panier_table")); 1637 1638 } 1639 }).catch(function (error) { 1640 logDebug('Error:', error); 1641 }); 1642 } 1643} 1644 1645function get_tables_baskets(table, loader = false) { 1646 if (loader) { 1647 show_ajax_loader(); 1648 } 1649 return new Promise(function (resolve, reject) { 1650 fetch(get_protocol_domain_name() + "/panier_v3/ajax_get_tables_baskets", { 1651 method: "GET", headers: { 1652 "Content-Type": "application/json", "X-Requested-With": "XMLHttpRequest" 1653 } 1654 }) 1655 .then(function (response) { 1656 if (response.ok) { 1657 return response.text(); 1658 } else { 1659 throw new Error("get_tables_baskets failed with status: " + response.status); 1660 } 1661 }) 1662 .then(async function (data) { 1663 if (table) { 1664 table.innerHTML = data; 1665 } else { 1666 document.querySelector("#view_step_basket").innerHTML = data; 1667 } 1668 1669 action_delete_line_basket(); 1670 action_update_line_basket(); 1671 reload_view_header_contact_concess(); 1672 await get_recapitulatif_basket_view(); 1673 await get_basket_footer_message(); 1674 1675 resolve(true); 1676 }) 1677 .catch(function (error) { 1678 reject(error); 1679 }).finally(hide_ajax_loader); 1680 }); 1681} 1682 1683 1684async function get_vehicule() { 1685 var csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 1686 var id = jQuery('#panier_select_vehicule').val(); 1687 var vhc_selected = id !== 'autre' ? 'true' : 'false'; 1688 1689 var params = new URLSearchParams(); 1690 params.append('id', id); 1691 params.append('csrf_test_name', csrf_test_name); 1692 params.append('vhc_selected', vhc_selected); 1693 1694 try { 1695 const response = await fetch('/panier_v3/get_vehicule', { 1696 method: 'POST', headers: { 1697 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 1698 }, body: params.toString(), 1699 mode: 'cors', 1700 credentials: 'same-origin' 1701 }); 1702 1703 if (response.ok) { 1704 const vehicule = await response.json(); 1705 1706 jQuery('#numero_serie').removeAttr("value").val(vehicule.numero_serie); 1707 jQuery('#type_carte_grise').removeAttr("value").val(vehicule.carte_grise); 1708 jQuery('#couleur_moto').removeAttr("value").val(vehicule.couleur); 1709 } else { 1710 logDebug('Erreur lors de la requête :', response.statusText); 1711 } 1712 } catch (error) { 1713 logDebug('Erreur lors de la requête :', error); 1714 } 1715} 1716 1717function refresh_compteur_panier(nb_ligne) { 1718 var res_ajout_panier = document.querySelectorAll(".resultat_ajout_panier") 1719 for (var i = 0; i < res_ajout_panier.length; i++) { 1720 res_ajout_panier[i].innerHTML = nb_ligne; 1721 } 1722} 1723 1724// Ajout des écouteurs d'événements pour les boutons 1725 1726window.onload = () => { 1727 if (document.getElementById("next_basket") || document.getElementById("back_basket")) { 1728 init_navigation(); 1729 } 1730 remove_placeholders(); 1731}; 1732 1733function add_placeholders(button) { 1734 button.classList.add("placeholder"); 1735 // button.classList.add("placeholder-dynamique"); 1736 button.classList.add("disabled"); 1737 button.disbaled = true; 1738} 1739function remove_placeholders() { 1740 // Sélectionne tous les boutons avec la classe "placeholder" 1741 const placeholders = document.querySelectorAll("button.placeholder"); 1742 placeholders.forEach(button => { 1743 1744 //Specifique payment 1745 const alertExists = document.querySelector("#basket_payment_alert"); 1746 1747 if (button.id !== "next_basket" || !alertExists) { 1748 button.classList.remove("placeholder"); // Retire la classe 1749 button.classList.remove("disabled"); // Retire la classe 1750 button.disabled = false; // Réactive le bouton 1751 } 1752 }); 1753} 1754function init_navigation() { 1755 if (document.getElementById("next_basket")) { 1756 document.getElementById("next_basket").addEventListener("click", nextStep); 1757 document.getElementById("next_basket").addEventListener("touchstart", nextStep); 1758 } 1759 if (document.getElementById("back_basket")) { 1760 document.getElementById("back_basket").addEventListener("click", previousStep); 1761 document.getElementById("back_basket").addEventListener("touchstart", previousStep); 1762 1763 } 1764} 1765 1766async function validateAddressStep() { 1767 let formIsValid = true; 1768 removeError("adr_errors"); 1769 1770 // ð¹ Validation du formulaire de facturation 1771 if (document.querySelector("#form_adr_fact")) { 1772 await check_tva_intracom(document.querySelector("#form_adr_fact"), "facturation"); 1773 await Promise.all(promises_form_fac); 1774 1775 const formFact = document.querySelector("#form_adr_fact"); 1776 const validFact = validate_form(formFact); 1777 1778 if (!validFact && !document.querySelector("#basket_form_facturation").classList.contains("show")) { 1779 new bootstrap.Collapse("#basket_form_facturation").show(); 1780 } else if (document.querySelector("#basket_form_facturation").classList.contains("show")) { 1781 addError("adr_errors", await trad("_JS_CART_FORM_OPEN")); 1782 form_validation(formFact); 1783 formIsValid = false; 1784 } 1785 } 1786 1787 // ð¹ Validation du formulaire de livraison 1788 if (formIsValid) { 1789 if (document.querySelector("#form_adr_liv")) { 1790 const formLiv = document.querySelector("#form_adr_liv");
1791 const validLiv = validate_form(formLiv); 1792 1793 if (!validLiv && !document.querySelector("#basket_form_livraison").classList.contains("show")) { 1794 new bootstrap.Collapse("#basket_form_livraison").show(); 1795 } else if (document.querySelector("#basket_form_livraison").classList.contains("show")) { 1796 addError("adr_errors", await trad("_JS_CART_FORM_OPEN")); 1797 form_validation(formLiv); 1798 formIsValid = false; 1799 } 1800 } 1801 } 1802 1803 if (formIsValid) { 1804 if (document.querySelector("#div_info_livraison") && !document.querySelector("#div_info_livraison").classList.contains("d-none")) { 1805 document.querySelector("#alert_telephone").classList.add("d-block"); 1806 formIsValid = false; 1807 } 1808 } 1809 1810 return formIsValid; 1811} 1812 1813 1814// ð Vérifie la validité du paiement 1815async function validatePaymentStep() { 1816 let formIsValid = true; 1817 1818 // ð¹ Validation du formulaire d'information 1819 if (document.querySelector("#form_panier_information")) { 1820 formIsValid = validate_form(document.querySelector("#form_panier_information")) && formIsValid; 1821 } 1822 1823 if (formIsValid) { 1824 const form = document.getElementById("form_basket_payment"); 1825 formIsValid = await form_panier_payment(form); 1826 } 1827 return formIsValid; 1828} 1829 1830// ð Effectue la requête AJAX pour passer à l'étape suivante 1831async function submitNextStep(step, maxRetries, retries) { 1832 let csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 1833 const params = new URLSearchParams({ 1834 step: step, 1835 action: "next", 1836 csrf_test_name: csrf_test_name, 1837 }); 1838 1839 // ð¹ Loader timeout pour affichage si délai > 250ms 1840 let loaderTimeout = setTimeout(show_ajax_loader, 200); 1841 1842 if (step === "step_payment") { 1843 // ð¹ Vérifie si la case CGV est présente et ajoute sa valeur 1844 const cgvCheckbox = document.getElementById("checkbox_condition_vente"); 1845 if (cgvCheckbox) { 1846 params.append("cgv_check", cgvCheckbox.checked); 1847 } 1848 1849 // ð¹ Récupère la valeur du bouton radio sélectionné dans le formulaire de paiement 1850 const selectedPayment = document.querySelector("#form_basket_payment [name=choix_payment]:checked"); 1851 if (selectedPayment) { 1852 params.append("payment", selectedPayment.value); 1853 } 1854 } 1855 1856 try { 1857 const response = await fetch_with_retries( 1858 get_protocol_domain_name() + "/panier_v3/navigation", 1859 { 1860 method: 'POST', 1861 headers: { 1862 'Content-Type': 'application/x-www-form-urlencoded', 1863 'X-Requested-With': 'XMLHttpRequest' 1864 }, 1865 body: params.toString(), 1866 mode: 'cors', 1867 credentials: 'same-origin' 1868 }, 1869 maxRetries, 1870 retries 1871 ); 1872 1873 clearTimeout(loaderTimeout); 1874 1875 if (response.ok) { 1876 const responseData = await response.json(); 1877 if (responseData.valid) { 1878 if (responseData.requires_form_submission) { 1879 try { 1880 const submissionResult = await submitGeneratedForm( 1881 responseData.form_action, 1882 responseData.form_fields 1883 ); 1884 } catch (formError) { 1885 logDebug("Erreur lors de la soumission asynchrone du formulaire :", formError); 1886 hide_ajax_loader(); 1887 1888 } 1889 } else if (responseData.path){ 1890 switch (responseData.path) { 1891 case "views_form_google_pay": 1892 const googlePayButton = document.querySelector("#views_form_google_pay #container button"); 1893 if (googlePayButton) { 1894 await transaction_on_progress(); 1895 googlePayButton.click(); 1896 } else { 1897 logDebug("Bouton Google Pay introuvable !"); 1898 } 1899 break; 1900 case "views_form_paypal": 1901 const paypalForm = document.querySelector("#views_form_paypal form"); 1902 if (paypalForm) { 1903 await transaction_on_progress(); 1904 paypalForm.submit(); // ð¹ Soumet automatiquement le formulaire 1905 } else { 1906 logDebug("Formulaire PayPal introuvable !"); 1907 } 1908 break; 1909 case "views_form_bank_hondapl": 1910 const bankLink = document.querySelector("#views_form_bank_hondapl a"); 1911 if (bankLink) { 1912 await transaction_on_progress(); 1913 bankLink.click(); 1914 } else { 1915 logDebug("Lien bancaire introuvable !"); 1916 } 1917 break; 1918 case "views_form_bank_hondaua": 1919 const hondaUaForm = document.querySelector("#views_form_bank_hondaua form"); 1920 if (hondaUaForm) { 1921 try { 1922 await transaction_on_progress(); 1923 hondaUaForm.submit(); 1924 } catch (error) { 1925 logDebug("Impossible de soumettre le formulaire"); 1926 } 1927 } else { 1928 logDebug("Formulaire Honda UA introuvable !"); 1929 } 1930 break; 1931 case "views_form_bank_hondath": 1932 const hondaThForm = document.querySelector("#views_form_bank_hondath form"); 1933 if (hondaThForm) { 1934 try { 1935 await transaction_on_progress(); 1936 hondaThForm.submit(); 1937 } catch (error) { 1938 logDebug("Impossible de soumettre le formulaire"); 1939 } 1940 } else { 1941 logDebug("Formulaire Honda UA introuvable !"); 1942 } 1943 break; 1944 } 1945 } else { 1946 window.location.href = responseData.url; 1947 } 1948 } else { 1949 if (responseData.is_multi_basket) { 1950 if (document.querySelector("#delivery_area_all")) { 1951 await get_delivery_mod_view(); 1952 await load_choix_livr(); 1953 await choix_pts_relais(); 1954 } 1955 } 1956 1957 if (responseData.error_return) { 1958 window.location.reload(); 1959 } 1960 1961 await get_navigation(responseData.msg); 1962 hide_ajax_loader(); 1963 } 1964 } 1965 } catch (error) { 1966 logDebug('Error in submitNextStep : ', error); 1967 hide_ajax_loader(); 1968 clearTimeout(loaderTimeout); 1969 } 1970} 1971 1972async function submitGeneratedForm(formAction, formFields) { 1973 show_ajax_loader(); 1974 let csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 1975 const params = new URLSearchParams({ 1976 csrf_test_name: csrf_test_name, 1977 }); 1978 params.append("type", formFields); 1979 try { 1980 const response = await fetch(get_protocol_domain_name() + formAction, { 1981 headers: { 1982 'Content-Type': 'application/x-www-form-urlencoded', 1983 }, 1984 method: 'POST', 1985 body: params, 1986 mode: 'cors', 1987 credentials: 'same-origin' 1988 }); 1989 if (!response.ok) { 1990 logDebug("Erreur lors de la soumission du formulaire :", response.statusText); 1991 hide_ajax_loader(); 1992 throw new Error('Form submission failed'); 1993 } else { 1994 const responseData = await response.json(); 1995 if (responseData.valid && responseData.url) { 1996 window.location.href = responseData.url; // ð¹ Redirection en JS 1997 } else { 1998 hide_ajax_loader(); 1999 } 2000 } 2001 2002 } catch (error) { 2003 logDebug("Erreur réseau lors de la soumission du formulaire :", error); 2004 hide_ajax_loader(); 2005 throw error; 2006 } 2007}
2008// ð Fonction principale orchestrant les étapes 2009async function nextStep(maxRetries = 5, retries = 0) { 2010 const step = document.querySelector("#step_basket").value; 2011 let formIsValid = true; 2012 2013 if (step === "step_address") { 2014 formIsValid = await validateAddressStep(); 2015 } else if (step === "step_payment") { 2016 show_ajax_loader(); 2017 formIsValid = await validatePaymentStep(); 2018 removeError("payment_open"); 2019 if (document.getElementById("checkbox_condition_vente")) { 2020 removeError("cgv"); 2021 if (!document.getElementById("checkbox_condition_vente").checked) { 2022 addError("cgv",await trad("_NEED_CGV")); 2023 } 2024 } 2025 } else if (step === "step_divers") { 2026 const promises = []; 2027 if (document.querySelector("#form_panier_information")) { 2028 promises.push(submit_panier_information()); 2029 } 2030 if (promises.length > 0) { 2031 await Promise.all(promises); 2032 } 2033 } 2034 if (have_errors() && formIsValid) { 2035 formIsValid = false; 2036 } 2037 if (formIsValid) { 2038 await submitNextStep(step, maxRetries, retries); 2039 } else { 2040 hide_ajax_loader(); 2041 } 2042} 2043 2044// Fonction pour le bouton "Retour" 2045async function previousStep(maxRetries = 5, retries = 0) { 2046 const step = document.querySelector("#step_basket").value; 2047 let csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 2048 2049 const params = new URLSearchParams(); 2050 params.append('step', step); 2051 params.append('action', "previous"); 2052 params.append('csrf_test_name', csrf_test_name); 2053 2054 // Variable de controle de délai 2055 let loaderTimeout 2056 // Démarre le timer pour vérifier si l'utilisateur attend plus de 250ms 2057 loaderTimeout = setTimeout(() => { 2058 show_ajax_loader(); // Affiche le loader si le délai dépasse 250ms 2059 }, 200); 2060 try { 2061 2062 const response = await fetch(get_protocol_domain_name() + "/panier_v3/navigation", { 2063 method: 'POST', headers: { 2064 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 2065 }, body: params.toString(), 2066 mode: 'cors', 2067 credentials: 'same-origin' 2068 }); 2069 2070 // Lorsque la réponse est reçue, on annule le timer et on cache le loader 2071 clearTimeout(loaderTimeout); 2072 2073 if (response.ok) { 2074 const responseData = await response.json(); // Parse the response as JSON 2075 if (responseData.valid) { 2076 window.location.href = responseData.url; 2077 } 2078 } else { 2079 if (retries < maxRetries) { 2080 retries++; 2081 logDebug(`Tentative ${retries} de ${maxRetries}`); 2082 // Réessayer la requête 2083 return nextStep(maxRetries, retries); // Correction : passer les arguments 2084 } else { 2085 throw new Error('Nombre maximal de tentatives atteint'); 2086 } 2087 } 2088 } catch (error) { 2089 logDebug('Error in navigateToNextStep:', error); 2090 clearTimeout(loaderTimeout); 2091 } 2092} 2093 2094async function get_navigation(msg, maxRetries = 5, retries = 0) { 2095 const csrf_test_name = encodeURIComponent(document.querySelector("[name=csrf_test_name]").value); 2096 // const errors = msg; 2097 2098 let errors_list = collectErrors(); // Récupérer les erreurs de la liste ul+ 2099 errors_list = Object.assign({}, errors_list); // Convertir errors_list en objet 2100 2101 // Ajouter les erreurs de msg à errors_list 2102 if (msg) { 2103 for (const key in msg) { 2104 if (msg.hasOwnProperty(key)) { 2105 errors_list[key] = msg[key]; 2106 } 2107 } 2108 } 2109 const errors = JSON.stringify(errors_list); // Convertir la liste complète en JSON 2110 const params = new URLSearchParams(); 2111 const step_basket = document.getElementById("step_basket").value; 2112 params.append('csrf_test_name', csrf_test_name); 2113 params.append('errors', errors); 2114 params.append('step_basket', step_basket); 2115 2116 try { 2117 const response = await fetch(get_protocol_domain_name() + "/panier_v3/ajax_get_navigation_view", { 2118 method: 'POST', headers: { 2119 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 2120 }, body: params, 2121 mode: 'cors', 2122 credentials: 'same-origin' 2123 }); 2124 2125 if (response.ok) { 2126 const text = await response.text(); // Correction : await pour récupérer le texte de la réponse 2127 document.getElementById("basket_navigation").innerHTML = text; 2128 init_navigation(); 2129 remove_placeholders(); 2130 } else { 2131 if (retries < maxRetries) { 2132 retries++; 2133 logDebug("Tentative " + retries + " de " + maxRetries); 2134 // Réessayer la requête 2135 return get_navigation(msg, maxRetries, retries); // Correction : passer les arguments 2136 } else { 2137 throw new Error('Nombre maximal de tentatives atteint'); 2138 } 2139 } 2140 } catch (error) { 2141 logDebug('Error get_navigation:', error); 2142 } 2143} 2144 2145async function choix_pts_relais() { 2146 const choix_pts_relais = document.querySelectorAll('.choix_pts_relais'); 2147 for (let i = 0; i < choix_pts_relais.length; i++) { 2148 choix_pts_relais[i].addEventListener("change", async function () { 2149 try { 2150 const collapse_livraison = document.getElementById('basket_form_livraison'); 2151 const bs_collapse_livraison = new bootstrap.Collapse(collapse_livraison, { 2152 toggle: false 2153 }) 2154 bs_collapse_livraison.hide(); 2155 2156 const num_panier = encodeURIComponent(this.name.split('_')[3]); 2157 await unset_delivery_mode(num_panier); 2158 await load_choix_livr(this); 2159 await get_recapitulatif_basket_view(); 2160 var infos_form = []; 2161 infos_form["collapse"] = false; 2162 await update_both_labels_info(infos_form, infos_form) 2163 removeError("adr_errors"); 2164 2165 } catch (error) { 2166 logDebug('Error choix_pts_relais:', error); 2167 } 2168 }); 2169 } 2170} 2171 2172async function unset_delivery_mode(num_panier = "", maxRetries = 5, retries = 0) { 2173 const csrf_test_name = encodeURIComponent(document.querySelector("[name=csrf_test_name]").value); 2174 const params = new URLSearchParams(); 2175 params.append('csrf_test_name', csrf_test_name); 2176 params.append('num_panier', num_panier); 2177 try { 2178 const response = await fetch(get_protocol_domain_name() + "/panier_v3/u
2178nset_delivery_mode", { 2179 method: 'POST', headers: { 2180 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 2181 }, body: params, 2182 mode: 'cors', 2183 credentials: 'same-origin' 2184 }); 2185 2186 if (response.ok) { 2187 removeError("mode_livraison_error"); 2188 } else { 2189 if (retries < maxRetries) { 2190 retries++; 2191 logDebug("Tentative " + retries + " de " + maxRetries); 2192 // Réessayer la requête 2193 return unset_delivery_mode(num_panier, maxRetries, retries); 2194 } else { 2195 throw new Error('Nombre maximal de tentatives atteint'); 2196 } 2197 } 2198 } catch (error) { 2199 logDebug('Error unset_delivery_mode:', error); 2200 } finally { 2201 2202 } 2203} 2204 2205async function check_delivery_pro() { 2206 const params = new URLSearchParams(); 2207 params.append('csrf_test_name', document.querySelector("[name=csrf_test_name]").value); 2208 2209 const selectedPoint = document.querySelector('.choix_pts_relais:checked'); 2210 if (selectedPoint) { 2211 const idPtsRelais = selectedPoint.id.split('_')[2]; 2212 params.append('id_pts_relais', idPtsRelais); 2213 } 2214 2215 try { 2216 const response = await fetch(get_protocol_domain_name() + '/panier_v3/check_delivery_pro', { 2217 method: 'POST', 2218 headers: { 2219 'Content-Type': 'application/x-www-form-urlencoded', 2220 'X-Requested-With': 'XMLHttpRequest' 2221 }, 2222 body: params, 2223 mode: 'cors', 2224 credentials: 'same-origin' 2225 }); 2226 2227 if (response.ok) { 2228 const result = await response.text(); 2229 console.log('Résultat check_delivery_pro:', result.trim()); 2230 2231 } else { 2232 console.error("Erreur HTTP:", response.status); 2233 } 2234 } catch (error) { 2235 console.error('Erreur fetch check_delivery_pro:', error); 2236 } 2237} 2238 2239 2240async function check_country_is_valid(pays) { 2241 const params = new URLSearchParams(); 2242 params.append('csrf_test_name', encodeURIComponent(document.querySelector("[name=csrf_test_name]").value)); 2243 params.append('pays', encodeURIComponent(pays)); 2244 params.append('direct_request', encodeURIComponent("true")); 2245 removeError("country_blocked"); 2246 removeError("payment_blocked"); 2247 removeError("mode_livraison_error"); 2248 try { 2249 const response = await fetchWithRetries(get_protocol_domain_name() + '/panier_v3/check_country_is_valid', { 2250 method: 'POST', 2251 headers: { 2252 'Content-Type': 'application/x-www-form-urlencoded', 2253 'X-Requested-With': 'XMLHttpRequest' 2254 }, 2255 body: params, 2256 mode: 'cors', 2257 credentials: 'same-origin' 2258 }); 2259 2260 if (response.ok) { 2261 const data = await response.json(); 2262 if (!data["valid"]) { 2263 if (data["msg"]["country_blocked"]) { 2264 addError("country_blocked", data["msg"]["country_blocked"]); 2265 } 2266 if (data["msg"]["payment_blocked"]) { 2267 addError("payment_blocked", data["msg"]["payment_blocked"]); 2268 } 2269 2270 add_placeholders(document.querySelector("#next_basket")); 2271 } else { 2272 remove_placeholders(); 2273 } 2274 return data; 2275 } 2276 2277 } catch (error) { 2278 logDebug('Erreur:', error); 2279 return { valid: false, msg: { error: "Erreur de communication avec le serveur." } }; 2280 } 2281} 2282 2283async function check_delivery_pro_usage(id_choix_pts_relais) { 2284 try { 2285 const response = await check_delivery_pro(); 2286 2287 // Votre logique de traitement basée sur la réponse ici 2288 if (response === "") { 2289 document.querySelector("[name=entreprise]").required = true; 2290 if (document.querySelector("[name=entreprise]").value === "") { 2291 open_close_form_adresse_livraison("open"); 2292 } 2293 } else { 2294 document.querySelector("[name=entreprise]").required = false; 2295 } 2296 2297 } catch (error) { 2298 logDebug('Error during check_delivery_pro:', error); 2299 } 2300} 2301 2302async function check_exclude_area(id_choix_pts_relais, cp, pays, selected_value, maxRetries = 5, retries = 0) { 2303 2304 let response = false; 2305 const params = new URLSearchParams(); 2306 params.append('csrf_test_name', document.querySelector("[name=csrf_test_name]").value); 2307 params.append('code_postal', cp); 2308 params.append('pays', pays); 2309 params.append('direct_request', 'true'); 2310 2311 params.append('id_pts_relais', id_choix_pts_relais); 2312 2313 setTimeout(async () => { 2314 try { 2315 const ajax_check_exclude_area = await fetch(get_protocol_domain_name() + "/panier_v3/cp_check_exclude_area", { 2316 method: 'POST', headers: { 2317 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'
2318 }, body: params, 2319 mode: 'cors', 2320 credentials: 'same-origin' 2321 }); 2322 2323 if (ajax_check_exclude_area.ok) { 2324 response = await ajax_check_exclude_area.text(); 2325 } else { 2326 if (retries < maxRetries) { 2327 retries++; 2328 logDebug("Tentative " + retries + " de " + maxRetries); 2329 // Réessayer la requête 2330 return check_exclude_area(id_choix_pts_relais, cp, pays, selected_value, maxRetries, retries); 2331 } else { 2332 throw new Error('Nombre maximal de tentatives atteint'); 2333 } 2334 } 2335 } catch (error) { 2336 logDebug('Error:', error); 2337 } finally { 2338 2339 } 2340 }, 1000); // Attendre 1 seconde avant d'envoyer la requête 2341 2342 return response; 2343} 2344 2345function check_adresse_pr(elem) { 2346 var bsCollapse = new bootstrap.Collapse(elem, { 2347 toggle: false 2348 }) 2349 bsCollapse.show(); 2350} 2351 2352function delete_sms_colisimo() { 2353 var ajax_request_sms_field = new XMLHttpRequest(); 2354 ajax_request_sms_field.open("GET", get_protocol_domain_name() + "/panier_v3/delete_mobile_coliship", true); 2355 ajax_request_sms_field.setRequestHeader('Content-Type', 'application/json'); 2356 ajax_request_sms_field.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 2357 ajax_request_sms_field.send(); 2358} 2359 2360async function check_pts_relais(maxRetries = 5, retries = 0) { 2361 try { 2362 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 2363 const params = 'csrf_test_name=' + encodeURIComponent(csrf_test_name) + '&pays=' + encodeURIComponent(document.querySelector("#pays_facturation").value); 2364 2365 const response = await fetch(get_protocol_domain_name() + "/panier_v3/have_pts_relais", { 2366 method: 'POST', headers: { 2367 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 2368 }, body: params, 2369 mode: 'cors', 2370 credentials: 'same-origin' 2371 }); 2372 2373 if (response.ok) { 2374 const data = await response.text(); 2375 if (data === "true") { 2376 await get_delivery_mod_view(); 2377 await load_choix_livr(); 2378 await choix_pts_relais(); 2379 await form_panier_mobile_coliship(); 2380 } else { 2381 document.querySelector("#delivery_area_all").innerHTML = ""; 2382 } 2383 } else { 2384 if (retries < maxRetries) { 2385 retries++; 2386 logDebug("Tentative " + retries + " de " + maxRetries); 2387 // Réessayer la requête 2388 return check_pts_relais(maxRetries, retries); 2389 } else { 2390 throw new Error('Nombre maximal de tentatives atteint'); 2391 } 2392 } 2393 } catch (error) { 2394 logDebug('Erreur lors de la requête :', error); 2395 } 2396} 2397 2398 2399async function get_delivery_mod_view() { 2400 try { 2401 const response = await fetchWithRetries(get_protocol_domain_name() + "/panier_v3/get_delivery_mod_view", { 2402 method: 'GET', headers: { 2403 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' 2404 }, 2405 mode: 'cors', 2406 credentials: 'same-origin' 2407 }); 2408 2409 if (response.ok) { 2410 const data = await response.text(); 2411 if (document.getElementById("delivery_area_all").innerHTML !== data) { 2412 document.getElementById("delivery_area_all").innerHTML = data; 2413 button_collapse_delivery_mod(); 2414 } 2415 } 2416 } catch (error) { 2417 logDebug('Erreur lors de la requête :', error); 2418 } 2419} 2420 2421async function get_recapitulatif_basket_view(maxRetries = 5, retries = 0) { 2422 try { 2423 const response = await fetchWithRetries(get_protocol_domain_name() + "/panier_v3/get_recapitulatif_basket", { 2424 method: 'GET', headers: { 2425 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' 2426 }, 2427 mode: 'cors', 2428 credentials: 'same-origin' 2429 }); 2430 2431 if (response.ok) { 2432 const data = await response.text(); 2433 const basketRecapitulatif = document.querySelector("#basket_recapitulatif"); 2434 if (basketRecapitulatif.innerHTML !== data) { 2435 basketRecapitulatif.innerHTML = data; 2436 } 2437 await form_promo(); 2438 await form_delete_promo(); 2439 save_basket() 2440 } 2441 } catch (error) { 2442 logDebug('Erreur lors de la requête :', error); 2443 } 2444} 2445 2446async function get_basket_message($pays, maxRetries = 5, retries = 0) { 2447 2448 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 2449 const params = new URLSearchParams(); 2450 params.append('csrf_test_name', csrf_test_name); 2451 params.append('pays', $pays); 2452 try { 2453 const response = await fetch(get_protocol_domain_name() + "/panier_v3/get_basket_message", { 2454 method: 'POST', 2455 headers: { 2456 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'
2457 }, 2458 body: params, 2459 mode: 'cors', 2460 credentials: 'same-origin' 2461 }); 2462 2463 if (response.ok) { 2464 const data = await response.text(); 2465 const basketMessage = document.querySelector("#basket_message"); 2466 if (basketMessage.innerHTML !== data) { 2467 basketMessage.innerHTML = data; 2468 } 2469 } else { 2470 if (retries < maxRetries) { 2471 retries++; 2472 logDebug("Tentative " + retries + " de " + maxRetries); 2473 // Réessayer la requête 2474 return get_basket_message($pays, maxRetries, retries); 2475 } else { 2476 throw new Error('Nombre maximal de tentatives atteint'); 2477 } 2478 } 2479 } catch (error) { 2480 logDebug('Erreur lors de la requête :', error); 2481 } 2482} 2483async function get_basket_footer_message() { 2484 2485 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 2486 const params = new URLSearchParams(); 2487 params.append('csrf_test_name', csrf_test_name); 2488 try { 2489 const response = await fetchWithRetries(get_protocol_domain_name() + "/panier_v3/get_basket_footer_message", { 2490 method: 'POST', 2491 headers: { 2492 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 2493 }, 2494 body: params, 2495 mode: 'cors', 2496 credentials: 'same-origin' 2497 }); 2498 2499 if (response.ok) { 2500 const data = await response.text(); 2501 const basketMessage = document.querySelector("#basket_footer_message"); 2502 if (basketMessage.innerHTML !== data) { 2503 basketMessage.innerHTML = data; 2504 } 2505 } 2506 } catch (error) { 2507 logDebug('Erreur lors de la requête :', error); 2508 } 2509} 2510 2511async function check_phone_missing() { 2512 var divMobile = document.querySelector("#div_info_livraison"); 2513 if (!divMobile) { 2514 return; 2515 } 2516 divMobile.classList.add("d-none"); 2517 2518 try { 2519 const response = await fetchWithRetries(get_protocol_domain_name() + "/panier_v3/check_mobile_coliship", { 2520 method: 'GET', headers: { 2521 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' 2522 }, 2523 mode: 'cors', 2524 credentials: 'same-origin' 2525 }); 2526 2527 if (response.ok) { 2528 const responseData = await response.text(); 2529 if (responseData === "false") { 2530 divMobile.classList.remove("d-none"); 2531 if (document.querySelector('#choix_livraison_mobile') && document.querySelector('#choix_livraison_mobile').value == "") { 2532 const JS_collapse_form_info_livraison = document.querySelector("#form_info_livraison"); 2533 const bsCollapse = new bootstrap.Collapse(JS_collapse_form_info_livraison, { 2534 toggle: false 2535 }); 2536 bsCollapse.show(); 2537 } 2538 } 2539 } 2540 } catch (error) { 2541 logDebug('Error check_phone_missing:', error); 2542 } 2543} 2544 2545async function load_choix_livr(choice) { 2546 2547 show_ajax_loader(); 2548 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 2549 let selected_value_error = false; 2550 let selected_value = ""; 2551 let id_choix_delivery_mod = ""; 2552 if (choice) { 2553 selected_value = choice.value; 2554 id_choix_delivery_mod = choice.id.split('_')[2]; 2555 } 2556 2557 if (selected_value !== "") { 2558 await get_cache_current_delivery_address(); 2559 2560 let params = 'csrf_test_name=' + encodeURIComponent(csrf_test_name); 2561 params += '&ad=' + encodeURIComponent(document.querySelector("#ad_livraison").value) 2562 params += '&ville=' + encodeURIComponent(document.querySelector("#ville_livraison").value) 2563 params += '&cp=' + encodeURIComponent(document.querySelector("#cp_livraison").value) 2564 params += '&id_choix_delivery_mod=' + encodeURIComponent(id_choix_delivery_mod) 2565 if (document.querySelector("#div_info_livraison")) { 2566 let divMobile = document.querySelector("#div_info_livraison"); 2567 if (!divMobile.classList.contains("d-none")) { 2568 divMobile.classList.add("d-none"); 2569 } 2570 } 2571 2572 const delivery_area = choice.closest(".delivery_area"); 2573 let collapses_points_relais = delivery_area.querySelectorAll(".collapse"); 2574 collapses_points_relais.forEach(function (element) { 2575 if (element.classList.contains("collapse_sms")) { 2576 return; 2577 } 2578 var bscollapse_element = new bootstrap.Collapse(element, { 2579 toggle: false 2580 }) 2581 element.innerHTML = ""; 2582 bscollapse_element.hide(); 2583 }); 2584 2585 let mycollapse_point_relais = document.getElementById('collapse_point_relais_' + id_choix_delivery_mod) 2586 let bscollapse_point_relais = new bootstrap.Collapse(mycollapse_point_relais, { 2587 toggle: false 2588 }) 2589 2590 let cp_exclude_area = document.querySelector("#cp_livraison").value; 2591 let pays_exclude_area = document.querySelector("#pays_livraison").value 2592 let exclude_area = check_exclude_area(id_choix_delivery_mod, cp_exclude_area, pays_exclude_area, selected_value) 2593 2594 const promises = []; 2595 2596 // promises.push(check_delivery_pro_usage(id_choix_delivery_mod)); 2597 2598 switch (selected_value) { 2599 //on declenche la fonction ajax et on recharge la page sur succes 2600 case 'Formulaire': 2601 promises.push(set_choice_domicile(choice)); 2602 // promises.push(get_cache_current_delivery_address()); 2603 2604 break; 2605 //on deroule la liste des points 2606 case 'Autre': 2607 bscollapse_point_relais.show(); 2608 await get_colissimo_pts_relais(mycollapse_point_relais, params); 2609 await check_phone_missing(); 2610 submit_choix_relais() 2611 2612 break; 2613 /****** Display colissimo points ******/ 2614 case 'Colissimo': 2615 bscollapse_point_relais.show(); 2616 promises.push(load_widget_colissimo_div(mycollapse_point_relais, id_choix_delivery_mod));
2617 promises.push(widget_colissimo(choice, mycollapse_point_relais, id_choix_delivery_mod, csrf_test_name)); 2618 2619 delete_sms_colisimo(); 2620 submit_choix_relais() 2621 2622 break; 2623 /****** Display mondial relay points ******/ 2624 case 'MR': 2625 bscollapse_point_relais.show(); 2626 widget_mondial_relay(id_choix_delivery_mod); 2627 break; 2628 /****** Display DPD points ******/ 2629 case 'DPD': 2630 bscollapse_point_relais.show(); 2631 promises.push(fetchPointsRelaisDPD(choice, mycollapse_point_relais, id_choix_delivery_mod, exclude_area)); 2632 2633 submit_choix_relais() 2634 2635 break; 2636 2637 } 2638 2639 await Promise.all(promises); 2640 2641 if (!selected_value_error) { 2642 set_ajax_input_error("cp_livraison", ""); 2643 set_ajax_input_error("entreprise_livraison", ""); 2644 if (exclude_area === "") { 2645 if (exclude_area === "") { 2646 set_ajax_input_error("cp_livraison",await trad("_CP_EXCLUDE_AREA_ERROR")); 2647 } 2648 } 2649 } 2650 } 2651 hide_ajax_loader(); 2652} 2653 2654button_collapse_delivery_mod(); 2655 2656function button_collapse_delivery_mod() { 2657 const buttons = document.querySelectorAll(".button_collapse_delivery_mod"); 2658 if (buttons) { 2659 buttons.forEach(button => { 2660 button.addEventListener('click', async function () { 2661 const num_panier = encodeURIComponent(this.id.split('_')[4]); 2662 const elementName = "choix_pts_relais_" + num_panier; 2663 const checkedElement = document.querySelector("[name='" + elementName + "']:checked"); 2664 try { 2665 await load_choix_livr(checkedElement); 2666 await unset_delivery_mode(num_panier); 2667 await choix_pts_relais(); 2668 2669 // await set_identic_livraison_to_facturation(); 2670 } catch (error) { 2671 logDebug('Erreur lors de l\'exécution des fonctions asynchrones :', error); 2672 } 2673 }); 2674 }); 2675 } 2676} 2677 2678submit_choix_relais() 2679 2680function submit_choix_relais() { 2681 const radioButtons = document.querySelectorAll(".radio_choix_pr"); 2682 if (radioButtons.length > 0) { 2683 radioButtons.forEach(button => { 2684 2685 button.addEventListener('click', function () { 2686 // Soumettre le formulaire parent 2687 const form = this.closest("form"); 2688 if (form) { 2689 form.requestSubmit(); // Utiliser requestSubmit pour éviter de bypass le submit event listener 2690 } 2691 }); 2692 }); 2693 } 2694} 2695 2696// DOMICILE 2697async function set_choice_domicile(choice) { 2698 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 2699 const id_delivery_mode = encodeURIComponent(choice.id.split('_')[2]); 2700 const num_panier = encodeURIComponent(choice.name.split('_')[3]); 2701 2702 const params = new URLSearchParams(); 2703 params.append('csrf_test_name', csrf_test_name); 2704 params.append('id_delivery_mode', id_delivery_mode); 2705 params.append('num_panier', num_panier); 2706 2707 try { 2708 const response = await fetchWithRetries(get_protocol_domain_name() + "/panier_v3/choix_livraison_domicile", { 2709 method: 'POST', headers: { 2710 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 2711 }, body: params, 2712 mode: 'cors', 2713 credentials: 'same-origin' 2714 }); 2715 2716 if (response.ok) { 2717 const mycollapse_views_panier_livraison = document.getElementById('views_panier_livraison_' + num_panier); 2718 const bscollapse_views_panier_livraison = new bootstrap.Collapse(mycollapse_views_panier_livraison, { 2719 toggle: false 2720 }); 2721 bscollapse_views_panier_livraison.hide(); 2722 2723 // await update_labels_info_adresse_livraison() 2724 let promises = []; 2725 2726 promises.push(update_labels_info_adresses("/panier_v3/get_basket_livraison_view")); 2727 promises.push(update_delivery_area_info_adresse_livraison(num_panier)); 2728 promises.push(update_form_adresse_livraison()); 2729 promises.push(get_recapitulatif_basket_view()); 2730 2731 await Promise.all(promises); 2732 2733 } 2734 } catch (error) { 2735 // Gérer les erreurs 2736 logDebug('Erreur lors de la requête :', error); 2737 } 2738} 2739 2740// AUTRE (pts relais Colissimo) 2741async function get_colissimo_pts_relais(collapse, params, maxRetries = 5, retries = 0) { 2742 try { 2743 show_ajax_loader(); 2744 const response = await fetch(get_protocol_domain_name() + "/panier_v3/geoloc_relais", { 2745 method: 'POST', headers: { 2746 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'
2747 }, body: params, 2748 mode: 'cors', 2749 credentials: 'same-origin' 2750 }); 2751 2752 if (response.ok) { 2753 const responseData = await response.text(); 2754 collapse.innerHTML = responseData; 2755 form_panier_pts_relais_Colissimo_validate(); 2756 2757 // await event_colissimo(params); 2758 // delete_sms_colisimo(); 2759 } else { 2760 if (retries < maxRetries) { 2761 retries++; 2762 logDebug("Tentative " + retries + " de " + maxRetries); 2763 // Réessayer la requête 2764 return get_colissimo_pts_relais(params, maxRetries, retries); 2765 } else { 2766 throw new Error('Nombre maximal de tentatives atteint'); 2767 } 2768 } 2769 } catch (error) { 2770 logDebug('Error get_colissimo_pts_relais:', error); 2771 } finally { 2772 hide_ajax_loader(); 2773 } 2774} 2775 2776function form_panier_pts_relais_Colissimo_validate() { 2777 const form = document.querySelector("#form_panier_pts_relais_Colissimo_validate"); 2778 const delivery_area = form.closest('.delivery_area'); 2779 if (form) { 2780 form.addEventListener("submit", async function (event) { 2781 event.preventDefault(); 2782 const collectPoint = form.querySelector('[name=choix_relais]:checked'); 2783 if (collectPoint) { 2784 const csrf_test_name = form.querySelector("[name=csrf_test_name]").value; 2785 const collectPoint_data = { 2786 id: collectPoint.value, 2787 address: form.querySelector(`#${collectPoint.id}_ad`).value, 2788 postal_code: form.querySelector(`#${collectPoint.id}_postal_code`).value, 2789 shop_name: form.querySelector(`#${collectPoint.id}_shop_name`).value, 2790 city: form.querySelector(`#${collectPoint.id}_city`).value, 2791 distance: form.querySelector(`#${collectPoint.id}_distance`).value 2792 }; 2793 2794 const id_delivery_mode = encodeURIComponent(delivery_area.querySelector('.choix_pts_relais:checked').id.split('_')[2]); 2795 const num_panier = encodeURIComponent(delivery_area.querySelector('.choix_pts_relais:checked').name.split('_')[3]); 2796 2797 const params = new URLSearchParams(); 2798 params.append('csrf_test_name', csrf_test_name); 2799 params.append('collectPoint', JSON.stringify(collectPoint_data)); 2800 params.append('id_delivery_mode', id_delivery_mode); 2801 params.append('num_panier', num_panier); 2802 2803 await validate_point_relais(num_panier, params, 'collapse_point_relais_' + id_delivery_mode); 2804 2805 } 2806 }); 2807 } 2808} 2809 2810// WIDGET COLISSIMO 2811async function load_widget_colissimo_div(mycollapse_point_relais, id_choix_delivery_mod, maxRetries = 5, retries = 0) { 2812 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 2813 2814 if (mycollapse_point_relais) { 2815 2816 const paramsDPD = new URLSearchParams(); 2817 paramsDPD.append('csrf_test_name', encodeURIComponent(csrf_test_name)); 2818 paramsDPD.append('meta_shop_delivery_mod_id', encodeURIComponent(id_choix_delivery_mod)); 2819 try { 2820 const response = await fetch(get_protocol_domain_name() + "/panier_v3/get_widget_div", { 2821 method: 'POST', headers: { 2822 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 2823 }, body: paramsDPD, 2824 mode: 'cors', 2825 credentials: 'same-origin' 2826 }); 2827 2828 if (response.ok) { 2829 const data = await response.text(); 2830 mycollapse_point_relais.innerHTML = data; 2831 } else { 2832 if (retries < maxRetries) { 2833 retries++; 2834 logDebug("Tentative " + retries + " de " + maxRetries); 2835 // Réessayer la requête 2836 return load_widget_colissimo_div(mycollapse_point_relais, id_choix_delivery_mod, maxRetries, retries); 2837 } else { 2838 throw new Error('Nombre maximal de tentatives atteint'); 2839 } 2840 } 2841 2842 } catch (error) { 2843 logDebug('Error:', error); 2844 } 2845 } 2846} 2847 2848async function widget_colissimo(choice, mycollapse_point_relais, id_choix_delivery_mod, csrf_test_name, maxRetries = 5, retries = 0) { 2849 if (document.querySelector("#widget-container_" + id_choix_delivery_mod).innerHTML === "") { 2850 const form_livraison = document.querySelector("#form_adr_liv"); 2851 2852 const ad = form_livraison.querySelector("[name=ad]").value; 2853 const cp = form_livraison.querySelector("[name=cp]").value; 2854 const ville = form_livraison.querySelector("[name=ville]").value; 2855 const params = new URLSearchParams(); 2856 params.append('csrf_test_name', csrf_test_name); 2857 try { 2858 const response = await fetch(get_protocol_domain_name() + "/panier_v3/colissimo_api_auth", { 2859 method: 'POST', headers: { 2860 'Content-Type': 'application/x-www-form-urlencoded' 2861 }, body: params, 2862 mode: 'cors', 2863 credentials: 'same-origin' 2864 }); 2865 2866 if (response.ok) { 2867 const data = await response.text(); 2868 if (data) { 2869 jQuery.ajax({ 2870 type: "GET", 2871 url: "https://ws.colissimo.fr/widget-point-retrait/resources/js/jquery.plugin.colissimo.min.js", 2872 dataType: "script", 2873 success: function () { 2874 jQuery('#widget-container_' + id_choix_delivery_mod).frameColissimoOpen({
2875 "ceLang": "fr", 2876 "callBackFrame": function (collectPoint) { 2877 updatePointRetraitColissimo(collectPoint, choice); 2878 }, 2879 "URLColissimo": "https://ws.colissimo.fr", 2880 "ceCountryList": "FR", 2881 "ceCountry": "FR", 2882 "dyPreparationTime": "1", 2883 "ceAddress": ad, 2884 "ceZipCode": cp, 2885 "ceTown": ville, 2886 "token": data 2887 }); 2888 } 2889 }); 2890 2891 } 2892 } else { 2893 if (retries < maxRetries) { 2894 retries++; 2895 logDebug("Tentative " + retries + " de " + maxRetries); 2896 // Réessayer la requête 2897 return widget_colissimo(choice, csrf_test_name, maxRetries, retries); 2898 } else { 2899 throw new Error('Nombre maximal de tentatives atteint'); 2900 } 2901 } 2902 } catch (error) { 2903 logDebug 2904 } 2905 } 2906} 2907 2908async function updatePointRetraitColissimo(collectPoint, choice) { 2909 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 2910 const params = new URLSearchParams(); 2911 const id_delivery_mode = encodeURIComponent(choice.id.split('_')[2]); 2912 const num_panier = encodeURIComponent(choice.name.split('_')[3]); 2913 2914 params.append('csrf_test_name', csrf_test_name); 2915 params.append('collectPoint', JSON.stringify(collectPoint)); 2916 params.append('id_delivery_mode', id_delivery_mode); 2917 2918 try { 2919 const response = await fetch(get_protocol_domain_name() + "/panier_v3/ajout_panier_colissimo", { 2920 method: 'POST', headers: { 2921 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 2922 }, body: params, 2923 mode: 'cors', 2924 credentials: 'same-origin' 2925 }); 2926 2927 if (!response.ok) { 2928 throw new Error('Network response was not ok'); 2929 } 2930 2931 // await update_form_adresse_livraison(); 2932 2933 await update_delivery_area_info_adresse_livraison(num_panier); 2934 button_collapse_delivery_mod(); 2935 await get_recapitulatif_basket_view(); 2936 2937 } catch (error) { 2938 logDebug('Error updatePointRetraitColissimo:', error); 2939 } finally { 2940 2941 } 2942} 2943 2944// WIDGET MONDIAL RELAY 2945function widget_mondial_relay(id_delivery_mode, maxAttempts = 5, currentAttempt = 1) { 2946 if (currentAttempt > maxAttempts) { 2947 logDebug('Maximum number of attempts reached. Unable to load ParcelShopPicker.'); 2948 return; 2949 } 2950 2951 var key = "CC22LZIZ"; 2952 if (key !== "") { 2953 2954 2955 var cp = document.querySelector("#cp").value; 2956 var ville = document.querySelector("#ville").value; 2957 var pays = document.querySelector("#pays_livraison").value; 2958 var p = "FR"; 2959 switch (pays) { 2960 case 'FRANCE' : 2961 p = "FR"; 2962 break; 2963 case 'BELGIQUE' : 2964 p = "BE"; 2965 break; 2966 case 'DUTSCHLAND' : 2967 p = "DE"; 2968 break; 2969 case 'NEDERLANDS' : 2970 p = "NL"; 2971 break; 2972 default: 2973 logDebug("Aucun points relais pour ce pays"); 2974 } 2975 2976 jQuery.ajax({ 2977 type: "GET", 2978 url: "https://widget.mondialrelay.com/parcelshop-picker/jquery.plugin.mondialrelay.parcelshoppicker.min.js", 2979 dataType: "script", 2980 async: true, 2981 success: function () { 2982 if (document.querySelector(".MR-Widget")) { 2983 jQuery("#Zone_Widget").trigger("MR_SetParams", { 2984 Country: p, City: ville, Postcode: cp, AllowedCountries: p 2985 }); 2986 jQuery("#Zone_Widget").trigger("MR_DoSearch", [cp, p]); 2987 jQuery("#Zone_Widget").trigger("MR_RebindMap") 2988 } else { 2989 jQuery("#Zone_Widget").MR_ParcelShopPicker({ 2990 Target: "#Target_Widget", 2991 Brand: key, 2992 Country: p, 2993 AllowedCountries: p, 2994 City: ville, 2995 PostCode: cp, 2996 NbResults: 10, 2997 Responsive: true, 2998 MapScrollWheel: true, 2999 OnParcelShopSelected: confirmPointRetraitMondial 3000 }); 3001 } 3002 3003 var elem = document.querySelector("#collapse_point_relais_" + id_delivery_mode); 3004 check_adresse_pr(elem); 3005 }, 3006 error: function (xhr, status, error) { 3007 logDebug('Error loading ParcelShopPicker:', error); 3008 // Retry the request 3009 widget_mondial_relay(maxAttempts, currentAttempt + 1); 3010 } 3011 }); 3012 3013 } 3014} 3015 3016function confirmPointRetraitMondial(collectPoint) { 3017 var collectPointInfos = document.querySelector("#collectPointInfos"); 3018 if (collectPointInfos.classList.contains("d-none")) { 3019 collectPointInfos.classList.remove("d-none"); 3020 collectPointInfos.classList.add("d-block"); 3021 }
3022 jQuery('#confirmCollectPoint').data("collectPoint", collectPoint); 3023 jQuery('#collectPointName').html(collectPoint.Nom); 3024 jQuery('#collectPointAdress').html(collectPoint.Adresse1); 3025 jQuery('#collectPointCity').html(collectPoint.CP + ' - ' + collectPoint.Ville); 3026 3027 var confirmCollectPoint = document.querySelector("#confirmCollectPoint"); 3028 if (confirmCollectPoint.classList.contains("d-none")) { 3029 confirmCollectPoint.classList.remove("d-none"); 3030 confirmCollectPoint.classList.add("d-block"); 3031 } 3032 // shipping_adress_scroll(); 3033} 3034 3035// Récupère les points DPD 3036async function fetchPointsRelaisDPD(choice, mycollapse_point_relais, id_choix_pts_relais, exclude_area, maxRetries = 5, retries = 0) { 3037 const form_livraison = document.querySelector("#form_adr_liv"); 3038 const csrf_test_name = form_livraison.querySelector("[name=csrf_test_name]").value; 3039 const adresse = form_livraison.querySelector("[name=ad]").value; 3040 const cp = form_livraison.querySelector("[name=cp]").value; 3041 const ville = form_livraison.querySelector("[name=ville]").value; 3042 const pays = form_livraison.querySelector("#pays_livraison").value; 3043 3044 if (mycollapse_point_relais) { 3045 if (!adresse || !cp || !ville || !pays) { 3046 selected_value_error = true; 3047 } else { 3048 3049 const paramsDPD = new URLSearchParams(); 3050 paramsDPD.append('csrf_test_name', encodeURIComponent(csrf_test_name)); 3051 paramsDPD.append('address', encodeURIComponent(adresse)); 3052 paramsDPD.append('code_postal', encodeURIComponent(cp)); 3053 paramsDPD.append('city', encodeURIComponent(ville)); 3054 paramsDPD.append('pays', encodeURIComponent(pays)); 3055 3056 paramsDPD.append('id_pts_relais', encodeURIComponent(id_choix_pts_relais)); 3057 3058 try { 3059 const response = await fetch(get_protocol_domain_name() + "/panier_v3/get_points_dpd", { 3060 method: 'POST', headers: { 3061 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 3062 }, body: paramsDPD, 3063 mode: 'cors', 3064 credentials: 'same-origin' 3065 }); 3066 3067 if (response.ok) { 3068 const data = await response.text(); 3069 if (exclude_area) { 3070 mycollapse_point_relais.innerHTML = data; 3071 await form_panier_pts_relais_DPD_validate(choice); 3072 submit_choix_relais() 3073 3074 } 3075 } else { 3076 if (retries < maxRetries) { 3077 retries++; 3078 logDebug("Tentative " + retries + " de " + maxRetries); 3079 // Réessayer la requête 3080 return fetchPointsRelaisDPD(choice, id_choix_pts_relais, exclude_area, maxRetries, retries); 3081 } else { 3082 throw new Error('Nombre maximal de tentatives atteint'); 3083 } 3084 } 3085 3086 } catch (error) { 3087 logDebug('Error:', error); 3088 } 3089 } 3090 } 3091} 3092 3093async function form_panier_pts_relais_DPD_validate(choice) { 3094 const form = document.querySelector("#form_panier_pts_relais_DPD_validate"); 3095 if (form) { 3096 form.addEventListener("submit", async function (event) { 3097 event.preventDefault(); 3098 const collectPoint = form.querySelector('[name=choix_relais]:checked'); 3099 if (collectPoint) { 3100 const csrf_test_name = form.querySelector("[name=csrf_test_name]").value; 3101 const id_delivery_mode = encodeURIComponent(choice.id.split('_')[2]); 3102 const num_panier = encodeURIComponent(choice.name.split('_')[3]); 3103 3104 const collectPoint_data = { 3105 id: collectPoint.value, 3106 address: form.querySelector(`#${collectPoint.id}_ad`).value, 3107 postal_code: form.querySelector(`#${collectPoint.id}_postal_code`).value, 3108 shop_name: form.querySelector(`#${collectPoint.id}_shop_name`).value, 3109 city: form.querySelector(`#${collectPoint.id}_city`).value, 3110 distance: form.querySelector(`#${collectPoint.id}_distance`).value 3111 }; 3112 3113 const params = new URLSearchParams(); 3114 params.append('csrf_test_name', csrf_test_name); 3115 params.append('collectPoint', JSON.stringify(collectPoint_data)); 3116 params.append('id_delivery_mode', id_delivery_mode); 3117 params.append('num_panier', num_panier); 3118 await validate_point_relais(num_panier, params, 'collapse_point_relais_' + id_delivery_mode); 3119 } 3120 }); 3121 } 3122} 3123 3124async function validate_point_relais(num_panier, params, collapse) { 3125 show_ajax_loader(); 3126 try { 3127 const response = await fetch(get_protocol_domain_name() + "/panier_v3/ajout_panier_point_relais", { 3128 method: 'POST', headers: { 3129 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'
3130 }, body: params, 3131 mode: 'cors', 3132 credentials: 'same-origin' 3133 }); 3134 3135 if (!response.ok) { 3136 throw new Error('Network response was not ok'); 3137 } 3138 3139 const infos_form = { 3140 "identic": false 3141 }; 3142 await update_labels_info_adresses("/panier_v3/get_basket_livraison_view", infos_form) 3143 3144 disabled_inputs_form_adresse_livraison(true); 3145 await update_delivery_area_info_adresse_livraison(num_panier); 3146 button_collapse_delivery_mod(); 3147 await get_recapitulatif_basket_view(); 3148 3149 removeError("mode_livraison_error"); 3150 3151 const mycollapse_views_panier_livraison = document.getElementById('views_panier_livraison_' + num_panier); 3152 const bscollapse_views_panier_livraison = new bootstrap.Collapse(mycollapse_views_panier_livraison, { 3153 toggle: false 3154 }); 3155 bscollapse_views_panier_livraison.show(); 3156 3157 const mycollapse_point_relais = document.getElementById(collapse); 3158 const bscollapse_point_relais_DPD = new bootstrap.Collapse(mycollapse_point_relais, { 3159 toggle: false 3160 }); 3161 bscollapse_point_relais_DPD.hide(); 3162 3163 } catch (error) { 3164 logDebug('Error form_panier_pts_relais_validate:', error); 3165 } finally { 3166 hide_ajax_loader(); 3167 } 3168} 3169 3170/////////////////////////////////////////////////////////////////////////////// 3171 3172 3173 3174function collectErrors() { 3175 const errorsList = document.getElementById("basket_errors_list"); 3176 const errors = []; 3177 3178 if (errorsList) { 3179 const errorItems = errorsList.querySelectorAll("li"); 3180 errorItems.forEach(item => { 3181 errors[item.id] = item.textContent.trim(); 3182 }); 3183 } 3184 3185 return errors; 3186} 3187 3188function addError(id, message) { 3189 if (document.getElementById("step_errors")) { 3190 const ul = document.querySelector('#step_errors ul'); 3191 const li = document.createElement('li'); 3192 li.id = id; 3193 li.textContent = message; 3194 ul.appendChild(li); 3195 3196 // Assurer que le conteneur d'erreurs est visible 3197 document.getElementById('step_errors').classList.remove('d-block'); 3198 document.getElementById('step_errors').classList.add('d-block'); 3199 document.getElementById('step_errors').classList.remove('d-none'); 3200 } 3201} 3202 3203function removeError(id) { 3204 if (document.getElementById("step_errors")) { 3205 const li = document.getElementById(id); 3206 if (li) { 3207 li.remove(); 3208 3209 // Si le ul est vide, cacher le conteneur des erreurs 3210 const ul = document.querySelector('#step_errors ul'); 3211 if (ul.children.length === 0) { 3212 document.getElementById('step_errors').classList.remove('d-block'); 3213 document.getElementById('step_errors').classList.add('d-none'); 3214 } 3215 } 3216 } 3217} 3218function removeAllError() { 3219 if (document.getElementById("step_errors")) { 3220 const ul = document.querySelector('#step_errors ul'); 3221 3222 // Si le <ul> existe et contient des erreurs, on les supprime toutes 3223 if (ul && ul.children.length > 0) { 3224 while (ul.firstChild) { 3225 ul.firstChild.remove(); 3226 } 3227 3228 if (ul.children.length === 0) { 3229 document.getElementById('step_errors').classList.remove('d-block'); 3230 document.getElementById('step_errors').classList.add('d-none'); 3231 } 3232 } 3233 } 3234} 3235function have_errors() { 3236 let error = false; 3237 if (document.getElementById("step_errors")) { 3238 if (document.getElementById("step_errors").classList.contains("d-block")) { 3239 error = true; 3240 } 3241 return error; 3242 } 3243} 3244 3245async function check_basket_errors() { 3246 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 3247 const params = new URLSearchParams(); 3248 params.append('csrf_test_name', csrf_test_name); 3249 3250 try { 3251 const response = await fetch_with_retries(get_protocol_domain_name() + "/panier_v3/get_basket_errors", { 3252 method: 'POST', headers: { 3253 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 3254 }, body: params, 3255 mode: 'cors', 3256 credentials: 'same-origin' 3257 }); 3258 3259 3260 if (response.ok) { 3261 const errors = await response.json(); 3262 for (var error in errors) { 3263 addError("adr_errors",errors[error]); 3264 } 3265 } 3266 } catch (error) { 3267 logDebug('Erreur lors de la requête :', error); 3268 throw error; // Rejeter l'erreur pour la gérer à l'extérieur si nécessaire 3269 } 3270} 3271 3272async function get_basket_facturation_option(country, pro = false, maxRetries = 5, retries = 0) { 3273 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 3274 const params = new URLSearchParams(); 3275 params.append('csrf_test_name', csrf_test_name); 3276 if (!country) { 3277 country = document.getElementById("pays_facturation").value; 3278 } 3279 params.append('country', country); 3280 params.append('pro', pro); 3281 3282 try { 3283 const response = await fetch(get_protocol_domain_name() + "/panier_v3/get_basket_facturation_option", { 3284 method: 'POST', headers: { 3285 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'
3286 }, body: params, 3287 mode: 'cors', 3288 credentials: 'same-origin' 3289 }); 3290 3291 3292 if (response.ok) { 3293 const fields = await response.json(); 3294 await update_fields(fields["champ"]); 3295 return fields; 3296 } else { 3297 if (retries < maxRetries) { 3298 retries++; 3299 logDebug("Tentative " + retries + " de " + maxRetries); 3300 // Réessayer la requête 3301 return get_basket_facturation_option(country, pro, maxRetries, retries); 3302 } else { 3303 throw new Error('Nombre maximal de tentatives atteint'); 3304 } 3305 } 3306 3307 3308 } catch (error) { 3309 logDebug('Erreur lors de la requête :', error); 3310 throw error; // Rejeter l'erreur pour la gérer à l'extérieur si nécessaire 3311 } 3312} 3313async function form_login(maxRetries = 5, retries = 0) { 3314 const form = document.querySelector('#form_basket_login'); 3315 form.addEventListener('submit', async function (event) { 3316 // Vérifie la validité du formulaire avant de procéder 3317 event.preventDefault(); // Empêche l'envoi du formulaire 3318 show_ajax_loader(); // Affiche le loader AJAX 3319 try { 3320 let url = "/panier_v3/form_login"; 3321 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 3322 const infos_form = { 3323 "email": document.querySelector("#email_login").value, 3324 }; 3325 3326 if (document.querySelector("#password")) { 3327 infos_form["password"] = document.querySelector("#password").value; 3328 url = "/user/login"; 3329 infos_form["login_basket"] = true; 3330 } 3331 3332 const params = new URLSearchParams(); 3333 params.append('csrf_test_name', encodeURIComponent(csrf_test_name)); // Encode le CSRF 3334 Object.entries(infos_form).forEach(([key, value]) => { 3335 params.append(key, encodeURIComponent(value)); // Encode les valeurs du formulaire 3336 }); 3337 3338 const response = await fetch(get_protocol_domain_name() + url, { 3339 method: 'POST', headers: { 3340 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 3341 }, body: params, 3342 mode: 'cors', 3343 credentials: 'same-origin' 3344 }); 3345 3346 3347 if (response.ok) { 3348 const data = await response.json(); 3349 if (data.status === 'valid') { 3350 if (data.view) { 3351 // Remplace le contenu du panier par la nouvelle vue 3352 document.getElementById("view_step_basket").innerHTML = data.view; 3353 await form_login(); // Réattache le listener pour le formulaire si nécessaire 3354 passwordToggle(); 3355 3356 } else if (data.redirect) { 3357 // Redirection vers la bonne page 3358 window.location.href = data.redirect; 3359 } 3360 } else if (data.status === 'invalid') { 3361 // Afficher l'erreur lorsque le mot de passe est incorrect 3362 const passwordField = document.querySelector("#password"); 3363 field_error(passwordField, true, data.message); // Utilisation de la fonction `field_error` 3364 } 3365 } else { 3366 3367 if (retries < maxRetries) { 3368 retries++; 3369 logDebug("Tentative " + retries + " de " + maxRetries); 3370 // Réessayer la requête 3371 return form_login(maxRetries, retries); 3372 } else { 3373 throw new Error('Nombre maximal de tentatives atteint'); 3374 } 3375 } 3376 } catch (error) { 3377 logDebug('Erreur lors de la requête :', error); 3378 } finally { 3379 hide_ajax_loader(); // Cache le loader AJAX 3380 } 3381 }); 3382} 3383function save_basket() { 3384 if (document.querySelector("#form_basket_save")) { 3385 document.querySelector("#form_basket_save").addEventListener("submit", async function (event) { 3386 event.preventDefault(); 3387 show_ajax_loader(); 3388 validate_form(this); 3389 try { 3390 const csrf_test_name = this.querySelector("[name=csrf_test_name]").value; 3391 const infos_form = { 3392 "type": this.querySelector("[name=basket_save]").value, 3393 }; 3394 3395 const params = new URLSearchParams(); 3396 params.append('csrf_test_name', csrf_test_name); 3397 Object.entries(infos_form).forEach(([key, value]) => { 3398 params.append(key, value); 3399 }); 3400 3401 const response = await fetch(get_protocol_domain_name() + "/panier_v3/save_basket", { 3402 method: 'POST', headers: { 3403 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'
3404 }, body: params, 3405 mode: 'cors', 3406 credentials: 'same-origin' 3407 }); 3408 3409 if (response.ok) { 3410 const data = await response.text(); 3411 if (data.includes('error')) { 3412 logDebug('Erreur lors de la sauvegarde du panier:', data); 3413 } else { 3414 window.location.href = data; // Redirection vers la confirmation 3415 } 3416 } else { 3417 throw new Error('Response not OK'); 3418 } 3419 } catch (error) { 3420 logDebug('Erreur lors de la requête :', error); 3421 } finally { 3422 // hide_ajax_loader(); 3423 } 3424 }); 3425 } 3426} 3427 3428function transform_devis() { 3429 // Récupérer tous les formulaires avec la classe "form_transform_devis" 3430 const forms = document.querySelectorAll(".form_transform_devis"); 3431 if (forms.length > 0) { 3432 forms.forEach(function (form) { 3433 form.addEventListener("submit", async function (event) { 3434 event.preventDefault(); 3435 3436 const num_panier = this.getAttribute("id").split("_").pop(); // Extraire le numéro de panier depuis l'id 3437 const modalElement = document.getElementById(`modal_devis_to_commande_${num_panier}`); 3438 const closeButton = document.getElementById(`button_close_devis_modal_${num_panier}`); 3439 const validationDiv = document.getElementById(`validation_div_devis_to_commande_${num_panier}`); 3440 // Initialiser le modal avec l'API Bootstrap 3441 const modal = new bootstrap.Modal(modalElement, { 3442 backdrop: 'static', // Empêche la fermeture en cliquant à l'extérieur 3443 keyboard: false, // Empêche la fermeture avec la touche Ãchap 3444 }); 3445 3446 modal.show(); // Affiche le modal 3447 3448 if (closeButton) { 3449 closeButton.style.display = "none"; 3450 } 3451 3452 const csrf_test_name = this.querySelector("[name=csrf_test_name]").value; 3453 const num_devis = this.querySelector("[name=num_devis]").value; 3454 3455 const params = new URLSearchParams(); 3456 params.append("csrf_test_name", csrf_test_name); 3457 if (num_devis !== undefined) { 3458 params.append("num_devis", num_devis); 3459 } 3460 try { 3461 3462 // Effectuer la requête fetch 3463 const response = await fetch(get_protocol_domain_name() + "/panier_v3/transform_devis", { 3464 method: "POST", headers: { 3465 "Content-Type": "application/x-www-form-urlencoded", "X-Requested-With": "XMLHttpRequest", 3466 }, body: params.toString(), 3467 }); 3468 3469 if (response.ok) { 3470 const data = await response.json(); 3471 3472 if (data.old || !data.success) { 3473 if (closeButton) closeButton.style.display = "block"; 3474 if (validationDiv) validationDiv.innerHTML = data.view; 3475 } else { 3476 if (validationDiv) { 3477 setTimeout(() => { 3478 validationDiv.innerHTML = data.view; 3479 }, 1000); 3480 } 3481 setTimeout(() => { 3482 window.location = data.link; 3483 }, 3000); 3484 } 3485 } else { 3486 if (validationDiv) { 3487 setTimeout(() => { 3488 validationDiv.innerHTML = data.view; 3489 }, 1000); 3490 } 3491 setTimeout(() => { 3492 window.location = data.link; 3493 }, 3000); 3494 } 3495 } catch (error) { 3496 logDebug("Erreur lors de la requête :", error); 3497 } finally { 3498 setTimeout(() => { 3499 modal.hide(); // Fermer le modal via l'API Bootstrap 3500 }, 4000); 3501 } 3502 }); 3503 }); 3504 } 3505} 3506function delete_devis() { 3507 const delete_button = document.querySelectorAll(".btn-delete-devis"); 3508 if (delete_button.length > 0) { 3509 document.querySelectorAll("[id^='confirmDeleteBtn_']").forEach(function (confirmButton) { 3510 confirmButton.addEventListener("click", async function () { 3511 show_ajax_loader(); 3512 const num_panier = this.dataset.panierId; // Extraire le numéro de panier depuis l'attribut data-panier-id du bouton 3513 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 3514 const confirmModalId = `confirmDeleteModal_${num_panier}`; 3515 const confirmModal = document.getElementById(confirmModalId); 3516 const loadingModalId = `loadingDeleteModal_${num_panier}`; 3517 const loadingModal = new bootstrap.Modal(document.getElementById(loadingModalId)); 3518 3519 // Fermer la modal de confirmation avant d'ouvrir la modal de "Suppression en cours" 3520 const bootstrapConfirmModal = bootstrap.Modal.getInstance(confirmModal); 3521 bootstrapConfirmModal.hide(); 3522 3523
3524 try { 3525 const params = new URLSearchParams(); 3526 params.append("csrf_test_name", csrf_test_name); 3527 params.append("num_devis", num_panier); 3528 3529 const response = await fetch(get_protocol_domain_name() + "/panier_v3/delete_devis", { 3530 method: "POST", 3531 headers: { 3532 "Content-Type": "application/x-www-form-urlencoded", 3533 "X-Requested-With": "XMLHttpRequest", 3534 }, 3535 body: params.toString(), 3536 }); 3537 3538 if (response.ok) { 3539 const data = await response.json(); 3540 if (data.success) { 3541 const panierElement = document.querySelector(`#order_detail_${num_panier}`); 3542 if (panierElement) { 3543 const cardElement = panierElement.closest(".card"); 3544 if (cardElement) { 3545 const allOrderDetails = cardElement.querySelectorAll(".JS_order_detail"); 3546 3547 if (allOrderDetails.length === 1 && allOrderDetails[0] === panierElement) { 3548 // Si c'est le seul, on supprime toute la carte 3549 cardElement.remove(); 3550 } else { 3551 // Si ce nâest PAS le seul JS_order_detail 3552 const allOrderDetailsLeft = Array.from(allOrderDetails).filter(el => el !== panierElement); 3553 3554 if (allOrderDetailsLeft.length === 1) { 3555 // Après suppression, il ne restera quâun seul JS_order_detail, 3556 // donc on peut retirer les JS_total_subbasket 3557 const totalSubbaskets = cardElement.querySelectorAll(".JS_total_subbasket"); 3558 totalSubbaskets.forEach(el => el.remove()); 3559 } 3560 3561 // Ensuite on supprime juste le panier visé 3562 panierElement.remove(); 3563 } 3564 } 3565 } 3566 3567 } else { 3568 logDebug("Erreur serveur :", data.message); 3569 } 3570 } else { 3571 logDebug("Erreur réseau :", response.status); 3572 } 3573 } catch (error) { 3574 logDebug("Erreur lors de la requête :", error); 3575 } finally { 3576 loadingModal.hide(); 3577 hide_ajax_loader(); 3578 } 3579 }); 3580 }); 3581 } 3582} 3583 3584if (document.querySelector("#basket_form_vehicule")) { 3585 // Initialisation de l'affichage au chargement de la page 3586 collapse_elements_specific("vehicle_recap", "vehicle_info_form"); 3587} 3588 3589function collapse_elements_specific(recapSectionLibellle, formSectionLibelle) { 3590 const recapSection = document.getElementById(recapSectionLibellle); // Section récap 3591 const formSection = document.getElementById(formSectionLibelle); // Section formulaire 3592 const editButton = document.querySelector('.btn-secondary'); // Bouton d'édition 3593 3594 // Ajouter la classe collapse_specific pour gérer les transitions sur recapSection 3595 recapSection.classList.add('collapse_specific'); 3596 3597 // Fonction pour afficher/masquer les sections avec transition fluide 3598 const toggleDisplayBasketFormVehicule = () => { 3599 if (formSection.classList.contains('show')) { 3600 // Formulaire est ouvert, cacher récap avec animation 3601 recapSection.classList.add('hide'); // Ajout d'une classe pour masquer avec transition 3602 recapSection.style.display = 'none'; // S'assurer que c'est caché 3603 } else { 3604 // Formulaire est fermé, afficher récap avec animation 3605 recapSection.classList.remove('hide'); // Retirer la classe qui masque 3606 recapSection.style.display = 'flex'; // S'assurer que c'est visible 3607 } 3608 }; 3609 3610 // Gestion des événements de collapse Bootstrap 3611 formSection.addEventListener('shown.bs.collapse', function () { 3612 recapSection.classList.add('hide'); // Cache le récap avec transition quand le formulaire est montré 3613 recapSection.style.display = 'none'; 3614 }); 3615 3616 formSection.addEventListener('hidden.bs.collapse', function () { 3617 recapSection.classList.remove('hide'); // Montre le récap avec transition quand le formulaire est caché 3618 recapSection.style.display = 'flex'; 3619 }); 3620 3621 // Gestion des clics sur le bouton d'édition 3622 editButton.addEventListener('click', function () { 3623 // Même gestion que pour le titre 3624 if (formSection.classList.contains('show')) { 3625 formSection.classList.remove('show'); 3626 recapSection.classList.remove('hide'); 3627 } else { 3628 formSection.classList.add('show'); 3629 recapSection.classList.add('hide'); 3630 } 3631 }); 3632 3633 toggleDisplayBasketFormVehicule(); 3634 3635 3636 3637} 3638 3639let paymentLocked = false; 3640 3641function collapse_elements_payment() { 3642 const inputs = document.querySelectorAll('input[name="choix_payment"]'); 3643
3644 inputs.forEach(input => { 3645 input.addEventListener("click", function (e) { 3646 if (paymentLocked) { 3647 e.preventDefault(); 3648 e.stopImmediatePropagation(); 3649 return false; 3650 } 3651 3652 paymentLocked = true; 3653 3654 // Même logique qu'avant... 3655 if (this.checked && this.dataset.selected === "true") { 3656 this.checked = false; 3657 this.dataset.selected = "false"; 3658 3659 document.querySelectorAll('.collapse_payments').forEach(collapse => { 3660 let bsCollapse_off = bootstrap.Collapse.getOrCreateInstance(collapse, { 3661 toggle: false 3662 }); 3663 bsCollapse_off.hide(); 3664 }); 3665 } else { 3666 inputs.forEach(i => i.dataset.selected = "false"); 3667 this.dataset.selected = "true"; 3668 3669 document.querySelectorAll('.collapse_payments').forEach(collapse => { 3670 let bsCollapse_off = bootstrap.Collapse.getOrCreateInstance(collapse, { 3671 toggle: false 3672 }); 3673 bsCollapse_off.hide(); 3674 }); 3675 3676 let selectedCollapse = document.getElementById("collapse_payment_" + this.value); 3677 if (selectedCollapse) { 3678 let bsCollapse = bootstrap.Collapse.getOrCreateInstance(selectedCollapse); 3679 bsCollapse.show(); 3680 } 3681 } 3682 3683 // Déverrouiller après la transition 3684 setTimeout(() => { 3685 paymentLocked = false; 3686 }, 400); 3687 }); 3688 }); 3689} 3690 3691async function getBasketInformations(maxRetries = 5, retries = 0) { 3692 try { 3693 const response = await fetch(get_protocol_domain_name() + "/panier_v3/get_basket_informations", { 3694 method: "GET", 3695 headers: { 3696 "X-Requested-With": "XMLHttpRequest" 3697 }, 3698 mode: "cors", 3699 credentials: "same-origin" 3700 }); 3701 3702 if (response.ok) { 3703 const modalContent = await response.text(); // Récupération du HTML 3704 document.querySelector("#panier_modal").innerHTML = modalContent; 3705 // Affichage de la modale Bootstrap 3706 3707 if (modalContent) { 3708 let basketModal = new bootstrap.Modal(document.getElementById("basket_modal_information")); 3709 basketModal.show(); 3710 } 3711 } else { 3712 if (retries < maxRetries) { 3713 retries++; 3714 logDebug(`Tentative ${retries} de ${maxRetries}`); 3715 return getBasketInformations(maxRetries, retries); // On retente la requête 3716 } else { 3717 throw new Error('Nombre maximal de tentatives atteint'); 3718 } 3719 } 3720 } catch (error) { 3721 logDebug('Erreur dans getBasketInformations:', error); 3722 3723 if (retries < maxRetries) { 3724 retries++; 3725 logDebug(`Tentative ${retries} de ${maxRetries}`); 3726 return getBasketInformations(maxRetries, retries); // On retente la requête 3727 } else { 3728 console.error("Ãchec après plusieurs tentatives."); 3729 } 3730 } 3731} 3732 3733async function set_transaction_on_progress() { 3734 document.querySelector("#form_card_payment").addEventListener("submit", async function() { 3735 await transaction_on_progress(); 3736 }); 3737} 3738 3739async function transaction_on_progress() { 3740 const csrf_test_name = document.querySelector("[name=csrf_test_name]").value; 3741 const params = new URLSearchParams(); 3742 params.append('csrf_test_name', csrf_test_name); 3743 3744 try { 3745 await fetchWithRetries(get_protocol_domain_name() + "/panier_v3/set_transaction_on_progress", { 3746 method: 'POST', headers: { 3747 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' 3748 }, body: params, 3749 mode: 'cors', 3750 credentials: 'same-origin' 3751 }); 3752 } catch (error) { 3753 // Gérer les erreurs 3754 logDebug('Erreur lors de la requête :', error); 3755 } 3756} 3757function check_transaction_on_progress() { 3758 document.querySelector("#form_card_payment").addEventListener("submit", async function(event) { 3759 event.preventDefault(); 3760 3761 const form = this; 3762 const csrf_test_name = form.querySelector("[name=csrf_test_name]").value; 3763 const params = new URLSearchParams(); 3764 params.append('csrf_test_name', csrf_test_name); 3765 3766 try { 3767 const response = await fetchWithRetries(get_protocol_domain_name() + "/panier_v3/check_transaction_on_progress", { 3768 method: 'POST', 3769 headers: { 3770 'Content-Type': 'application/x-www-form-urlencoded', 3771 'X-Requested-With': 'XMLHttpRequest' 3772 }, 3773 body: params.toString(), 3774 mode: 'cors', 3775 credentials: 'same-origin' 3776 }); 3777 3778 if (response.ok) { 3779 const data = await response.json(); 3780 if (data.status === "ok") { 3781 form.submit(); 3782 } else { 3783 if (data.redirect_url) { 3784 window.location.href = data.redirect_url; 3785 } else { 3786 window.location.href = "/" + await trad('_ROUTE_PANIER_AFFICHER') 3787 } 3788 } 3789 } 3790 } catch (error) { 3791 logDebug('Erreur lors de la requête :', error); 3792 } 3793 }); 3794} 3795 3796 3797
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.