1/** 2 * Unified Button Manager pentru Fake Checkout 3 * Versiunea 2.1.0 - Production Ready (log cleaned) 4 * 5 * Acest manager unificat este singurul sistem de toggle butoane: 6 * - fake-checkout-toggle.js (removed) 7 * - CheckoutButtonManager din form-checkout.js (removed in Task #011) 8 * - toggleCheckoutButtons din fake-checkout-handler.js (consolidated in Task #011) 9 * - Colaboreaza cu Horeka Core pentru validare suma minima 10 * 11 * Caracteristici: 12 * - Un singur punct de control pentru toate butoanele 13 * - FÄrÄ race conditions sau conflicte 14 * - Debouncing pentru performanÈÄ 15 * - Minimal logging pentru producÈie 16 */ 17 18(function($) { 19 'use strict'; 20 21 // ======================================== 22 // CONFIG ÈI CONSTANTE 23 // ======================================== 24 25 // Logging pentru producÈie (dezactivat implicit) 26 const ENABLE_LOGGING = false; 27 const log = function(message, data) { 28 if (ENABLE_LOGGING) { 29 if (data) { 30 console.log(message, data); 31 } else { 32 console.log(message); 33 } 34 } 35 }; 36 37 const CONFIG = { 38 // Debounce delays pentru evitarea apelurilor multiple 39 DEBOUNCE_DELAY: 250, // Delay pentru toggle buttons 40 INIT_DELAY: 500, // Delay pentru iniÈializare 41 42 // Selectori DOM 43 SELECTORS: { 44 normalButton: '#place_order', 45 fakeButton: '.fake-checkout-button, #place_order_fake', 46 paymentRadios: 'input[name="payment_method"]', 47 paymentDropdown: 'select[name="payment_method"]', 48 blueCards: '.blue-cards label', 49 body: 'body', 50 iframe: '#iframeCheckout' 51 }, 52 53 // Clase CSS pentru detectare 54 CLASSES: { 55 fakeCheckoutMode: 'fake-checkout-mode', 56 inIframe: 'in-iframe-checkout', 57 netopiaSelected: 'netopia-payment-selected' 58 }, 59 60 // Metode de platÄ 61 PAYMENT_METHODS: { 62 // Procesatorul de card activ (NETOPIA sau EuPlatesc), injectat din PHP. 63 netopia: window.HOREKA_ONLINE_GATEWAY || 'netopiapayments', 64 cod: 'cod', 65 cardOnDelivery: 'WC_Card_Livrare_Payment_Gateway' 66 } 67 }; 68 69 // ======================================== 70 // MANAGER PRINCIPAL 71 // ======================================== 72 window.UnifiedButtonManager = { 73 // State intern 74 state: { 75 isInitialized: false, 76 currentPaymentMethod: null, 77 isFakeCheckoutMode: false, 78 isNetopiaSelected: false, 79 lastToggleTime: 0, 80 toggleCount: 0, 81 // SOLUÈIE PAYMENT PERSISTENCE: SalvÄm alegerea utilizatorului 82 userSelectedPaymentMethod: null, // Metoda aleasÄ explicit de utilizator 83 isRestoringPayment: false, // Flag pentru a evita salvarea în timpul restaurÄrii 84 hasUserMadeSelection: false // Flag pentru a detecta dacÄ utilizatorul a fÄcut o selecÈie explicitÄ 85 }, 86 87 /** 88 * IniÈializeazÄ managerul 89 * Aceasta este singura metodÄ care trebuie apelatÄ 90 */ 91 init: function() { 92 const self = this; 93 94 // Auto-fix pointer-events:none on fake checkout button so clicks register. 95 document.addEventListener('click', function(e) { 96 var fakeBtn = document.querySelector('.fake-checkout-button'); 97 if (!fakeBtn) { 98 return; 99 } 100 var rect = fakeBtn.getBoundingClientRect(); 101 var clickX = e.clientX, clickY = e.clientY; 102 if (clickX >= rect.left && clickX <= rect.right && clickY >= rect.top && clickY <= rect.bottom) { 103 if (window.getComputedStyle(fakeBtn).pointerEvents === 'none') { 104 fakeBtn.style.pointerEvents = 'auto'; 105 fakeBtn.style.opacity = '1'; 106 fakeBtn.style.cursor = 'pointer'; 107 fakeBtn.disabled = false;
108 fakeBtn.classList.remove('button-disabled'); 109 } 110 } 111 }, true); 112 113 // Previne iniÈializarea dublÄ 114 if (this.state.isInitialized) { 115 return; 116 } 117 118 // SOLUÈIE CRITICÄ: CurÄÈÄ localStorage la prima încÄrcare 119 // Doar dacÄ utilizatorul nu a fÄcut încÄ o selecÈie explicitÄ Ã®n aceastÄ sesiune 120 this.clearInitialPaymentState(); 121 122 // DetecteazÄ contextul iniÈial 123 this.detectContext(); 124 125 // ConfigureazÄ event listeners 126 this.setupEventListeners(); 127 128 // IniÈializare cu delay pentru a permite încÄrcarea completÄ a DOM 129 setTimeout(function() { 130 self.checkInitialState(); 131 self.state.isInitialized = true; 132 log('[UnifiedManager] â Manager iniÈializat cu succes'); 133 }, CONFIG.INIT_DELAY); 134 }, 135 136 /** 137 * SOLUÈIE CRITICÄ: CurÄÈÄ starea iniÈialÄ de payment pentru prima vizitare 138 * Previne restaurarea automatÄ din localStorage la prima încÄrcare a paginii 139 */ 140 clearInitialPaymentState: function() { 141 // VerificÄ dacÄ avem un marker cÄ utilizatorul a fÄcut o selecÈie în aceastÄ sesiune 142 const sessionKey = 'horeka_user_made_payment_selection_' + Date.now().toString().slice(-8); 143 const hasSessionSelection = sessionStorage.getItem('horeka_user_made_selection'); 144 145 if (!hasSessionSelection) { 146 // Prima încÄrcare în aceastÄ sesiune de browser - curÄÈÄ localStorage 147 try { 148 const oldValue = localStorage.getItem('horeka_user_payment_method'); 149 if (oldValue) { 150 localStorage.removeItem('horeka_user_payment_method'); 151 log('[UnifiedManager] ð§¹ Prima încÄrcare - Èters localStorage payment method:', oldValue); 152 } 153 } catch (e) { 154 // Ignore localStorage errors 155 } 156 157 // MarcheazÄ cÄ am curÄÈat starea iniÈialÄ 158 try { 159 sessionStorage.setItem('horeka_session_cleaned', 'true'); 160 } catch (e) { 161 // Ignore sessionStorage errors 162 } 163 164 log('[UnifiedManager] ð Prima încÄrcare detectatÄ - utilizatorul va selecta fresh'); 165 } else { 166 log('[UnifiedManager] ð Sesiune continuÄ - pÄstrez preferinÈele utilizatorului'); 167 this.state.hasUserMadeSelection = true; 168 } 169 }, 170 171 /** 172 * DetecteazÄ contextul (iframe, fake checkout mode, lite version) 173 */ 174 detectContext: function() { 175 const $body = $(CONFIG.SELECTORS.body); 176 const $iframe = $(CONFIG.SELECTORS.iframe); 177 178 // VerificÄ dacÄ suntem în iframe 179 const inIframe = (window !== window.top); 180 181 // VerificÄ lite version din PHP config 182 const isLiteVersion = window.unifiedManagerConfig && window.unifiedManagerConfig.isLiteVersion; 183 184 // VerificÄ dacÄ avem fake checkout mode (iframe SAU lite version) 185 this.state.isFakeCheckoutMode = 186 $body.hasClass(CONFIG.CLASSES.fakeCheckoutMode) || 187 $iframe.length > 0 || 188 document.cookie.indexOf('is_iframe_context=1') > -1 || 189 inIframe || 190 isLiteVersion; 191 192 log('[UnifiedManager] ð Context detectat:', { 193 inIframe: inIframe, 194 isLiteVersion: isLiteVersion, 195 fakeCheckoutMode: this.state.isFakeCheckoutMode, 196 hasIframeElement: $iframe.length > 0, 197 hasCookie: document.cookie.indexOf('is_iframe_context=1') > -1 198 }); 199 200 return this.state.isFakeCheckoutMode; 201 }, 202 203 /** 204 * VerificÄ starea iniÈialÄ Èi seteazÄ butoanele corect 205 */ 206 checkInitialState: function() { 207 // GÄseÈte metoda de platÄ selectatÄ 208 const $selectedPayment = $(CONFIG.SELECTORS.paymentRadios + ':checked'); 209 const $dropdown = $(CONFIG.SELECTORS.paymentDropdown); 210 211 let currentMethod = null; 212 213 if ($selectedPayment.length) { 214 currentMethod = $selectedPayment.val(); 215 } else if ($dropdown.length) { 216 currentMethod = $dropdown.val(); 217 } 218 219 if (currentMethod) { 220 log('[UnifiedManager] ð Stare iniÈialÄ - metodÄ platÄ:', currentMethod); 221 this.state.currentPaymentMethod = currentMethod; 222 this.updateButtons(); 223 } else { 224 log('[UnifiedManager] â ï¸ Nicio metodÄ de platÄ selectatÄ iniÈial'); 225 } 226 }, 227 228 /** 229 * ConfigureazÄ toÈi event listeners 230 * Un singur loc pentru toate evenimentele 231 */ 232 setupEventListeners: function() { 233 const self = this; 234 235 // IMPORTANT: CurÄÈÄm TOATE event listeners existente înainte de a adÄuga noi 236 $(document).off('change', CONFIG.SELECTORS.paymentRadios); 237 $(document).off('change', CONFIG.SELECTORS.paymentDropdown); 238 $(document).off('click', CONFIG.SELECTORS.blueCards); 239 $(document.body).off('updated_checkout.unifiedManager'); 240 $(document).off('payment_method_visibility_updated.unifiedManager'); 241 242 log('[UnifiedManager] ð§§ Event listeners curÄÈate pentru a preveni duplicarea'); 243 244 // Debounce function pentru a preveni apelurile multiple 245 const debouncedUpdate = this.debounce(function() { 246 self.updateButtons(); 247 }, CONFIG.DEBOUNCE_DELAY); 248 249 // ======================================== 250 // EVENIMENTE PENTRU SCHIMBAREA METODEI DE PLÄTÄ 251 // ======================================== 252 253 // 1. Radio buttons standard - cu namespace pentru identificare uÈoarÄ 254 $(document).on('change.unifiedManager', CONFIG.SELECTORS.paymentRadios, function() { 255 const method = $(this).val();
256 log('[UnifiedManager] ð» Radio schimbat:', method); 257 self.state.currentPaymentMethod = method; 258 259 // SOLUÈIE PAYMENT PERSISTENCE: SalvÄm alegerea utilizatorului 260 // SalvÄm DOAR dacÄ nu suntem în proces de restaurare Èi utilizatorul a fÄcut o selecÈie explicitÄ 261 if (!self.state.isRestoringPayment) { 262 // MarcÄm cÄ utilizatorul a fÄcut o selecÈie explicitÄ (nu automatÄ) 263 self.state.hasUserMadeSelection = true; 264 self.saveUserPaymentChoice(method); 265 log('[UnifiedManager] ð¾ MetodÄ salvatÄ pentru restaurare (selecÈie utilizator):', method); 266 } 267 268 debouncedUpdate(); 269 }); 270 271 // 2. Dropdown select (dacÄ existÄ) - cu namespace 272 $(document).on('change.unifiedManager', CONFIG.SELECTORS.paymentDropdown, function() { 273 const method = $(this).val(); 274 log('[UnifiedManager] ð Dropdown schimbat:', method); 275 self.state.currentPaymentMethod = method; 276 277 // SOLUÈIE PAYMENT PERSISTENCE: SalvÄm Èi pentru dropdown 278 if (!self.state.isRestoringPayment) { 279 self.state.hasUserMadeSelection = true; 280 self.saveUserPaymentChoice(method); 281 log('[UnifiedManager] ð¾ MetodÄ salvatÄ pentru restaurare (dropdown):', method); 282 } 283 284 debouncedUpdate(); 285 }); 286 287 // 3. Blue cards click (pentru design custom) - cu namespace 288 $(document).on('click.unifiedManager', CONFIG.SELECTORS.blueCards, function() { 289 const method = $(this).find('input').val(); 290 log('[UnifiedManager] ð³ Card selectat:', method); 291 self.state.currentPaymentMethod = method; 292 293 // SOLUÈIE PAYMENT PERSISTENCE: SalvÄm Èi pentru blue cards 294 if (!self.state.isRestoringPayment) { 295 self.state.hasUserMadeSelection = true; 296 self.saveUserPaymentChoice(method); 297 log('[UnifiedManager] ð¾ MetodÄ salvatÄ pentru restaurare (blue card):', method); 298 } 299 300 // Delay mic pentru a permite radio sÄ se selecteze 301 setTimeout(function() { 302 debouncedUpdate(); 303 }, 50); 304 }); 305 306 // ======================================== 307 // EVENIMENTE WOOCOMMERCE 308 // ======================================== 309 310 // 4. DupÄ update checkout - cu namespace 311 $(document.body).on('updated_checkout.unifiedManager', function() { 312 log('[UnifiedManager] â»ï¸ Checkout actualizat'); 313 self.detectContext(); // Re-verificÄ contextul 314 315 // SOLUÈIE PAYMENT PERSISTENCE: RestaurÄm metoda de platÄ salvatÄ 316 // ÃMBUNÄTÄÈIRE TIMING: RestaurÄm IMEDIAT pentru a preveni auto-selecÈia 317 setTimeout(function() { 318 // PRIORITATE: ÃncercÄm sÄ restaurÄm metoda salvatÄ de utilizator PRIMUL 319 self.restoreUserPaymentChoice(); 320 321 // DupÄ restaurare, verificÄm starea iniÈialÄ 322 self.checkInitialState(); 323 }, 10); // Redus de la 100ms la 10ms pentru timing mai rapid 324 }); 325 326 // 4b. ÃMBUNÄTÄÈIRE ANTI-RESET: SalveazÄ metoda curentÄ ÃNAINTE de update_checkout 327 $(document.body).on('update_checkout.unifiedManager', function() { 328 log('[UnifiedManager] â° Pre-update: Salvez metoda curentÄ...'); 329 // SalvÄm rapid metoda curent selectatÄ Ã®nainte ca checkout-ul sÄ se actualizeze 330 var currentMethod = $('input[name="payment_method"]:checked').val(); 331 if (currentMethod) { 332 self.state.userSelectedPaymentMethod = currentMethod; 333 self.state.hasUserMadeSelection = true; 334 log('[UnifiedManager] ð¾ Pre-salvat pentru backup:', currentMethod); 335 } 336 }); 337 338 // 5. Custom event pentru update vizibilitate - cu namespace 339 $(document).on('payment_method_visibility_updated.unifiedManager', function() { 340 log('[UnifiedManager] ðï¸ Vizibilitate actualizatÄ'); 341 debouncedUpdate(); 342 }); 343 344 // ======================================== 345 // EVENIMENTE PENTRU METODA DE LIVRARE 346 // ======================================== 347 348 // 6. Schimbarea metodei de livrare (radio buttons) 349 $(document).on('change.unifiedManager', 'input[name="delivery_method"]', function() { 350 const method = $(this).val(); 351 log('[UnifiedManager] ð MetodÄ livrare schimbatÄ:', method); 352 353 // Re-verificÄ suma minimÄ când se schimbÄ metoda de livrare 354 setTimeout(function() { 355 self.updateButtons(); 356 }, 100); 357 }); 358 359 // 7. Schimbarea metodei de livrare (dropdown) 360 $(document).on('change.unifiedManager', 'select[name="delivery_method"]', function() { 361 const method = $(this).val(); 362 log('[UnifiedManager] ð MetodÄ livrare schimbatÄ (dropdown):', method); 363 364 // Re-verificÄ suma minimÄ când se schimbÄ metoda de livrare 365 setTimeout(function() { 366 self.updateButtons(); 367 }, 100); 368 }); 369 370 // 8. Schimbarea adresei de livrare sau facturare 371 $(document).on('change.unifiedManager blur.unifiedManager', 372 '#billing_address_1_field input, #shipping_address_1_field input, input[name="billing_address_1"], input[name="shipping_address_1"]', 373 function() { 374 const addressValue = $(this).val(); 375 log('[UnifiedManager] ð AdresÄ schimbatÄ:', addressValue); 376 377 // Delay mai mare pentru a permite calculul taxelor de livrare 378 setTimeout(function() { 379 self.updateButtons(); 380 }, 300); 381 }); 382 383 // 9. Update când se schimbÄ totalul comenzii (pentru re-validare) 384 $(document.body).on('updated_cart_totals updated_checkout updated_shipping_method.unifiedManager', function() { 385 log('[UnifiedManager] ð° Totaluri actualizate - re-verific suma minimÄ'); 386 setTimeout(function() { 387 self.updateButtons(); 388 }, 200); 389 }); 390 391 // ======================================== 392 // DEZACTIVARE SISTEME VECHI 393 // ======================================== 394 395 // OpreÈte alte managere sÄ intervinÄ 396 this.disableConflictingSystems(); 397 }, 398 399 /** 400 * Ensures the fake checkout button exists in the DOM. 401 * Creates it dynamically next to #place_order if missing. 402 * Previously this logic lived in fake-checkout-handler.js toggleCheckoutButtons(). 403 * Consolidated here in Task #011. 404 */ 405 ensureFakeButtonExists: function() { 406 var $fakeButton = $(CONFIG.SELECTORS.fakeButton); 407 if ($fakeButton.length > 0) { 408 return $fakeButton; 409 } 410 411 var $normalButton = $(CONFIG.SELECTORS.normalButton); 412 if (!$normalButton.length) { 413 return $(); 414 } 415 416 var buttonText = $normalButton.text() || 'Plaseaza comanda'; 417 var fakeButtonHtml = '<button type="button" class="button alt fake-checkout-button" id="place_order_fake" style="display: none;" data-fake-checkout="true">' + buttonText + '</button>'; 418 $normalButton.after(fakeButtonHtml); 419 $fakeButton = $('#place_order_fake'); 420 log('[UnifiedManager] Fake button created dynamically'); 421 422 return $fakeButton; 423 }, 424 425 /** 426 * DetecteazÄ pagina de platÄ a unei comenzi (endpoint-ul order-pay). 427 * 428 * Endpoint-ul e tradus pe unele site-uri (`finalizare-comanda`), deci nu ne 429 * uitÄm la URL, ci la structura DOM: form-pay.php randeazÄ `<form id="order_review">`, 430 * în timp ce checkout-ul randeazÄ `<form class="checkout">` cu un `<div id="order_review">` 431 * înÄuntru. Butonul fake nu are niciun handler util aici â dacÄ Ã®l afiÈÄm, 432 * clientul apasÄ Èi nu se întâmplÄ nimic, iar comanda rÄmâne neplÄtitÄ. 433 * 434 * @returns {boolean} 435 */ 436 isOrderPayPage: function() { 437 if (new URLSearchParams(window.location.search).get('pay_for_order') === 'true') { 438 return true; 439 } 440 441 return $('form#order_review').length > 0 && $('form.checkout').length === 0; 442 }, 443 444 /** 445 * FuncÈia principalÄ care actualizeazÄ butoanele 446 * Aceasta este singura funcÈie care manipuleazÄ DOM-ul 447 */ 448 updateButtons: function() { 449 // CENTURÄ DE SIGURANÈÄ: pe pagina de platÄ butonul real este singurul care 450 // trimite formularul spre procesatorul de card. Nu îl atingem niciodatÄ. 451 if (this.isOrderPayPage()) { 452 log('[UnifiedManager] â Pagina de platÄ (order-pay) - butoanele nu se modificÄ'); 453 return; 454 } 455 456 // Re-detecteazÄ contextul la fiecare update 457 this.detectContext(); 458 459 const $normalButton = $(CONFIG.SELECTORS.normalButton); 460 461 // Ensure fake button exists before trying to use it 462 if (this.state.isFakeCheckoutMode && 463 this.state.currentPaymentMethod === CONFIG.PAYMENT_METHODS.netopia) { 464 this.ensureFakeButtonExists(); 465 } 466 467 const $fakeButton = $(CONFIG.SELECTORS.fakeButton); 468 469 // VerificÄ dacÄ butoanele existÄ 470 if (!$normalButton.length && !$fakeButton.length) { 471 return; 472 } 473 474 // ======================================== 475 // VERIFICARE SUMA MINIMÄ DE COMANDÄ 476 // ======================================== 477 478 // VerificÄ dacÄ suntem în modul redirect fake checkout SAU fake-checkout-mode (light app)
479 const urlParams = new URLSearchParams(window.location.search); 480 const isRedirectMode = urlParams.get('auto_submit') === '1' || 481 urlParams.get('fake_checkout') === '1' || 482 $('body').hasClass('fake-checkout-mode'); 483 484 log('[UnifiedManager] updateButtons() - isRedirectMode:', isRedirectMode, 'fake-checkout-mode class:', $('body').hasClass('fake-checkout-mode')); 485 486 // VerificÄ metoda de livrare ÃNAINTE de validarea sumei minime 487 const deliveryMethod = this.getDeliveryMethod(); 488 489 // Pentru ridicare personalÄ, NU verifica suma minimÄ deloc 490 if (deliveryMethod === 'pickup') { 491 log('[UnifiedManager] ðª Ridicare personalÄ - skip complet validare sumÄ minimÄ'); 492 } else if (isRedirectMode) { 493 // Ãn modul redirect pentru livrare acasÄ, NU verifica suma minimÄ 494 log('[UnifiedManager] ð Redirect mode livrare acasÄ - skip validare sumÄ minimÄ'); 495 } else { 496 // Doar pentru livrare acasÄ Ã®n mod normal, verificÄ suma minimÄ 497 log('[UnifiedManager] ð Livrare acasÄ mod normal - verific suma minimÄ'); 498 const validationPassed = this.checkMinimumOrderAmount(); 499 500 // DacÄ validarea nu a trecut, butoanele rÄmân disable Èi ieÈim 501 if (!validationPassed) { 502 log('[UnifiedManager] â ï¸ Suma minimÄ nu este atinsÄ - butoane disabled'); 503 return; 504 } 505 } 506 507 // VERIFICARE PRIORITARÄ: DacÄ Horeka Core a disabled butoanele, respectÄ decizia 508 if (this.state.buttonsDisabledByHoreka) { 509 log('[UnifiedManager] â¸ï¸ Butoane disabled de Horeka Core - nu aplic toggle logic'); 510 return; // NU schimba nimic, lasÄ Horeka Core sÄ controleze 511 } 512 513 // DeterminÄ dacÄ trebuie sÄ arÄtÄm butonul fake 514 const shouldShowFake = 515 this.state.isFakeCheckoutMode && 516 this.state.currentPaymentMethod === CONFIG.PAYMENT_METHODS.netopia && 517 !this.hasAddressValidationErrors(); // ADÄUGAT: Verificare erori adresÄ 518 519 // Logging doar dacÄ starea se schimbÄ 520 if (this.shouldLog()) { 521 log('[UnifiedManager] ð Toggle butoane:', { 522 metodaPlata: this.state.currentPaymentMethod, 523 fakeMode: this.state.isFakeCheckoutMode, 524 showFake: shouldShowFake, 525 hasAddressErrors: this.hasAddressValidationErrors(), 526 redirectMode: isRedirectMode 527 }); 528 } 529 530 // ======================================== 531 // APLICARE STARE - SIMPLU ÈI CLAR 532 // ======================================== 533 534 if (shouldShowFake) { 535 // AratÄ butonul fake, ascunde pe cel normal - FORÈAT cu CSS inline 536 $normalButton 537 .css({ 538 'display': 'none', 539 'visibility': 'hidden', 540 'position': 'absolute', 541 'left': '-9999px' 542 }) 543 .addClass('button-hidden') 544 .removeClass('button-visible'); 545 546 $fakeButton 547 .css({ 548 'display': 'inline-block', 549 'visibility': 'visible', 550 'position': 'relative', 551 'left': 'auto', 552 'pointer-events': 'auto', 553 'opacity': '1', 554 'cursor': 'pointer' 555 }) 556 .prop('disabled', false) 557 .addClass('button-visible') 558 .removeClass('button-hidden button-disabled'); 559 560 log('[UnifiedManager] updateButtons() - fake button ENABLED & SHOWN'); 561 562 // AdaugÄ clase pe body pentru CSS 563 $(CONFIG.SELECTORS.body).addClass(CONFIG.CLASSES.netopiaSelected); 564 565 // DEZACTIVAT: Nu salva automat în localStorage - doar pentru redirect iframe specific 566 // localStorage.setItem('paymentMethod', CONFIG.PAYMENT_METHODS.netopia); 567 568 log('[UnifiedManager] â Buton FAKE activat pentru Netopia'); 569 } else { 570 // AratÄ butonul normal, ascunde pe cel fake - FORÈAT cu CSS inline 571 $normalButton 572 .css({ 573 'display': 'inline-block', 574 'visibility': 'visible', 575 'position': 'relative', 576 'left': 'auto' 577 }) 578 .addClass('button-visible') 579 .removeClass('button-hidden'); 580 581 $fakeButton 582 .css({ 583 'display': 'none', 584 'visibility': 'hidden', 585 'position': 'absolute', 586 'left': '-9999px' 587 }) 588 .addClass('button-hidden') 589 .removeClass('button-visible'); 590 591 // EliminÄ clase de pe body 592 $(CONFIG.SELECTORS.body).removeClass(CONFIG.CLASSES.netopiaSelected); 593 594 // CurÄÈÄ localStorage 595 localStorage.removeItem('paymentMethod'); 596 597 if (this.shouldLog()) { 598 log('[UnifiedManager] â Buton NORMAL activat'); 599 } 600 } 601 602 // Update state pentru tracking 603 this.state.toggleCount++; 604 }, 605 606 /** 607 * VerificÄ suma minimÄ de comandÄ 608 * ColaboreazÄ REAL cu validarea din Horeka Core 609 */ 610 checkMinimumOrderAmount: function() { 611 // 1. VerificÄ mai întâi tipul de livrare 612 const deliveryMethod = this.getDeliveryMethod(); 613 614 // Pentru ridicare personalÄ (pickup), nu verificÄ suma minimÄ 615 if (deliveryMethod === 'pickup') { 616 log('[UnifiedManager] ðª Ridicare personalÄ - nu se verificÄ suma minimÄ'); 617 this.enableButtons(); 618 return true; 619 } 620 621 // 2. Pentru livrare acasÄ, verificÄ cookie-ul CanDeliver setat de Horeka Core 622 log('[UnifiedManager] ð Livrare acasÄ - verific cookie CanDeliver'); 623 624 var canDeliver = (this.getCookie('CanDeliver') || '').toLowerCase(); 625 626 if (canDeliver === 'false') { 627 log('[UnifiedManager] ð CanDeliver=False - butoane disabled (Horeka Core decision)'); 628 this.disableButtons(); 629 return false;
630 } 631 632 if (canDeliver === 'true' || canDeliver === '') { 633 log('[UnifiedManager] â CanDeliver OK - butoane enabled'); 634 this.enableButtons(); 635 return true; 636 } 637 638 // Cookie absent (prima încÄrcare) â Horeka Core va seta cookie-ul la updated_checkout 639 log('[UnifiedManager] â³ Cookie CanDeliver absent - permit trecerea, aÈtept Horeka Core'); 640 return true; 641 }, 642 643 /** 644 * DeterminÄ metoda de livrare selectatÄ 645 */ 646 getDeliveryMethod: function() { 647 // CautÄ radio buttons pentru metoda de livrare 648 const $deliveryRadio = $('input[name="delivery_method"]:checked'); 649 if ($deliveryRadio.length) { 650 const method = $deliveryRadio.val(); 651 652 // MapeazÄ valorile posibile la categorii 653 if (method === 'ridicare-personala' || method === 'servire-la-restaurant' || method === 'pickup') { 654 return 'pickup'; 655 } else if (method === 'livrare-la-domiciliu' || method === 'home_delivery') { 656 return 'home_delivery'; 657 } 658 return method; // ReturneazÄ valoarea exactÄ dacÄ nu se potriveÈte 659 } 660 661 // CautÄ Ã®n dropdown 662 const $deliverySelect = $('select[name="delivery_method"]'); 663 if ($deliverySelect.length) { 664 const method = $deliverySelect.val(); 665 log('[UnifiedManager] ð MetodÄ livrare detectatÄ (select):', method); 666 667 // MapeazÄ valorile posibile 668 if (method === 'ridicare-personala' || method === 'servire-la-restaurant' || method === 'pickup') { 669 return 'pickup'; 670 } else if (method === 'livrare-la-domiciliu' || method === 'home_delivery') { 671 return 'home_delivery'; 672 } 673 return method; 674 } 675 676 // VerificÄ Ã®n body class sau alte indicii 677 if ($(document.body).hasClass('pickup-delivery')) { 678 log('[UnifiedManager] ð MetodÄ livrare detectatÄ (body class): pickup'); 679 return 'pickup'; 680 } 681 682 // Debug - aratÄ toate input-urile de delivery pentru diagnosticare 683 const $allDeliveryInputs = $('input[name*="delivery"], select[name*="delivery"]'); 684 if ($allDeliveryInputs.length) { 685 log('[UnifiedManager] ð§ Debug - toate input-urile delivery gÄsite:'); 686 $allDeliveryInputs.each(function() { 687 log(' -', $(this).attr('name'), '=', $(this).val(), 'checked:', $(this).is(':checked')); 688 }); 689 } 690 691 // Default: presupune cÄ e livrare acasÄ 692 log('[UnifiedManager] â ï¸ Nu s-a putut determina metoda de livrare - presupun livrare acasÄ'); 693 return 'home_delivery'; 694 }, 695 696 /** 697 * VerificÄ dacÄ existÄ erori de validare adresÄ 698 * @returns {boolean} true dacÄ existÄ erori de adresÄ 699 */ 700 hasAddressValidationErrors: function() { 701 // VerificÄ mesajele de eroare WooCommerce 702 const $errors = $('.woocommerce-error, .woocommerce-message--error'); 703 if ($errors.length > 0) { 704 const errorText = $errors.text().toLowerCase(); 705 if (errorText.includes('nu putem livra') ||
706 errorText.includes('cannot deliver') || 707 errorText.includes('select an address')) { 708 log('[UnifiedManager] â Eroare validare adresÄ detectatÄ:', errorText); 709 return true; 710 } 711 } 712 713 // VerificÄ cookie-ul CanDeliver (poate fi 'false' cu F mic sau 'False' cu F mare) 714 const canDeliver = this.getCookie('CanDeliver'); 715 if (canDeliver === 'false' || canDeliver === 'False') { 716 log('[UnifiedManager] â Cookie CanDeliver =', canDeliver); 717 // Ascunde secÈiunea place-order când adresa nu e validÄ 718 $('.form-row.place-order').hide(); 719 return true; 720 } else if (canDeliver === 'true' || canDeliver === 'True' || canDeliver === '') { 721 // AfiÈeazÄ secÈiunea place-order când adresa e validÄ sau neutrÄ 722 $('.form-row.place-order').show(); 723 } 724 725 return false; 726 }, 727 728 /** 729 * ObÈine valoarea unui cookie 730 * @param {string} name Numele cookie-ului 731 * @returns {string} Valoarea cookie-ului sau string gol 732 */ 733 getCookie: function(name) { 734 const nameEQ = name + "="; 735 // FIX: Split raw cookie string FIRST, then decode only the matched value. 736 // decodeURIComponent(document.cookie) breaks if ANY cookie has a raw '%'. 737 const cookies = document.cookie.split(';'); 738 739 for (let i = 0; i < cookies.length; i++) { 740 let c = cookies[i].trim(); 741 if (c.indexOf(nameEQ) === 0) { 742 const rawValue = c.substring(nameEQ.length); 743 try { 744 return decodeURIComponent(rawValue); 745 } catch (e) { 746 // Value contains malformed percent-encoding; return as-is 747 return rawValue; 748 } 749 } 750 } 751 return ""; 752 }, 753 754 /** 755 * Validare fallback pentru suma minimÄ când Horeka Core nu e disponibil 756 */ 757 validateMinimumOrderFallback: function() { 758 // CautÄ suma totalÄ Ã®n DOM 759 const $totalElement = $('.order-total .woocommerce-Price-amount, .total .amount'); 760 761 if (!$totalElement.length) { 762 log('[UnifiedManager] â ï¸ Nu s-a gÄsit elementul cu suma totalÄ'); 763 return true; // LasÄ sÄ treacÄ dacÄ nu gÄsim suma 764 } 765 766 // Extrage valoarea numericÄ din text 767 const totalText = $totalElement.text(); 768 const totalValue = parseFloat(totalText.replace(/[^\d,.-]/g, '').replace(',', '.')); 769 770 // Suma minimÄ default (poate fi configuratÄ) 771 const minimumAmount = (window.unifiedManagerConfig && window.unifiedManagerConfig.minimumOrderAmount) 772 ? parseFloat(window.unifiedManagerConfig.minimumOrderAmount) 773 : 50; 774 775 log('[UnifiedManager] ð° Validare fallback:', { 776 totalText: totalText, 777 totalValue: totalValue, 778 minimumAmount: minimumAmount, 779 isValid: totalValue >= minimumAmount 780 }); 781 782 if (totalValue >= minimumAmount) { 783 return true; 784 } else { 785 log('[UnifiedManager] ð Suma minimÄ nu e atinsÄ - disable silent fÄrÄ popup'); 786 return false; 787 } 788 }, 789 790 /** 791 * AfiÈeazÄ popup-ul pentru suma minimÄ (colaboreazÄ cu Horeka Core) 792 */ 793 showMinimumOrderPopup: function() { 794 // DacÄ Horeka Core are funcÈia pentru popup, o foloseÈte 795 if (typeof window.showMinimumOrderPopup === 'function') { 796 log('[UnifiedManager] ð¢ AfiÈez popup Horeka Core pentru suma minimÄ'); 797 window.showMinimumOrderPopup(); 798 return; 799 } 800 801 // Fallback: popup simplu 802 const message = 'Suma minimÄ pentru comandÄ nu este atinsÄ. Te rugÄm sÄ adaugi mai multe produse.'; 803 804 // VerificÄ dacÄ avem sweet alert sau alt sistem 805 if (typeof Swal !== 'undefined') { 806 Swal.fire({ 807 icon: 'warning', 808 title: 'SumÄ minimÄ necesarÄ', 809 text: message, 810 confirmButtonText: 'OK' 811 }); 812 } else { 813 // Fallback la alert browser 814 alert(message); 815 } 816 817 log('[UnifiedManager] ð¢ Am afiÈat popup fallback pentru suma minimÄ'); 818 }, 819 820 /** 821 * DezactiveazÄ butoanele când suma minimÄ nu e atinsÄ 822 */ 823 disableButtons: function() { 824 log('[UnifiedManager] ð« disableButtons() called'); 825 const $normalButton = $(CONFIG.SELECTORS.normalButton); 826 const $fakeButton = $(CONFIG.SELECTORS.fakeButton); 827 828 // Disable Èi stilizeazÄ butoanele 829 $normalButton 830 .prop('disabled', true) 831 .css({ 832 'opacity': '0.5', 833 'cursor': 'not-allowed', 834 'pointer-events': 'none' 835 }) 836 .addClass('button-disabled'); 837 838 $fakeButton 839 .prop('disabled', true) 840 .css({ 841 'opacity': '0.5', 842 'cursor': 'not-allowed', 843 'pointer-events': 'none' 844 }) 845 .addClass('button-disabled'); 846 847 log('[UnifiedManager] ð« Butoane disabled pentru sumÄ minimÄ'); 848 }, 849 850 /** 851 * ActiveazÄ butoanele când suma minimÄ este atinsÄ 852 */ 853 enableButtons: function() { 854 log('[UnifiedManager] â enableButtons() called'); 855 const $normalButton = $(CONFIG.SELECTORS.normalButton); 856 const $fakeButton = $(CONFIG.SELECTORS.fakeButton); 857 858 // Enable Èi reseteazÄ stilurile 859 $normalButton 860 .prop('disabled', false) 861 .css({ 862 'opacity': '1', 863 'cursor': 'pointer', 864 'pointer-events': 'auto' 865 }) 866 .removeClass('button-disabled'); 867 868 $fakeButton 869 .prop('disabled', false) 870 .css({ 871 'opacity': '1', 872 'cursor': 'pointer', 873 'pointer-events': 'auto' 874 }) 875 .removeClass('button-disabled'); 876 877 log('[UnifiedManager] â Butoane enabled - suma minimÄ atinsÄ'); 878 }, 879 880 /** 881 * ConfigureazÄ colaborarea perfectÄ cu Horeka Core 882 * SoluÈie hibridÄ: Horeka Core executÄ disable/enable, UnifiedManager sincronizeazÄ 883 */ 884 disableConflictingSystems: function() { 885 const self = this; 886 887 // SETEAZÄ FLAGS GLOBALE pentru autoritate partajatÄ 888 window.UNIFIED_MANAGER_IS_ACTIVE = true; 889 window.BUTTON_MANAGER_ACTIVE = 'hybrid'; 890 window.BUTTON_CONTROL_AUTHORITY = 'UnifiedManager+HorekaCore'; 891 892 log('[UnifiedManager] ð¤ Configurez colaborare hibridÄ cu Horeka Core'); 893 894 // STRATEGIA HIBRIDÄ: Permit Horeka Core sÄ facÄ disable/enable REAL 895 // dar sincronizez UnifiedManager cu aceste schimbÄri 896 897 // 1. NU bloca horekaButtonControlDisabled - permite Horeka Core sÄ lucreze 898 // Acest flag rÄmâne false pentru a permite Horeka Core sÄ execute logica 899 setTimeout(function() { 900 if (typeof window.horekaButtonControlDisabled !== 'undefined') { 901 // FORÈEZ false pentru a permite Horeka Core sÄ funcÈioneze 902 window.horekaButtonControlDisabled = false;
903 log('[UnifiedManager] ð Permit Horeka Core sÄ controleze butoanele (horekaButtonControlDisabled = false)'); 904 } 905 }, 100); 906 907 // 2. INTERCEPTARE INTELIGENTÄ: Horeka Core executÄ, UnifiedManager sincronizeazÄ 908 if (typeof window.disablePlaceOrderButton === 'function') { 909 const originalDisable = window.disablePlaceOrderButton; 910 window.disablePlaceOrderButton.unifiedManagerOriginal = originalDisable; 911 912 window.disablePlaceOrderButton = function(reason) { 913 log('[UnifiedManager] ð¨ Horeka Core cere disable butoane:', reason); 914 915 // 1. ExecutÄ ORIGINAL Horeka Core disable logic 916 originalDisable.apply(this, arguments); 917 918 // 2. Sincronizez UnifiedManager state 919 if (self && self.state) { 920 self.state.buttonsDisabledByHoreka = true; 921 self.state.horekaDisableReason = reason; 922 } 923 924 // 3. Apply UnifiedManager styling pentru consistenÈÄ 925 setTimeout(function() { 926 self.syncWithHorekaState('disabled', reason); 927 }, 50); 928 }; 929 } 930 931 if (typeof window.enablePlaceOrderButton === 'function') { 932 const originalEnable = window.enablePlaceOrderButton; 933 window.enablePlaceOrderButton.unifiedManagerOriginal = originalEnable; 934 935 window.enablePlaceOrderButton = function() { 936 log('[UnifiedManager] ð¨ Horeka Core cere enable butoane'); 937 938 // 1. ExecutÄ ORIGINAL Horeka Core enable logic 939 originalEnable.apply(this, arguments); 940 941 // 2. Sincronizez UnifiedManager state 942 if (self && self.state) { 943 self.state.buttonsDisabledByHoreka = false; 944 delete self.state.horekaDisableReason; 945 } 946 947 // 3. Apply UnifiedManager logic pentru toggle buttons 948 setTimeout(function() { 949 self.syncWithHorekaState('enabled'); 950 // Re-apply button toggle logic dacÄ e necesar 951 self.updateButtons(); 952 }, 50); 953 }; 954 } 955 956 // 3. PÄstreazÄ funcÈionalitatea checkPlaceOrderButtonState 957 if (typeof window.checkPlaceOrderButtonState === 'function') { 958 const originalCheck = window.checkPlaceOrderButtonState; 959 window.checkPlaceOrderButtonState.unifiedManagerOriginal = originalCheck; 960 961 // NU suprascriu aceastÄ funcÈie - o las sÄ funcÈioneze normal 962 // Horeka Core o va apela Èi va apela disable/enable care sunt deja interceptate 963 log('[UnifiedManager] â PÄstrez checkPlaceOrderButtonState original - Horeka Core va apela disable/enable interceptate'); 964 } 965 966 // 4. CheckoutButtonManager was removed in Task #011 - no longer needs deactivation 967 968 // 5. Flags pentru scripturile vechi 969 window.FAKE_CHECKOUT_TOGGLE_DISABLED = true; 970 window.BUTTON_MANAGER_DISABLED = true; 971 972 log('[UnifiedManager] â Colaborare hibridÄ configuratÄ: Horeka Core executÄ disable/enable, UnifiedManager sincronizeazÄ'); 973 }, 974 975 /** 976 * SincronizeazÄ UnifiedManager cu starea setatÄ de Horeka Core 977 */ 978 syncWithHorekaState: function(action, reason) { 979 log('[UnifiedManager] ð Sincronizez cu starea Horeka Core:', action); 980 981 const $normalButton = $(CONFIG.SELECTORS.normalButton); 982 const $fakeButton = $(CONFIG.SELECTORS.fakeButton); 983 984 if (action === 'disabled') { 985 // Horeka Core a disabled butoanele - asigur consistenÈa vizualÄ 986 987 // Adaug clase UnifiedManager pentru tracking 988 $normalButton.addClass('unified-disabled-by-horeka'); 989 $fakeButton.addClass('unified-disabled-by-horeka'); 990 991 // Asigur cÄ toggle logic nu interfereazÄ când butoanele sunt disabled 992 log('[UnifiedManager] ð Butoane disabled de Horeka Core - suspend toggle logic'); 993 994 } else if (action === 'enabled') { 995 // Horeka Core a enabled butoanele - pot continua cu toggle logic 996 997 // Elimin clase de tracking 998 $normalButton.removeClass('unified-disabled-by-horeka'); 999 $fakeButton.removeClass('unified-disabled-by-horeka'); 1000 1001 log('[UnifiedManager] ð Butoane enabled de Horeka Core - reiau toggle logic'); 1002 } 1003 }, 1004 1005 /** 1006 * Handler pentru rezultatul validÄrii din Horeka Core 1007 * AceastÄ funcÈie este apelatÄ automat când Horeka Core terminÄ validarea 1008 */ 1009 handleHorekaValidationResult: function(isValid) { 1010 log('[UnifiedManager] ð¨ Rezultat validare primit de la Horeka Core:', isValid); 1011 1012 if (isValid) { 1013 log('[UnifiedManager] â Validare OK - activez butoanele'); 1014 this.enableButtons(); 1015 } else { 1016 log('[UnifiedManager] ð Validare failed - dezactivez butoanele silent (fÄrÄ popup)'); 1017 this.disableButtons(); 1018 } 1019 }, 1020 1021 /** 1022 * SOLUÈIE PAYMENT PERSISTENCE: SalveazÄ alegerea utilizatorului 1023 * FuncÈie simplÄ care salveazÄ Ã®n localStorage Èi în state 1024 * @param {string} method - Metoda de platÄ selectatÄ (ex: 'netopiapayments', 'cod') 1025 */ 1026 saveUserPaymentChoice: function(method) { 1027 // SalvÄm în state intern pentru acces rapid 1028 this.state.userSelectedPaymentMethod = method; 1029 1030 // SOLUÈIE: MarcheazÄ cÄ utilizatorul a fÄcut o selecÈie în aceastÄ sesiune 1031 try { 1032 sessionStorage.setItem('horeka_user_made_selection', 'true'); 1033 } catch (e) { 1034 // Ignore sessionStorage errors 1035 } 1036 1037 // SalvÄm Èi în localStorage pentru persistenÈÄ Ã®ntre sesiuni 1038 // localStorage supravieÈuieÈte Èi dupÄ refresh paginÄ 1039 try { 1040 localStorage.setItem('horeka_user_payment_method', method); 1041 log('[UnifiedManager] ð¾ Salvat în localStorage (selecÈie utilizator):', method); 1042 } catch (e) { 1043 // DacÄ localStorage nu e disponibil, folosim doar state 1044 } 1045 }, 1046 1047 /** 1048 * SOLUÈIE PAYMENT PERSISTENCE: RestaureazÄ alegerea utilizatorului 1049 * Se apeleazÄ dupÄ fiecare update_checkout pentru a pÄstra selecÈia 1050 */ 1051 restoreUserPaymentChoice: function() { 1052 log('[UnifiedManager] ð Ãncerc restaurarea metodei de platÄ (timing optimizat)...'); 1053 1054 // VERIFICARE CRITICÄ: RestaurÄm DOAR dacÄ utilizatorul a fÄcut o selecÈie anterioarÄ 1055 if (!this.state.hasUserMadeSelection) { 1056 log('[UnifiedManager] â¹ï¸ Utilizatorul nu a fÄcut încÄ o selecÈie explicitÄ - nu restaurez nimic'); 1057 return; 1058 } 1059 1060 // Prioritate 1: ÃncercÄm din state (cel mai rapid) 1061 let savedMethod = this.state.userSelectedPaymentMethod; 1062 1063 // Prioritate 2: DacÄ nu e în state, încercÄm din localStorage 1064 if (!savedMethod) { 1065 try { 1066 savedMethod = localStorage.getItem('horeka_user_payment_method'); 1067 if (savedMethod) { 1068 log('[UnifiedManager] ð MetodÄ gÄsitÄ Ã®n localStorage:', savedMethod); 1069 // DacÄ gÄsim ceva în localStorage, înseamnÄ cÄ user-ul a avut o selecÈie anterioarÄ 1070 this.state.hasUserMadeSelection = true; 1071 } 1072 } catch (e) { 1073 // localStorage indisponibil 1074 } 1075 } 1076 1077 // DacÄ nu avem nimic salvat, nu facem nimic 1078 if (!savedMethod) { 1079 log('[UnifiedManager] â¹ï¸ Nicio metodÄ salvatÄ pe
1079ntru restaurare'); 1080 return; 1081 } 1082 1083 // VerificÄm dacÄ metoda salvatÄ mai existÄ Ã®n DOM 1084 // (poate fi indisponibilÄ dupÄ update datoritÄ logicii de business) 1085 const $savedMethodElement = $('input[name="payment_method"][value="' + savedMethod + '"]'); 1086 1087 if ($savedMethodElement.length === 0) { 1088 log('[UnifiedManager] â ï¸ Metoda salvatÄ nu mai e disponibilÄ:', savedMethod); 1089 return; 1090 } 1091 1092 // SetÄm flag pentru a nu salva din nou în timpul restaurÄrii 1093 this.state.isRestoringPayment = true; 1094 1095 // RestaurÄm selecÈia 1096 log('[UnifiedManager] â Restaurez metoda de platÄ:', savedMethod); 1097 1098 // 1. SetÄm radio button-ul 1099 $savedMethodElement.prop('checked', true).trigger('change'); 1100 1101 // 2. Pentru blue cards, triggeruim Èi click pe label 1102 const $blueCard = $('.blue-cards input[value="' + savedMethod + '"]'); 1103 if ($blueCard.length) { 1104 $blueCard.prop('checked', true); 1105 $blueCard.closest('label').addClass('active'); 1106 log('[UnifiedManager] ð³ Blue card restaurat pentru:', savedMethod); 1107 } 1108 1109 // 3. Pentru dropdown (dacÄ existÄ) 1110 const $dropdown = $('select[name="payment_method"]'); 1111 if ($dropdown.length) { 1112 $dropdown.val(savedMethod); 1113 log('[UnifiedManager] ð Dropdown restaurat pentru:', savedMethod); 1114 } 1115 1116 // ActualizÄm state-ul intern 1117 this.state.currentPaymentMethod = savedMethod; 1118 1119 // ResetÄm flag-ul dupÄ un delay mic 1120 const self = this; 1121 setTimeout(function() { 1122 self.state.isRestoringPayment = false; 1123 log('[UnifiedManager] â Restaurare completÄ, gata pentru noi schimbÄri'); 1124 }, 200); 1125 }, 1126 1127 /** 1128 * Helper pentru debounce - previne apelurile multiple rapide 1129 */ 1130 debounce: function(func, delay) { 1131 let timeoutId; 1132 return function() { 1133 const context = this; 1134 const args = arguments; 1135 clearTimeout(timeoutId); 1136 timeoutId = setTimeout(function() { 1137 func.apply(context, args); 1138 }, delay); 1139 }; 1140 }, 1141 1142 /** 1143 * Helper pentru logging - reduce spam în console 1144 */ 1145 shouldLog: function() { 1146 const now = Date.now(); 1147 1148 // Log primele 3 toggle-uri 1149 if (this.state.toggleCount < 3) { 1150 return true; 1151 } 1152 1153 // DupÄ aceea, log doar la 2 secunde interval 1154 if (now - this.state.lastToggleTime > 2000) { 1155 this.state.lastToggleTime = now; 1156 return true; 1157 } 1158 1159 return false; 1160 }, 1161 1162 /** 1163 * FuncÈii pentru debugging 1164 */ 1165 debug: function() { 1166 1167 1168 } 1169 }; 1170 1171 // ======================================== 1172 // INIÈIALIZARE AUTOMATÄ 1173 // ======================================== 1174 1175 // AÈteaptÄ jQuery Èi DOM ready 1176 $(document).ready(function() { 1177 // VerificÄ dacÄ nu a fost dezactivat manual 1178 if (!window.UNIFIED_MANAGER_DISABLED) { 1179 // Delay mic pentru a permite altor scripturi sÄ se încarce 1180 setTimeout(function() { 1181 window.UnifiedButtonManager.init(); 1182 }, 100); 1183 } 1184 1185 // SOLUÈIE PAYMENT PERSISTENCE: Cleanup dupÄ plasarea comenzii 1186 // CurÄÈÄm metoda salvatÄ când suntem pe pagina de confirmare comandÄ 1187 if ($('body').hasClass('woocommerce-order-received')) { 1188 log('[UnifiedManager] ð§¹ ComandÄ plasatÄ - curÄÈ metoda de platÄ salvatÄ'); 1189 try { 1190 localStorage.removeItem('horeka_user_payment_method'); 1191 } catch (e) { 1192 // IgnorÄm erorile de localStorage 1193 } 1194 } 1195 }); 1196
1197 // Expune funcÈia de debug global 1198 window.debugUnifiedManager = function() { 1199 window.UnifiedButtonManager.debug(); 1200 }; 1201 1202 // Script încÄrcat - foloseÈte debugUnifiedManager() pentru debug 1203 1204})(jQuery);
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.