1var myItems = {}; 2var products = []; 3var allProducts = []; 4var productsArr = {}; 5var bestDealsIDs = []; 6var allCoupons = ''; 7 8// Simplified URL parameter function 9const getUrlParameter = (param) => new URLSearchParams(window.location.search).get(param); 10 11// Open or create the IndexedDB 12function openDB() { 13 return new Promise((resolve, reject) => { 14 const request = indexedDB.open("productsDB", 2); 15 16 request.onerror = (event) => { 17 console.log("Error opening database", event); 18 reject(event); 19 }; 20 21 request.onsuccess = (event) => { 22 const db = event.target.result; 23 resolve(db); 24 }; 25 26 request.onupgradeneeded = (event) => { 27 const db = event.target.result; 28 if (!db.objectStoreNames.contains("jsonStore")) { 29 db.createObjectStore("jsonStore", { autoIncrement: true }); 30 } 31 }; 32 }); 33} 34 35// Get data from IndexedDB by ID 36async function getDataFromIndexedDB(id) { 37 const db = await openDB(); // Open the database 38 39 return new Promise((resolve, reject) => { 40 const transaction = db.transaction(["jsonStore"], "readonly"); // Open a readonly transaction 41 const objectStore = transaction.objectStore("jsonStore"); // Access the object store 42 const request = objectStore.get(id); // Get data by id 43 44 request.onsuccess = (event) => { 45 const data = event.target.result; 46 resolve(data); // Resolve with the retrieved data 47 }; 48 49 request.onerror = (event) => { 50 console.error("Error retrieving data from IndexedDB", event); 51 reject(event); // Reject with the error 52 }; 53 }); 54} 55 56// Add or update data in IndexedDB with a timestamp 57function addDataToIndexedDB(key, data) { 58 return openDB().then(db => { 59 return new Promise((resolve, reject) => { 60 const transaction = db.transaction(["jsonStore"], "readwrite"); 61 const objectStore = transaction.objectStore("jsonStore"); 62 63 // Add a timestamp to the data 64 const record = { 65 products: data.products, 66 timestamp: Date.now() // Store the current time 67 }; 68 69 const request = objectStore.put(record, key); 70 71 request.onsuccess = () => resolve(); 72 request.onerror = (event) => { 73 console.error("Error adding data to IndexedDB", event); 74 reject(event); 75 }; 76 }); 77 }); 78} 79 80function deleteDataFromIndexedDB(id) { 81 return openDB().then(db => { 82 return new Promise((resolve, reject) => { 83 const transaction = db.transaction(["jsonStore"], "readwrite"); 84 const objectStore = transaction.objectStore("jsonStore"); 85 86 const request = objectStore.delete(id); 87 88 request.onsuccess = () => { 89 console.log(`Record with id ${id} deleted successfully`); 90 resolve(); 91 }; 92 93 request.onerror = (event) => { 94 console.error(`Error deleting record with id ${id} from IndexedDB`, event); 95 reject(event); 96 }; 97 }); 98 }); 99} 100 101// Delete all records from IndexedDB 102function deleteAllDataFromIndexedDB() { 103 return openDB().then(db => { 104 return new Promise((resolve, reject) => { 105 const transaction = db.transaction(["jsonStore"], "readwrite"); 106 const objectStore = transaction.objectStore("jsonStore"); 107 108 const request = objectStore.clear(); // Clear all records 109 110 request.onsuccess = () => { 111 console.log("All records deleted successfully"); 112 resolve(); 113 }; 114 115 request.onerror = (event) => { 116 console.error("Error deleting all records from IndexedDB", event); 117 reject(event); 118 }; 119 }); 120 }); 121} 122 123async function clearAllIndexedDBData() { 124 const db = await openDB(); 125 const transaction = db.transaction(["jsonStore"], "readwrite"); 126 const objectStore = transaction.objectStore("jsonStore"); 127 128 return new Promise((resolve, reject) => { 129 const clearRequest = objectStore.clear(); 130 131 clearRequest.onsuccess = () => { 132 console.log("All records cleared from IndexedDB"); 133 resolve(); 134 }; 135 136 clearRequest.onerror = (event) => { 137 console.error("Error clearing IndexedDB records", event); 138 reject(event); 139 }; 140 });
141} 142 143// Fetch data from the server 144function fetchDataFromServer( params ) { 145 return jQuery.ajax({ 146 type: 'GET', 147 url: sitedata.svt_ajax_url, 148 data: params, 149 dataType: 'json', 150 cache: true, 151 }); 152} 153 154// Check if the data is expired (older than 15 minutes) 155function isDataExpired(timestamp) { 156 if(typeof timestamp == "undefined") { 157 return true; 158 } 159 const currentTime = Date.now(); 160 const timeDiff = (currentTime - timestamp) / (1000 * 60); // Time difference in minutes 161 return timeDiff > 15; // Return true if more than 15 minutes have passed 162} 163 164// Check data from IndexedDB and fetch from server if expired or not found 165async function checkAndFetchData(id) { 166 try { 167 const dataRecord = await getDataFromIndexedDB(id); 168 const currentTimestamp = Date.now(); // Use current time for comparison 169 170 // Prepare the parameters for server fetch 171 const params = { 172 action: 'list_products_json' 173 }; 174 175 if (id === 'cateringProducts') { 176 params.priceListID = getCookie('cateringPriceListID'); 177 } else if (id === 'myItems') { 178 params.action = 'get_my_items'; 179 } 180 181 if (dataRecord) { 182 const { products, timestamp } = dataRecord; 183 184 // Check if the data has expired (15 minutes) 185 /*if (isDataExpired(timestamp, currentTimestamp)) { 186 return await updateData(id, params); 187 }*/ 188 189 // Data is valid 190 if (products) { 191 return products; 192 } else { 193 console.log(`${id} is null. Fetching from server...`); 194 return await updateData(id, params); 195 } 196 } else { 197 console.log(`${id} data not found in IndexedDB. Fetching from server...`); 198 return await updateData(id, params); 199 } 200 } catch (error) { 201 console.error("Error:", error); 202 } 203} 204 205// Helper function to update data 206async function updateData(id, params) { 207 const serverData = await fetchDataFromServer(params); 208 if (serverData.products) { 209 if (typeof serverData.products === "string") { 210 serverData.products = JSON.parse(serverData.products); 211 } 212 await addDataToIndexedDB(id, serverData); 213 } 214 return serverData.products; // Return the fetched data 215} 216 217 218function formatPrice(priceStr, unit, avgWeight) { 219 // Remove $ sign 220 let clean = priceStr.replace('$', '').trim(); 221 222 if(avgWeight) { 223 clean = (parseFloat(clean) * avgWeight); 224 clean = (clean.toFixed(2)).toString(); 225 } 226 227 // Split into dollars + cents 228 let [dollars, cents] = clean.split('.'); 229 230 // Default cents if missing 231 cents = cents || "00"; 232 233 // If price is less than $1 ââ â show only cents (e.g., 0.69 ââ â 69â) 234 if (Number(dollars) === 0) { 235 return ` 236 <div class="svt-product-org-price under-1"> 237 <span class="price-dollar">${cents}</span> 238 <span class="price-currency">¢${(unit) ? '/'+unit : ''}</span> 239 </div> 240 `; 241 } 242 243 // Normal price format 244 return ` 245 <div class="svt-product-org-price"> 246 <span class="price-currency">$</span> 247 <span class="price-dollar">${dollars}</span> 248 <span class="price-cents">${cents}${(unit) ? '/'+unit : ''}</span> 249 </div> 250 `; 251} 252 253function isFreePromo(promo) { 254 return promo 255 && typeof promo === 'object' 256 && promo.tag 257 && promo.tag.toLowerCase() === 'free'; 258} 259 260function isTprPromo(promo) { 261 return promo 262 && typeof promo === 'object' 263 && !isFreePromo(promo) 264 && typeof promo.salePrice === 'number' 265 && promo.salePrice > 0; 266} 267 268function isComplexPromo(promo) { 269 return promo 270 && typeof promo === 'object' 271 && !isFreePromo(promo) 272 && !isTprPromo(promo); 273} 274 275function getGridPromotionsForProduct(promotions, productName) { 276 const promoList = 277 promotions?.items?.[productName]?.primary || []; 278 279 if (!Array.isArray(promoList) || promoList.length === 0) { 280 return { free: null, tpr: null, complex: null }; 281 } 282 283 // free promo will always be first (as per BE contract) 284 const freePromo = isFreePromo(promoList[0]) 285 ? promoList[0] 286 : null; 287 288 const firstTpr = promoList.find(p => isTprPromo(p)) || null; 289 const firstComplex = promoList.find(p => isComplexPromo(p)) || null; 290 291 return { 292 free: freePromo, 293 tpr: firstTpr, 294 complex: firstComplex 295 }; 296} 297 298function getSalePrice(product, promos) { 299 const { complex, tpr, free } = promos; 300 301 if(free) { 302 return 'FREE'; 303 } 304 305 // 1. Try complex sale price first 306 if (complex?.salePrice) { 307 return complex.salePrice; 308 } 309 310 // 2.If complex exists but has NO sale price, fallback to TPR price 311 if (complex && tpr?.salePrice) { 312 return tpr.salePrice; 313 } 314 315 // 3.Otherwise just use TPR (no complex at all) 316 if (tpr?.salePrice) { 317 return tpr.salePrice; 318 } 319 320 // 4.fallback to regular price 321 return product.regularPrice; 322} 323 324 325function buildStyledPromoHTML(styledTagLb, promoID) { 326 const promoHTML = styledTagLb.map(tagGroup => { 327 let prevText = ""; 328 329 const inner = tagGroup.map(tagData => { 330 const tag = tagData[0]; 331 const currentText = tag.text; 332 333 let addMargin = false; 334 const prevEnds = prevText.slice(-1); 335 const currStarts = currentText[0]; 336 337 addMargin = 338 prevText && 339 /[A-Za-z0-9]$/.test(prevEnds) && 340 /[A-Za-z0-9]/.test(currStarts) && 341 prevEnds !== "/" && 342 currStarts !== "$"; 343 344 prevText = currentText; 345 346 return `
347 <span class="promo-${tag.weight} promo-${tag.size}" 348 style="${addMargin ? 'margin-left:4px;' : ''}"> 349 ${currentText} 350 </span> 351 `; 352 }).join(""); 353 354 return `<span class="svt-promo-label">${inner}</span>`; 355 }).join(""); 356 357 return ` 358 <div class="svt-product-new-promo-wrap"> 359 <div class="svt-product-new-promo svt-promotion-link" data-id="${promoID}"> 360 ${promoHTML} 361 </div> 362 </div> 363 `; 364} 365 366function filterUsableCoupons(coupons) { 367 if (!Array.isArray(coupons)) return []; 368 369 return coupons.filter(coupon => 370 coupon?.isclippable || coupon?.isclipped 371 ); 372} 373 374function couponAppliesToUpc(coupon, upc, productMap) { 375 if (!coupon || !Array.isArray(coupon.upcs)) return false; 376 if (!upc) return false; 377 378 const regex = /^02\d{5}0{5}\d$/; 379 380 // Normalize the incoming UPC the same way 381 function normalize(upcID) { 382 let id = regex.test(upcID) ? upcID.slice(1, 7) : upcID; 383 384 if (id.length > 6) { 385 id = id.replace(/^0+/, '').slice(0, -1); 386 } 387 388 return id; 389 } 390 391 const target = normalize(upc); 392 393 return coupon.upcs.some(upcID => { 394 const normalized = normalize(upcID); 395 396 // If you're matching against productMap like your snippet 397 if (productMap) { 398 const product = productMap.get(normalized); 399 return product && normalized === target; 400 } 401 402 // fallback: compare normalized UPC values directly 403 return normalized === target; 404 }); 405} 406 407function couponAppliesToMerchandiseDepartmentCode(coupon, code) { 408 if (!coupon || !Array.isArray(coupon.merchandiseDepartmentCodes)) return false; 409 if (!code) return false; 410 411 return coupon.merchandiseDepartmentCodes.includes(code); 412} 413 414function couponAppliesToProduct(coupon, product) { 415 if (!coupon || !product) return false; 416 417 return ( 418 couponAppliesToUpc(coupon, product.upc) || 419 couponAppliesToMerchandiseDepartmentCode( 420 coupon, 421 product.merchandiseDepartmentCode 422 ) 423 ); 424} 425 426function filterApplicableCouponsForProduct(product, coupons) { 427 if ( 428 !product || 429 (!product.upc && !product.merchandiseDepartmentCode) || 430 !Array.isArray(coupons) || 431 coupons.length === 0 432 ) { 433 return []; 434 } 435 436 return coupons.filter(coupon => 437 couponAppliesToProduct(coupon, product) 438 ); 439} 440 441function getGridCouponForProduct(product, coupons) { 442 if (!product || !Array.isArray(coupons) || coupons.length === 0) { 443 return null; 444 } 445 446 const applicable = filterApplicableCouponsForProduct(product, coupons); 447 const usable = filterUsableCoupons(applicable); 448 449 return usable.length > 0 ? usable[0] : null; 450} 451 452function getGridCouponHTML( product, coupon ) { 453 if(!coupon) return ''; 454 const user = JSON.parse(localStorage.getItem('user')); 455 var pointsRequired = coupon.pointrequirement; 456 let couponHTML = ''; 457 var points = 0; 458 if(user != null) { 459 points = user.loyaltyAccount.pointbalance; 460 } 461 if(pointsRequired == null) { 462 pointsRequired = 0; 463 } 464 let confirmationPopup = ''; 465 if(pointsRequired) { 466 confirmationPopup = ` 467 <div class="svt-list-point-confirmation-popup"> 468 <div class="svt-list-point-confirmation-popup-text"> 469 Clipping this coupon will use ${pointsRequired} reward points. Do you want to continue? 470 </div> 471 <div class="svt-list-point-confirmation-popup-actions"> 472 <a href="javascript:void(0);" class="cancel-list-coupon">Cancel</a> 473 <a href="javascript:void(0);" class="confirm-list-coupon">Confirm</a> 474 </div> 475 </div> 476 `; 477 } 478 const checked = coupon.isclipped ? 'checked="checked"' : ''; 479 if(pointsRequired <= points) { 480 couponHTML = ` 481 <div class="svt-list-item-coupon"> 482 <div class="svt-custom-checkbox"> 483 <input type="checkbox" id="coupon_${product.name}_${coupon.couponid}" name="coupon_${coupon.couponid}" value="${coupon.couponid}" ${checked}>
484 <span class="checkmark"></span> 485 <label class="svt-custom-checkbox-lable" for="coupon_${product.name}_${coupon.couponid}"> 486 ${coupon.title} 487 </label> 488 </div> 489 ${confirmationPopup} 490 </div> 491 `; 492 } 493 return couponHTML; 494} 495 496 497function loadProductCoupons() { 498 const coupons = JSON.parse(sessionStorage.getItem('buyAgainCoupons')) || []; 499 const user = JSON.parse(localStorage.getItem('user')); 500 501 let productsData = allProducts.products || []; 502 let productMap = new Map(); 503 504 productsData.forEach(product => { 505 let productUpc = product.upc; 506 507 if (productUpc && productUpc.length > 6) { 508 productUpc = productUpc.replace(/^0+/, '').slice(0, -1); 509 } 510 511 productMap.set(productUpc, product); 512 }); 513 514 // Loop all products instead of coupons 515 productMap.forEach((product) => { 516 const coupon = getGridCouponForProduct(product, coupons); 517 518 if (!coupon) return; 519 520 const productID = product.name; 521 const $box = jQuery('.svt-product-box[data-id="' + productID + '"]'); 522 523 if ($box.length === 0) return; 524 525 let pointsRequired = coupon.pointrequirement || 0; 526 let points = user?.loyaltyAccount?.pointbalance || 0; 527 528 let confirmationPopup = ""; 529 530 if (pointsRequired) { 531 confirmationPopup = ` 532 <div class="svt-list-point-confirmation-popup"> 533 <div class="svt-list-point-confirmation-popup-text"> 534 Clipping this coupon will use ${pointsRequired} reward points. Do you want to continue? 535 </div> 536 <div class="svt-list-point-confirmation-popup-actions"> 537 <a href="javascript:void(0);" class="cancel-list-coupon">Cancel</a> 538 <a href="javascript:void(0);" class="confirm-list-coupon">Confirm</a> 539 </div> 540 </div> 541 `; 542 } 543 544 const checked = coupon.isclipped ? 'checked="checked"' : ''; 545 546 let couponHTML = ""; 547 548 if (pointsRequired <= points) { 549 couponHTML = ` 550 <div class="svt-list-item-coupon"> 551 <div class="svt-custom-checkbox"> 552 <input type="checkbox" 553 id="coupon_${product.name}_${coupon.couponid}" 554 name="coupon_${product.name}_${coupon.couponid}" 555 value="${coupon.couponid}" 556 ${checked}> 557 558 <span class="checkmark"></span> 559 560 <label class="svt-custom-checkbox-lable" 561 for="coupon_${product.name}_${coupon.couponid}"> 562 ${coupon.title} 563 </label> 564 </div> 565 566 ${confirmationPopup} 567 </div> 568 `; 569 } 570 571 $box.find(".svt-product-coupon-wrap").html(couponHTML); 572 }); 573} 574 575function getWeightUnit() { 576 const location = JSON.parse(localStorage.getItem('ls.location')); 577 return location.weightUnit || 'lb'; 578} 579 580function isFloat(n) { 581 return typeof n === 'number' && !Number.isInteger(n); 582} 583 584function getStyledPriceRangeFromZeroPriceTag(tag) { 585 if (tag == '') return null; 586 587 var match = tag.match(/^\s*\$?\s*([\d,]+(?:\.\d{1,2})?)\s*-\s*\$?\s*([\d,]+(?:\.\d{1,2})?)\s*$/); 588 if (!match) return null; 589 590 var min = parseFloat(match[1].replace(/,/g, '')); 591 var max = parseFloat(match[2].replace(/,/g, '')); 592 593 if (min < 0 || max < 0) return null; 594 595 return { 596 min: formatPrice(min.toString()), 597 max: formatPrice(max.toString()), 598 }; 599} 600 601function renderProductCard( product, promotions, pricelist, pListName, screenName = 'Home' ) { 602 var html = ''; 603 var productID = product.name; 604 let productTitle = product.displayName; 605 var promoText = ''; 606 var promoSalePrice = ''; 607 var promoID = ''; 608 var showEligibleItems = true; 609 var imgName = product.mainImage; 610 if(typeof imgName == "undefined" || imgName == null) { 611 imgName = productID; 612 } 613 var productImg = 'https://s3-us-west-2.amazonaws.com/www.gethomesome.com/productimages_tn/'+imgName+'.jpg'; 614 let productPromoHTML = ''; 615 // console.log(promotions); 616 let promo = null; 617 618 const gridPromos = getGridPromotionsForProduct(promotions, productID); 619 620 const activePromo = 621 gridPromos.complex || 622 gridPromos.tpr || 623 gridPromos.free || 624 null; 625 626 // FREE or TPR â no eligible items 627 if (gridPromos.free || gridPromos.tpr) { 628 showEligibleItems = false; 629 } 630 631 // COMPLEX â show eligible items 632 if (gridPromos.complex) { 633 showEligibleItems = true; 634 } 635 636 if (activePromo) { 637 promoID = activePromo.id; 638 promoText = activePromo.tag; 639 promoSalePrice = getSalePrice(product, gridPromos)|| ''; 640 } 641 642 if (activePromo && promoID) { 643 const promoObj = promotions?.promotions?.[promoID]; 644 645 if (Array.isArray(promoObj?.styledTagLb)) { 646 productPromoHTML = buildStyledPromoHTML(promoObj.styledTagLb, promoID); 647 } 648 } 649 650 var activeQty = ''; 651 var activeMinus = ''; 652 var qtyVal = 1; 653 var unitQty = product.unitQuantity; 654 655 let price = product.price; 656 657 if(typeof unitQty == "undefined" || unitQty == null) { 658 unitQty = 1; 659 } 660 661 let weightUnit = getWeightUnit(); 662 663 let weightInPrice = weightUnit; 664 665 let unitIncrement = 1; 666 667 if(product.unit == weightUnit) { 668 unitIncrement = product?.unitIncrement || 0.5; 669 unitQty = unitIncrement; 670 if(promoText != '') { 671 promoText += ' /'+weightUnit; 672 } 673 } 674 675 let avgWeight = ''; 676 677 let eaEstimate = ''; 678 679 if(product.unit == weightUnit && product.sellByQty == true && promoSalePrice !== 'FREE') { 680 avgWeight = product.avgWeight; 681 weightInPrice = ''; 682 eaEstimate = ' ea (est.)'; 683 unitQty = 1; 684 unitIncrement = 1; 685 productTitle += ` (${unitQty} Count)`; 686 } 687 688 if(product.unit != weightUnit) { 689 weightInPrice = ''; 690 } 691 692 693 var redirectPDP = (product.hasModifiers) == false ? '#' : sitedata.pdpurl+'?product='+product.name; 694 // redirectPDP = sitedata.pdpurl+'?product='+product.name; 695 qtyVal = unitQty; 696 697 if(product.minQuantity > 0) { 698 qtyVal = product.minQuantity; 699 } 700 701 let escapedData = JSON.stringify(product).replace(/'/g, "'"); 702 703 var isFav = ''; 704 705 var basket = localStorage.getItem('basket'); 706 if(typeof pricelist != "undefined" && pricelist != null) { 707 basket = localStorage.getItem('basket_'+pricelist); 708 } 709
710 if(basket != null) { 711 basket = JSON.parse(basket); 712 let items = []; 713 if(typeof basket.items != "undefined") { 714 items = basket.items; 715 } 716 else if(typeof basket.basketItems != "undefined") { 717 items = basket.basketItems; 718 } 719 var productInBasket = items.filter(obj => obj.name == productID); 720 if(productInBasket.length) { 721 qtyVal = productInBasket[0].quantity; 722 activeQty = 'active-qty'; 723 if(qtyVal > 1) { 724 if(product.minQuantity > 0) { 725 if(qtyVal > product.minQuantity) { 726 activeMinus = ' active-minus'; 727 } 728 } 729 else { 730 activeMinus = ' active-minus'; 731 } 732 } 733 } 734 else { 735 activeQty = ''; 736 } 737 } 738 739 if(Object.keys(myItems).length) { 740 var productIDS = Object.keys(myItems); 741 if(productIDS.includes(productID)) { 742 isFav = 'in-fav'; 743 } 744 } 745 746 var cat = sanitizeTitle(product.type); 747 748 if(typeof pricelist == "undefined" || pricelist == null) { 749 pricelist = ''; 750 } 751 752 if(typeof pListName == "undefined" || pListName == null) { 753 pListName = ''; 754 } 755 756 var pdpLink = embeddata.product+'?product='+productID; 757 758 if(pListName) { 759 pdpLink += '&pListName='+pListName; 760 } 761 762 let ebtEnabled = false; 763 764 const location = JSON.parse(sessionStorage.getItem('ls.location')); 765 766 if(location != null) { 767 if(typeof location.ebtConfig != "undefined") { 768 if(location.ebtConfig.enabled == true && product.ebtSnapEligible == true) { 769 ebtEnabled = true; 770 } 771 } 772 } 773 774 let isZeroPrice = false; 775 776 var zeroPriceObj = {}; 777 778 if(price == 0 && product.zeroPriceTag != '' && product.zeroPriceInfo != '') { 779 isZeroPrice = true; 780 zeroPriceObj = getStyledPriceRangeFromZeroPriceTag(product.zeroPriceTag); 781 } 782 783 let isInStock = product.isInStock; 784 785 let priceFormatted = price; 786 787 if(priceFormatted != 'Free') { 788 priceFormatted = formatPrice(parseFloat(priceFormatted).toFixed(2), weightInPrice, avgWeight); 789 } 790 791 if(promoText == 'free') { 792 promoSalePrice = 'FREE'; 793 } 794 795 let couponHTML = ''; 796 const loggedIn = isUserLoggedIn(); 797 if(loggedIn) { 798 const coupons = JSON.parse(sessionStorage.getItem('buyAgainCoupons')); 799 const couponData = getGridCouponForProduct(product, coupons); 800 couponHTML = getGridCouponHTML( product, couponData ); 801 } 802 803 html += '<div class="svt-product-box '+cat+' '+isFav+'" data-id="'+productID+'">'+ 804 '<div class="svt-product-img-wrap">'+ 805 '<a href="javascript:void(0);" class="open-pdp" data-id="'+productID+'" data-pricelist="'+pricelist+'" aria-hidden="true" aria-label="'+productTitle+'">'+ 806 '<img src="'+productImg+'" onerror="this.onerror=null; this.className=\'placeholder-img\'; this.src=\''+embeddata.theme_url+'/images/nophoto-v2.svg\'" alt="'+productTitle+'" />'+ 807 '</a>'+ 808 '<a href="javascript:void(0);" class="svt-product-favourite" data-id="'+productID+'" aria-hidden="true" aria-label="Add to My Items">'+ 809 '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M19 21L12 16L5 21V5C5 4.46957 5.21071 3.96086 5.58579 3.58579C5.96086 3.21071 6.46957 3 7 3H17C17.5304 3 18.0391 3.21071 18.4142 3.58579C18.7893 3.96086 19 4.46957 19 5V21Z" stroke="#767676" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" /></svg>'+ 810 '</a>'+ 811 '<a href="javascript:void(0);" class="svt-product-list-remove" data-id="'+productID+'" aria-hidden="true" aria-label="Remove from My Items">'+ 812 '<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M19 21L12 16L5 21V5C5 4.46957 5.21071 3.96086 5.58579 3.58579C5.9
8126086 3.21071 6.46957 3 7 3H17C17.5304 3 18.0391 3.21071 18.4142 3.58579C18.7893 3.96086 19 4.46957 19 5V21Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" /></svg>'+ 813 //'<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 10.25C10.4142 10.25 10.75 10.5858 10.75 11V17C10.75 17.4142 10.4142 17.75 10 17.75C9.58579 17.75 9.25 17.4142 9.25 17V11C9.25 10.5858 9.58579 10.25 10 10.25Z" fill="#767676" /><path d="M14.75 11C14.75 10.5858 14.4142 10.25 14 10.25C13.5858 10.25 13.25 10.5858 13.25 11V17C13.25 17.4142 13.5858 17.75 14 17.75C14.4142 17.75 14.75 17.4142 14.75 17V11Z" fill="#767676" /><path fill-rule="evenodd" clip-rule="evenodd" d="M7.25 5.25V4C7.25 3.27065 7.53973 2.57118 8.05546 2.05546C8.57118 1.53973 9.27065 1.25 10 1.25H14C14.7293 1.25 15.4288 1.53973 15.9445 2.05546C16.4603 2.57118 16.75 3.27065 16.75 4V5.25H21C21.4142 5.25 21.75 5.58579 21.75 6C21.75 6.41421 21.4142 6.75 21 6.75H19.75V20C19.75 20.7293 19.4603 21.4288 18.9445 21.9445C18.4288 22.4603 17.7293 22.75 17 22.75H7C6.27065 22.75 5.57118 22.4603 5.05546 21.9445C4.53973 21.4288 4.25 20.7293 4.25 20V6.75H3C2.58579 6.75 2.25 6.41421 2.25 6C2.25 5.58579 2.58579 5.25 3 5.25H7.25ZM9.11612 3.11612C9.35054 2.8817 9.66848 2.75 10 2.75H14C14.3315 2.75 14.6495 2.8817 14.8839 3.11612C15.1183 3.35054 15.25 3.66848 15.25 4V5.25H8.75V4C8.75 3.66848 8.8817 3.35054 9.11612 3.11612ZM5.75 6.75H18.25V20C18.25 20.3315 18.1183 20.6495 17.8839 20.8839C17.6495 21.1183 17.3315 21.25 17 21.25H7C6.66848 21.25 6.35054 21.1183 6.11612 20.8839C5.8817 20.6495 5.75 20.3315 5.75 20V6.75Z" fill="#767676" /></svg>'+ 814 '</a>'; 815 if(ebtEnabled) { 816 html += '<div class="ebt-badge-container">'+ 817 '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">'+ 818 '<path d="M10.4685 10.3573H12.1049C12.3163 10.3573 12.5191 10.435 12.6686 10.5732C12.8181 10.7113 12.9021 10.8988 12.9021 11.0942C12.9021 11.2896 12.8181 11.477 12.6686 11.6152C12.5191 11.7534 12.3163 11.831 12.1049 11.831H10.4685V10.3573Z" fill="#767676"></path>'+ 819 '<path d="M12.7343 14.6427H10.4685V13.1302H12.7343C12.838 13.1276 12.9411 13.1442 13.0378 13.1791C13.1344 13.214 13.2224 13.2665 13.2968 13.3334C13.3711 13.4002 13.4301 13.4802 13.4704 13.5685C13.5108 13.6569 13.5315 13.7518 13.5315 13.8476C13.5402 13.9492 13.526 14.0513 13.4898 14.1475C13.4537 14.2437 13.3964 14.332 13.3214 14.4067C13.2465 14.4814 13.1557 14.5409 13.0546 14.5816C12.9535 14.6222 12.8445 14.643 12.7343 14.6427Z" fill="#767676"></path>'+ 820 '<path fill-rule="evenodd" clip-rule="evenodd" d="M2 4C0.895431 4 0 4.89543 0 6V18C0 19.1046 0.89543 20 2 20H22C23.1046 20 24 19.1046 24 18V6C24 4.89543 23.1046 4 22 4H2ZM6.82843 10.1586C6.71858 10.2858 6.56958 10.3573 6.41423 10.3573H4.13807V11.831H5.25941C5.40645 11.8304 5.54831 11.8939 5.65683 12.0088C5.76535 12.1238 5.83259 12.2818 5.84519 12.4515C5.84519 12.6315 5.78347 12.8041 5.67362 12.9314C5.56377 13.0587 5.41477 13.1302 5.25941 13.1302H4.13807V14.6427H6.41423C6.56958 14.6427 6.71858 14.7142 6.82843 14.8414C6.93828 14.9687 7 15.1413 7 15.3213C7 15.5013 6.93828 15.6739 6.82843 15.8012C6.71858 15.9285 6.56958 16 6.41423 16H3.58577C3.43536 15.9975 3.29153 15.9281 3.1841 15.8061C3.07015 15.6788 3.00402 15.5047 3 15.3213V9.67867C3 9.49868 3.06172 9.32605 3.17157 9.19878C3.28142 9.0715 3.43042 9 3.58577 9H6.41423C6.56958 9 6.71858 9.0715 6.82843 9.19878C6.93828 9.32605 7 9.49868 7 9.67867C7 9.85867 6.93828 10.0313 6.82843 10.1586ZM13.972 12.1994C14.2049 11.9047 14.3431 11.5552 14.3706 11.1911C14.3848 10.9081 14.3367 10.6253 14.2292 10.3599C14.1217 10.0945 13.9571 9.85209 13.7453 9.64724C13.5334 9.4424 13.2788 9.27941 12.9969 9.16816C12.7149 9.0569 12.4115 8.9997 12.1049 9H9.73427C9.53953 9 9.35276 9.0715 9.21506 9.19878C9.07736 9.32606 9 9.49868 9 9.67867V15.3213C9 15.5013 9.07736 15.6739 9.21506 15.8012C9.35276 15.9285 9.53953 16 9.73427 16H12.7343C13.3352 16 13.9115 15.7794 14.3364 15.3866C14.7613 14.9939 15 14.4612 15 13.9058C14.9898 13.5659 14.891 13.2334 14.712 12.9363C14.5331 12.6392 14.2792 12.3865 13.972 12.1994ZM16.1878 9.19878C16.308 9.0715 16.471 9 16.641 9H20.359C20.529 9 20.692 9.0715 20.8122 9.19878C20.9325 9.32605 21 9.49868 21 9.67867C21 9.85867 20.9325 10.0313 20.8122 10.1586C20.692 10.2858 20.529 10.3573 20.359 10.3573H19.1319V15.3213C19.1319 15.5013 19.0643 15.6739 18.9441 15.8012C18.8239 15.9285 18.6609 16 18.4908 16C18.3208 16 18.1578 15.9285 18.0376 15.8012C17.9174 15.6739 17.8498 15.5013 17.8498 15.3213V10.3573H16.641C16.471 10.3573 16.308 10.2858 16.1878 10.1586C16.0675 10.0313 16 9.85867 16 9.67867C16 9.49868 16.
8200675 9.32605 16.1878 9.19878Z" fill="#767676"></path>'+ 821 '</svg>'+ 822 '<span style="display:none;">EBT Eligible</span>'+ 823 '</div>'; 824 } 825 if(isInStock) { 826 html += 827 '<div class="svt-product-add-cart '+activeQty+'" data-minQty="'+product.minQuantity+'" data-maxQty="'+product.maxQuantity+'" data-unit="'+unitQty+'" data-pricelist="'+pricelist+'" data-screen="'+screenName+'">'+ 828 '<input type="hidden" name="productObj" value=\''+escapedData+'\'>'+ 829 '<a href="javascript:void(0);" class="initial-add add-to-cart-action '+(redirectPDP !== '#' ? "redirectpdp open-pdp" : "")+'" aria-hidden="true" aria-label="Add to Cart" data-id="'+productID+'" data-pricelist="'+pricelist+'">'+ 830 '<svg width="11" height="11" viewBox="0 0 11 11" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="ng-scope"><g id="Group 347"><path id="Vector" d="M5.66699 1V10.3333" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"></path><path id="Vector_2" d="M1 5.66699H10.3333" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>'+ 831 '<span>Add</span>'+ 832 '</a>'+ 833 '<div class="svt-product-qty '+activeMinus+'">'+ 834 '<button class="svt-product-delete" aria-hidden="true" aria-label="Delete from Cart">'+ 835 '<svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="Group 338"><path id="Vector" d="M1 5H3H19" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path id="Vector_2" d="M17 5V19C17 19.5304 16.7893 20.0391 16.4142 20.4142C16.0391 20.7893 15.5304 21 15 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V5M6 5V3C6 2.46957 6.21071 1.96086 6.58579 1.58579C6.96086 1.21071 7.46957 1 8 1H12C12.5304 1 13.0391 1.21071 13.4142 1.58579C13.7893 1.96086 14 2.46957 14 3V5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path id="Vector_3" d="M8 10V16" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path id="Vector_4" d="M12 10V16" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>'+ 836 '</button>'+ 837 '<button class="svt-minus-qty" aria-hidden="true" aria-label="Decrease Quantity">'+ 838 '<svg width="11" height="2" viewBox="0 0 11 2" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="ng-scope"><g id="Group 347"><path id="Vector" d="M1 0.666992H10.3333" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>'+ 839 '</button>'+ 840 '<div class="qty-value">'+qtyVal+'</div>'+ 841 '<button class="svt-qty-plus" aria-hidden="true" aria-label="Increase Quantity">'+
842 '<svg width="11" height="11" viewBox="0 0 11 11" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="ng-scope"><g id="Group 347"><path id="Vector" d="M5.66699 1V10.3333" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"></path><path id="Vector_2" d="M1 5.66699H10.3333" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>'+ 843 '</button>'+ 844 '<div class="bouncing-loader small-loader">'+ 845 '<div></div>'+ 846 '<div></div>'+ 847 '<div></div>'+ 848 '</div>'+ 849 '</div>'+ 850 '</div>'; 851 } 852 else { 853 html += '<div class="svt-out-of-stock-badge">Sold Out!</div>'; 854 } 855 html += 856 '</div>'; 857 html += '<div class="svt-product-info-wrap">'; 858 if(isZeroPrice == false) { 859 if((promoSalePrice != '' && promoSalePrice > 0) || promoSalePrice == 'FREE') { 860 let promoPriceFormatted = `<span class="price-dollar">${promoSalePrice}</span>`; 861 if(promoSalePrice != 'FREE') { 862 promoPriceFormatted = formatPrice(parseFloat(promoSalePrice).toFixed(2), weightInPrice, avgWeight); 863 } 864 var avgPrice = price; 865 if(product.sellByQty == true) { 866 avgPrice = price * avgWeight; 867 } 868 html += '<div class="svt-product-price">'; 869 html += '<div class="svt-product-sale-price">'; 870 html += promoPriceFormatted; 871 html += '</div>'; 872 html += "<div class='svt-product-old-price'>$"+parseFloat(avgPrice).toFixed(2)+"</div>"; 873 html += '<div class="svt-product-each-estimate">'+eaEstimate+'</div>'; 874 html += '</div>'; 875 } 876 else { 877 html += '<div class="svt-product-price">'; 878 html += priceFormatted; 879 html += '<div class="svt-product-each-estimate">'+eaEstimate+'</div>'; 880 html += '</div>'; 881 } 882 } 883 else { 884 html += '<div class="svt-product-zero-price">'+ 885 '<div class="svt-product-price-info" data-tippy-content="'+product.zeroPriceInfo+'" data-tippy-arrow="true" data-placement="bottom"><svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22" fill="none" class="ng-scope"><path d="M11 21C16.5228 21 21 16.5228 21 11C21 5.47715 16.5228 1 11 1C5.47715 1 1 5.47715 1 11C1 16.5228 5.47715 21 11 21Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11 15V11" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11 7H11.01" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path> </svg></div>'; 886 if(zeroPriceObj == null) { 887 html += '<span>'+product.zeroPriceTag+'</span>'; 888 } 889 else { 890 html+= '<span class="svt-product-price">'+zeroPriceObj.min +'-'+zeroPriceObj.max +'</span>'; 891 } 892 html += '</div>'; 893 } 894 html += '<h6><a href="'+pdpLink+'">'+productTitle+'</a></h6>'; 895 if(product.sellByQty == true) { 896 var avgOriginalPrice = price; 897 if(promoSalePrice != '' && promoSalePrice != 'FREE') { 898 avgOriginalPrice = promoSalePrice; 899 } 900 html += '<div class="svt-avg-weight-org-price">$'+parseFloat(avgOriginalPrice).toFixed(2)+'/'+weightUnit+'</div>'; 901 } 902 if(productPromoHTML != '' && showEligibleItems) { 903 html += '<div class="svt-product-promo-wrap">'; 904 html += productPromoHTML; 905 html += '<div class="svt-product-coupon-wrap">'+couponHTML+'</div>'; 906 if(promoID != '') { 907 html += '<a href="javascript:void(0);" data-id="'+promoID+'" class="svt-promotion-link" aria-hidden="true" aria-label="Eligible items">Eligible items</a>'; 908 } 909 html += '</div>'; 910 } 911 else { 912 html += '<div class="svt-product-coupon-wrap">'+couponHTML+'</div>'; 913 } 914 html += '</div>'+ 915 '</div>'; 916 return html; 917} 918 919function initPriceInfoTip() { 920 tippy('.svt-product-price-info', { 921 placement: 'bottom', 922 });
923} 924 925function renderCouponCard( coupon, productsData ) { 926 var timestamp = coupon.expirationtimestamp; 927 timestamp = timestamp.replace(' ', 'T'); 928 var date = new Date(timestamp); 929 var day = date.getDate(); 930 var month = date.getMonth() + 1; 931 var year = date.getFullYear(); 932 var expiryDate = month+'/'+day+'/'+year; 933 var pointsRequired = coupon.pointrequirement; 934 var clippable = coupon.isClippable; 935 var clipped = coupon.isclipped; 936 var upcs = coupon.upcs; 937 // console.log(coupon.tags); 938 var type = ''; 939 if(typeof coupon.type !== "undefined") { 940 type = coupon.type; 941 if(typeof type != "undefined") { 942 type = sanitizeTitle(type); 943 } 944 else { 945 type = ''; 946 } 947 } 948 let user = localStorage.getItem('user'); 949 var rewardPointsElement = 0; 950 if(user != null) { 951 user = JSON.parse(user); 952 rewardPointsElement = user.loyaltyAccount.pointbalance; 953 // console.log('Points from user session', rewardPointsElement); 954 } 955 var points = rewardPointsElement != null ? parseFloat(rewardPointsElement) : 0; 956 points = isNaN(points) ? 0 : points; 957 var clipCouponText = 'Clip Coupon'; 958 if(pointsRequired > points) { 959 clipCouponText = 'Need '+pointsRequired+' Pts'; 960 } 961 var imgClass = ''; 962 if(upcs != null) { 963 imgClass = 'eligible-items-coupon'; 964 } 965 966 let eligibleItems = false; 967 968 let productMap = new Map(); 969 const regex = /^02\d{5}0{5}\d$/; 970 971 if (typeof productsData !== "undefined") { 972 productsData.products.forEach(product => { 973 let productUpc = product.upc.length > 6 974 ? product.upc.replace(/^0+/, '').slice(0, -1) 975 : product.upc; 976 productMap.set(productUpc, product); 977 }); 978 } 979 980 if (typeof productsData !== "undefined" && coupon.upcs != null) { 981 eligibleItems = coupon.upcs.some(upcID => { 982 let cleanedUpcID = regex.test(upcID) ? upcID.slice(1, 7) : upcID; 983 if (cleanedUpcID.length > 6) { 984 cleanedUpcID = cleanedUpcID.replace(/^0+/, '').slice(0, -1); 985 } 986 return productMap.has(cleanedUpcID); 987 }); 988 } else { 989 eligibleItems = true; 990 } 991 992 let couponDetailURL = sitedata.home_url+'/coupon/?id='+coupon.couponid; 993 994 if(eligibleItems == false) { 995 imgClass = ''; 996 couponDetailURL = 'javascript:void(0);'; 997 } 998 999 let escapedData = JSON.stringify(coupon).replace(/'/g, "'"); 1000 1001 var html = ` 1002 <div class="svt-coupon-box ${type}" data-id="${coupon.couponid}" data-description="${coupon.description}"> 1003 <div class="svt-coupon-img-wrap ${imgClass}" data-obj='${escapedData}' data-id="${coupon.couponid}" data-title="${coupon.title}"> 1004 <img src="${coupon.detailmediapath}" onerror="this.onerror=null; this.className='placeholder-img'; this.src='${embeddata.theme_url}/images/nophoto-v2.svg'" alt="${coupon.title}"> 1005 </div> 1006 <div class="svt-coupon-actions ${(clipped == true || clippable == false) ? 'clipped' : ''} ${(clippable == false) ? 'noclip' : ''}"> 1007 <div class="svt-coupon-clip ${(pointsRequired !== null) ? 'points-required' : ''} ${(pointsRequired > points) ? 'nopoints': ''}"> 1008 <a href="javascript:void(0);" class="clip-action btn-with-loader ${(pointsRequired !== null) ? 'points-required-a' : ''}" data-id="${coupon.couponid}" aria-hidden="true" aria-label="Clip Coupon"> 1009 <div class="btn-txt-wrap"> 1010 <span class="btn-loader"></span> 1011 <span class="point-needed btn-txt-pre">${(pointsRequired !== null && pointsRequired < points) ? pointsRequired+' Pts' : ''}</span>`; 1012 if(pointsRequired > points) { 1013 html += `<svg xmlns="http://www.w3.org/2000/svg" width="25" height="24" viewBox="0 0 25 24" fill="none"> 1014 <path fill-rule="evenodd" clip-rule="evenodd" d="M9.51035 3.75001C10.665 1.75 13.5527 1.75 14.7074 3.75001L22.061
10145 16.4982C23.2148 18.4981 21.7713 20.997 19.4639 20.997H4.75387C2.4459 20.997 1.00164 18.4984 2.15622 16.4982V16.4982L9.51035 3.75001ZM10.8094 4.49999L3.45553 17.2478C2.87834 18.2475 3.59993 19.497 4.75387 19.497H19.4639C20.6165 19.497 21.3389 18.2478 20.7622 17.2477L13.4083 4.49999C12.831 3.5 11.3867 3.5 10.8094 4.49999ZM12.1089 8.997C12.5231 8.997 12.8589 9.33279 12.8589 9.747V13.497C12.8589 13.9112 12.5231 14.247 12.1089 14.247C11.6947 14.247 11.3589 13.9112 11.3589 13.497V9.747C11.3589 9.33279 11.6947 8.997 12.1089 8.997ZM11.3589 16.497C11.3589 16.0828 11.6947 15.747 12.1089 15.747H12.1159C12.5301 15.747 12.8659 16.0828 12.8659 16.497V16.505C12.8659 16.9192 12.5301 17.255 12.1159 17.255H12.1089C11.6947 17.255 11.3589 16.9192 11.3589 16.505V16.497Z" fill="#222222"/> 1015 </svg>`; 1016 } 1017 else { 1018 html += `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> 1019 <path fill-rule="evenodd" clip-rule="evenodd" 1020 d="M9.06507 8.07439C9.46634 7.48276 9.70078 6.76878 9.70078 6.00005C9.70078 3.9566 8.04424 2.30005 6.00078 2.30005C3.95733 2.30005 2.30078 3.9566 2.30078 6.00005C2.30078 8.0435 3.95733 9.70005 6.00078 9.70005C6.76951 9.70005 7.48349 9.46561 8.07512 9.06433L11.0108 12L8.07511 14.9358C7.48349 14.5345 6.76951 14.3 6.00078 14.3C3.95733 14.3 2.30078 15.9566 2.30078 18C2.30078 20.0435 3.95733 21.7 6.00078 21.7C8.04424 21.7 9.70078 20.0435 9.70078 18C9.70078 17.2313 9.46634 16.5173 9.06507 15.9257L20.4958 4.49502C20.7691 4.22166 20.7691 3.77844 20.4958 3.50507C20.2224 3.23171 19.7792 3.23171 19.5058 3.50507L12.0008 11.0101L9.06507 8.07439ZM6.00078 3.70005C4.73053 3.70005 3.70078 4.72979 3.70078 6.00005C3.70078 7.2703 4.73053 8.30005 6.00078 8.30005C6.61966 8.30005 7.18146 8.05561 7.59488 7.65802C7.60477 7.64679 7.61507 7.6358 7.6258 7.62507C7.63653 7.61434 7.64752 7.60403 7.65875 7.59415C8.05635 7.18072 8.30078 6.61893 8.30078 6.00005C8.30078 4.72979 7.27104 3.70005 6.00078 3.70005ZM6.00078 15.7C4.73053 15.7 3.70078 16.7298 3.70078 18C3.70078 19.2703 4.73053 20.3 6.00078 20.3C7.27104 20.3 8.30078 19.2703 8.30078 18C8.30078 17.3812 8.05633 16.8193 7.65872 16.4059C7.6475 16.396 7.63652 16.3857 7.6258 16.375C7.61508 16.3643 7.60478 16.3533 7.5949 16.3421C7.18148 15.9445 6.61968 15.7 6.00078 15.7Z" 1021 fill="currentColor" /> 1022 <path 1023 d="M13.9754 13.9855C14.2485 13.7119 14.6917 13.7115 14.9653 13.9846L20.4953 19.5046C20.7689 19.7777 20.7693 20.2209 20.4962 20.4946C20.2231 20.7682 19.7799 20.7686 19.5063 20.4955L13.9763 14.9755C13.7026 14.7023 13.7022 14.2591 13.9754 13.9855Z" 1024 fill="currentColor" /> 1025 </svg>`; 1026 } 1027 html += ` 1028 <span class="btn-txt">${clipCouponText}</span> 1029 </div> 1030 <div class="bouncing-loader small-loader"> 1031 <div></div> 1032 <div></div> 1033 <div></div> 1034 </div> 1035 </a> 1036 </div> 1037 <div class="svt-coupon-clipped"> 1038 <a href="javascript:void(0);" class="unclip-action btn-with-loader" data-id="${coupon.couponid}" aria-hidden="true" aria-label="Unclip Coupon"> 1039 <div class="btn-txt-wrap"> 1040 <span class="btn-loader"></span> 1041 <span class="btn-txt">
1041Clipped</span> 1042 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> 1043 <path 1044 d="M9 15L3 9M3 9L9 3M3 9H15C16.5913 9 18.1174 9.63214 19.2426 10.7574C20.3679 11.8826 21 13.4087 21 15C21 16.5913 20.3679 18.1174 19.2426 19.2426C18.1174 20.3679 16.5913 21 15 21H12" 1045 stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" /> 1046 </svg> 1047 </div> 1048 <div class="bouncing-loader small-loader"> 1049 <div></div> 1050 <div></div> 1051 <div></div> 1052 </div> 1053 </a> 1054 </div> 1055 </div> 1056 <div class="svt-coupon-info-wrap"> 1057 <h5> 1058 `; 1059 if(upcs != null && eligibleItems === true) { 1060 html += `<a href="${couponDetailURL}">`; 1061 } 1062 html += `${coupon.title}`; 1063 if(upcs != null && eligibleItems === true) { 1064 html += `</a>`; 1065 } 1066 html += `</h5> 1067 <div class="coupon-expiry"> 1068 Expires ${expiryDate} 1069 </div> 1070 `; 1071 if(upcs != null && eligibleItems === true) { 1072 html += `<div class="coupon-actions"> 1073 <a href="javascript:void(0);" data-obj='${escapedData}' data-title="${coupon.title}" data-id="${coupon.couponid}" class="eligible-items-coupon">Eligible items</a> 1074 </div>`; 1075 } 1076 html +=` 1077 </div> 1078 </div> 1079 `; 1080 return html; 1081} 1082 1083function sanitizeTitle(title) { 1084 if(typeof title != "undefined") { 1085 return title 1086 .trim() // Remove whitespace from both sides 1087 .toLowerCase() // Convert to lowercase 1088 .replace(/[^a-z0-9\s-]/g, '') // Remove special characters (keep letters, numbers, spaces, and dashes) 1089 .replace(/\s+/g, '-') // Replace spaces with dashes 1090 .replace(/-+/g, '-'); // Ensure there are no consecutive dashes 1091 } 1092 return ''; 1093} 1094 1095function setBasket( basket ) { 1096 const basketObj = { 1097 'items': basket.basketItems, 1098 'itemsTotal': basket.basketItems.length, 1099 'cartSubTotal': parseFloat(basket.basketSubTotal).toFixed(2), 1100 'cartTotal': parseFloat(basket.basketTotal).toFixed(2), 1101 'tax': parseFloat(basket.tax).toFixed(2), 1102 'isPickupOnly': basket.isPickupOnly 1103 } 1104 localStorage.setItem('basket',JSON.stringify(basketObj)); 1105} 1106 1107function updateCartCount() { 1108 let user = localStorage.getItem('user'); 1109 user = JSON.parse(user); 1110 const api = new HomesomeAPI(hsdata.base_url, hsdata.hs_api_key); 1111 const email = user.email; 1112 1113 let headers = { 1114 'emailid': email, 1115 'authToken': user.authToken, 1116 'location': getCookie('selectedLocation'), 1117 'pricelist': getCookie('selectedPriceList'), 1118 'Content-Type': 'application/json' 1119 }; 1120 1121 api.getData('/user/basket?lite=true', headers) 1122 .then(response => { 1123 if (response.basketItems) { 1124 setBasket(response); 1125 var cartCount = (response.basketItems).length; 1126 if(cartCount > 0) { 1127 jQuery('.hs-cart-count').html(cartCount); 1128 jQuery('.hs-cart-count').addClass('active'); 1129 } 1130 if(jQuery('.hs-coupon-detail-wrap').length) { 1131 loadCouponDetailPage(); 1132 } 1133 } 1134 }) 1135 .catch(error => console.error('Error fetching basket data:', error)); 1136} 1137 1138function loadBestDeals( productsData ) { 1139 jQuery('.hs-best-deals-products .shimmer-product-boxes').show(); 1140 jQuery('.hs-best-deals-products .svt-product-box:not(.shimmer-product-boxes)').remove(); 1141 1142 let dealsproducts = productsData.products; 1143 let promotions = productsData.promotions; 1144 dealsproducts = dealsproducts.filter((product) => product.virtualCategory == 'weekly deals'); 1145 1146 if(typeof promotions !== "undefined") { 1147 let productArr = []; 1148 let productArr2 = [];
1149 for (const product of Object.values(dealsproducts)) { 1150 const productID = product.name; 1151 const promoItem = promotions.items[productID]; 1152 1153 if (promoItem && promoItem.primary) { 1154 const promoID = promoItem.primary[0].id; 1155 const promoDetails = promotions.promotions[promoID]; 1156 if (promoDetails) { 1157 productArr.push(product); 1158 } 1159 else { 1160 productArr2.push(product); 1161 } 1162 } 1163 } 1164 const dealsproductsGroup = [...productArr, ...productArr2].slice(0,12); 1165 const html = dealsproductsGroup.map((product) => { 1166 bestDealsIDs.push(product.name); 1167 return renderProductCard(product, promotions); 1168 }).join(''); 1169 jQuery('.hs-best-deals-products .shimmer-product-boxes').hide(); 1170 jQuery('.hs-best-deals-products').append(html); 1171 initPriceInfoTip(); 1172 } 1173} 1174 1175function loadBestSellingProducts( productsData ) { 1176 let bsProducts = productsData.products; 1177 let promotions = productsData.promotions; 1178 // let productArr = []; 1179 1180 // console.log(bestDealsIDs); 1181 1182 bsProducts = bsProducts.filter((product) => !bestDealsIDs.includes(product.name)).slice(0,20); 1183 1184 const html = bsProducts.map(product => renderProductCard(product, promotions)).join(''); 1185 jQuery('.hs-best-selling-products').html(html).addClass('svt-product-carousel'); 1186 jQuery('.hs-best-selling-products').removeClass('slick-initialized slick-slider'); 1187 initPriceInfoTip(); 1188 1189 // Initialize slick carousel after a short delay 1190 setTimeout(() => { 1191 if(!jQuery('.hs-best-selling-products').hasClass('slick-initialized slick-slider')) { 1192 jQuery('.hs-best-selling-products').slick({ 1193 slidesToShow: 6, 1194 slidesToScroll: 1, 1195 dots: false, 1196 arrows: true, 1197 prevArrow: '<button type="button" aria-hidden="true" aria-label="Previous" class="slick-prev"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.5303 5.46967C15.2374 5.17678 14.7626 5.17678 14.4697 5.46967L8.46967 11.4697C8.17678 11.7626 8.17678 12.2374 8.46967 12.5303L14.4697 18.5303C14.7626 18.8232 15.2374 18.8232 15.5303 18.5303C15.8232 18.2374 15.8232 17.7626 15.5303 17.4697L10.0607 12L15.5303 6.53033C15.8232 6.23744 15.8232 5.76256 15.5303 5.46967Z" fill="currentColor"></path></svg></button>', 1198 nextArrow: '<button type="button" aria-hidden="true" aria-label="Next" class="slick-next"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M8.46967 5.46967C8.76256 5.17678 9.23744 5.17678 9.53033 5.46967L15.5303 11.4697C15.8232 11.7626 15.8232 12.2374 15.5303 12.5303L9.53033 18.5303C9.23744 18.8232 8.76256 18.8232 8.46967 18.5303C8.17678 18.2374 8.17678 17.7626 8.46967 17.4697L13.9393 12L8.46967 6.53033C8.17678 6.23744 8.17678 5.76256 8.46967 5.46967Z" fill="currentColor"></path></svg></button>', 1199 responsive: [ 1200 { 1201 breakpoint: 0, 1202 settings: { 1203 slidesToShow: 2, 1204 } 1205 }, 1206 { 1207 breakpoint: 767, 1208 settings: { 1209 slidesToShow: 2, 1210 } 1211 }, 1212 { 1213 breakpoint: 1024, 1214 settings: { 1215 slidesToShow: 4, 1216 } 1217 } 1218 ] 1219 }); 1220 } 1221 }, 100); 1222} 1223 1224function loadHomeFeaturedProducts( productsData ) { 1225 let bsProducts = productsData.products; 1226 let promotions = productsData.promotions; 1227 // let productArr = []; 1228 1229 // console.log(bestDealsIDs); 1230 1231 let bsProductsArr = bsProducts.filter((product) => !bestDealsIDs.includes(product.name)).slice(20,40); 1232 1233 if(bsProductsArr == false) { 1234 bsProductsArr = bsProducts.filter((product) => !bestDealsIDs.includes(product.name)).slice(0,20); 1235 } 1236 1237 const html = bsProductsArr.map(product => renderProductCard(product, promotions)).join(''); 1238 jQuery('.hs-home-featured-products').html(html).addClass('svt-product-carou
1238sel'); 1239 jQuery('.hs-home-featured-products').removeClass('slick-initialized slick-slider'); 1240 initPriceInfoTip(); 1241 1242 // Initialize slick carousel after a short delay 1243 setTimeout(() => { 1244 if(!jQuery('.hs-home-featured-products').hasClass('slick-initialized slick-slider')) { 1245 jQuery('.hs-home-featured-products').slick({ 1246 slidesToShow: 6, 1247 slidesToScroll: 1, 1248 dots: false, 1249 arrows: true, 1250 prevArrow: '<button type="button" aria-hidden="true" aria-label="Previous" class="slick-prev"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.5303 5.46967C15.2374 5.17678 14.7626 5.17678 14.4697 5.46967L8.46967 11.4697C8.17678 11.7626 8.17678 12.2374 8.46967 12.5303L14.4697 18.5303C14.7626 18.8232 15.2374 18.8232 15.5303 18.5303C15.8232 18.2374 15.8232 17.7626 15.5303 17.4697L10.0607 12L15.5303 6.53033C15.8232 6.23744 15.8232 5.76256 15.5303 5.46967Z" fill="currentColor"></path></svg></button>', 1251 nextArrow: '<button type="button" aria-hidden="true" aria-label="Next" class="slick-next"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M8.46967 5.46967C8.76256 5.17678 9.23744 5.17678 9.53033 5.46967L15.5303 11.4697C15.8232 11.7626 15.8232 12.2374 15.5303 12.5303L9.53033 18.5303C9.23744 18.8232 8.76256 18.8232 8.46967 18.5303C8.17678 18.2374 8.17678 17.7626 8.46967 17.4697L13.9393 12L8.46967 6.53033C8.17678 6.23744 8.17678 5.76256 8.46967 5.46967Z" fill="currentColor"></path></svg></button>', 1252 responsive: [ 1253 { 1254 breakpoint: 0, 1255 settings: { 1256 slidesToShow: 2, 1257 } 1258 }, 1259 { 1260 breakpoint: 767, 1261 settings: { 1262 slidesToShow: 2, 1263 } 1264 }, 1265 { 1266 breakpoint: 1024, 1267 settings: { 1268 slidesToShow: 4, 1269 } 1270 } 1271 ] 1272 }); 1273 } 1274 }, 100); 1275} 1276 1277function loadBuyAgainProducts( buyAgainProducts, productsData ) { 1278 // buyAgainProducts = []; 1279 if(buyAgainProducts.length) { 1280 let bsProducts = buyAgainProducts; 1281 let promotions = productsData.promotions; 1282 1283 const html = bsProducts.map(product => renderProductCard(product, promotions)).join(''); 1284 1285 const $productContainer = jQuery('.hs-buy-again-products'); 1286 $productContainer.html(html).addClass('svt-product-carousel'); 1287 1288 $productContainer.removeClass('slick-initialized slick-slider'); 1289 1290 initPriceInfoTip(); 1291 1292 setTimeout(function() {
1293 if (!$productContainer.hasClass('slick-initialized slick-slider')) { 1294 $productContainer.slick({ 1295 slidesToShow: 6, 1296 slidesToScroll: 1, 1297 dots: false, 1298 arrows: true, 1299 prevArrow: '<button type="button" aria-hidden="true" aria-label="Previous" class="slick-prev"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.5303 5.46967C15.2374 5.17678 14.7626 5.17678 14.4697 5.46967L8.46967 11.4697C8.17678 11.7626 8.17678 12.2374 8.46967 12.5303L14.4697 18.5303C14.7626 18.8232 15.2374 18.8232 15.5303 18.5303C15.8232 18.2374 15.8232 17.7626 15.5303 17.4697L10.0607 12L15.5303 6.53033C15.8232 6.23744 15.8232 5.76256 15.5303 5.46967Z" fill="currentColor"></path></svg></button>', 1300 nextArrow: '<button type="button" aria-hidden="true" aria-label="Next" class="slick-next"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M8.46967 5.46967C8.76256 5.17678 9.23744 5.17678 9.53033 5.46967L15.5303 11.4697C15.8232 11.7626 15.8232 12.2374 15.5303 12.5303L9.53033 18.5303C9.23744 18.8232 8.76256 18.8232 8.46967 18.5303C8.17678 18.2374 8.17678 17.7626 8.46967 17.4697L13.9393 12L8.46967 6.53033C8.17678 6.23744 8.17678 5.76256 8.46967 5.46967Z" fill="currentColor"></path></svg></button>', 1301 responsive: [ 1302 { 1303 breakpoint: 0, 1304 settings: { 1305 slidesToShow: 2, 1306 } 1307 }, 1308 { 1309 breakpoint: 767, 1310 settings: { 1311 slidesToShow: 2, 1312 } 1313 }, 1314 { 1315 breakpoint: 1024, 1316 settings: { 1317 slidesToShow: 4, 1318 } 1319 } 1320 ] 1321 }); 1322 } 1323 jQuery('.hs-buy-again-products-wrapper').addClass('active'); 1324 },100); 1325 } 1326} 1327 1328function loadBuyAgainProductsData( productsData ) { 1329 let api = new HomesomeAPI(hsdata.base_url, hsdata.hs_api_key); 1330 1331 var user = localStorage.getItem('user'); 1332 1333 let headers = { 1334 'apikey': hsdata.hs_api_key, 1335 'location': getCookie('selectedLocation'), 1336 'pricelist': getCookie('selectedPriceList') 1337 }; 1338 1339 if(user != null) { 1340 user = JSON.parse(user); 1341 jQuery('.user-name').html(user.firstName); 1342 headers.emailid = user.email; 1343 headers.authToken = user.authToken; 1344 api.getData('/user/items',headers).then(response => { 1345 if(response.orderedItems) { 1346 loadBuyAgainProducts(response.orderedItems, productsData); 1347 } 1348 }); 1349 } 1350} 1351 1352// Function to get a specific cookie value by name 1353function getCookie(name) { 1354 const value = `; ${document.cookie}`; 1355 const parts = value.split(`; ${name}=`); 1356 if (parts.length === 2) return parts.pop().split(';').shift(); 1357 return null; // If cookie doesn't exist 1358} 1359 1360// Function to check if both cookie and localStorage are valid 1361function checkStorageAndCookie() { 1362 const selectedLocationCookie = getCookie('selectedLocation'); 1363 const cateringPriceListID = getCookie('cateringPriceListID'); 1364 const localStorageLocation = sessionStorage.getItem('ls.location'); 1365 const localStoragePL = sessionStorage.getItem('ls.selectedPriceList'); 1366 1367 // Check if either cookie or localStorage entry is missing 1368 if (!selectedLocationCookie || !localStorageLocation || !localStoragePL) { 1369 console.log('Cookie or localStorage missing. Resending request...'); 1370 initLocation(); // Re-trigger the request if the cookie or localStorage is missing 1371 } else { 1372 var storeName = localStorage.getItem("storeName"); 1373 if(storeName != null) { 1374 // document.getElementById('navbar-store-location').innerHTML = storeName; 1375 // document.getElementById('navbar-store-location-tab').innerHTML = storeName; 1376 } 1377 // console.log('Cookie and localStorage are valid.'); 1378 } 1379 window.dispatchEvent(new Event('locationSet')); 1380} 1381 1382window.addEventListener('locationSet', function () { 1383 console.log('locationSet event triggered'); 1384}); 1385 1386function setLocationData(location, priceListData, cateringPricelist, deliPricelist, allLocationData) { 1387 1388 // console.log('Setting location data from initLocation'); 1389 1390 sessionStorage.setItem('ls.allLocations', JSON.stringify(allLocationData)); 1391 sessionStorage.setItem('ls.location', JSON.stringify(location)); 1392 localStorage.setItem('ls.location', JSON.stringify(location)); 1393 localStorage.setItem('ls.selectedPriceList', JSON.stringify(priceListData)); 1394 sessionStorage.setItem('ls.selectedPriceList', JSON.stringify(priceListData)); 1395 // console.log(priceListData); 1396 localStorage.setItem('ls.cateringPriceListID', JSON.stringify(cateringPricelist));
1397 localStorage.setItem('ls.deliPriceList', JSON.stringify(deliPricelist)); 1398 1399 document.cookie = `selectedLocation=${location.uniqueName}; path=/`; 1400 document.cookie = `selectedLocName=${location.locName}; path=/`; 1401 document.cookie = `selectedPriceList=${priceListData.uniqueName}; path=/`; 1402 document.cookie = `selectedPListName=${priceListData.pListName}; path=/`; 1403 document.cookie = `cateringPriceListID=${cateringPricelist.uniqueName}; path=/`; 1404 document.cookie = `deliPriceListID=${deliPricelist.uniqueName}; path=/`; 1405 1406 localStorage.setItem("storeName", location.name); 1407 1408 window.dispatchEvent(new Event('locationSet')); 1409 document.getElementById('navbar-store-location').innerHTML = location.name; 1410 document.getElementById('navbar-store-location-tab').innerHTML = location.name; 1411 const headerTabs = cateringPricelist.headerTabs; 1412 if(typeof headerTabs != "undefined" && headerTabs != null && headerTabs != '') { 1413 if(headerTabs.showCatering == true) { 1414 document.cookie = 'showCatering=1; path=/'; 1415 jQuery('body').addClass('show-catering'); 1416 } 1417 else { 1418 document.cookie = 'showCatering=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 1419 jQuery('body').removeClass('show-catering'); 1420 } 1421 if(headerTabs.showFloral == true) { 1422 document.cookie = 'showFloral=1; path=/'; 1423 jQuery('body').addClass('show-floral'); 1424 } 1425 else { 1426 document.cookie = 'showFloral=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 1427 jQuery('body').removeClass('show-floral'); 1428 } 1429 // if(headerTabs.showCakes == true) { 1430 // document.cookie = 'showCakes=1; path=/'; 1431 // jQuery('body').addClass('show-cakes'); 1432 // } 1433 // else { 1434 document.cookie = 'showCakes=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 1435 jQuery('body').removeClass('show-cakes'); 1436 // } 1437 } 1438 // if(cateringPricelist.isDisabled == true) { 1439 // jQuery('body').addClass('hide-catering-menus'); 1440 // document.cookie = 'hideCateringMenus=1; path=/'; 1441 // } 1442 // else { 1443 // jQuery('body').removeClass('hide-catering-menus'); 1444 // document.cookie = 'hideCateringMenus=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 1445 // } 1446} 1447 1448function clearLocationData() { 1449 document.cookie = 'selectedLocation=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 1450 document.cookie = 'selectedLocName=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 1451 document.cookie = 'selectedPriceList=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 1452 document.cookie = 'selectedPListName=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 1453 document.cookie = 'deliPriceListID=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 1454 document.cookie = 'cateringPriceListID=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 1455 1456 sessionStorage.removeItem('ls.allLocations'); 1457 sessionStorage.removeItem('ls.location'); 1458 localStorage.removeItem('ls.selectedPriceList'); 1459 sessionStorage.removeItem('ls.selectedPriceList'); 1460 localStorage.removeItem('ls.cateringPriceListID'); 1461 localStorage.removeItem('ls.deliPriceList'); 1462} 1463 1464function updateCurrentLocation() { 1465 const lsLocation = JSON.parse(localStorage.getItem('ls.location')); 1466 const locName = getUrlParameter('locName'); 1467 if(lsLocation != null) { 1468 // localStorage.removeItemItem('ls.location'); 1469 const api = new HomesomeAPI(hsdata.base_url, hsdata.hs_api_key); 1470 let headers = { 1471 'apikey': hsdata.hs_api_key 1472 }; 1473 1474 const loggedIn = isUserLoggedIn(); 1475 1476 if(loggedIn) { 1477 const user = JSON.parse(localStorage.getItem('user')); 1478 if(user) { 1479 headers.emailid = user.email; 1480 headers.authToken = user.authToken; 1481 } 1482 } 1483 api.getData('/locations', headers) 1484 .then(response => { 1485 if (response.length) { 1486 let locations = response; 1487 console.log('last location: ',lsLocation.name); 1488 let location = locations.filter(item => lsLocation.uniqueName == item.uniqueName); 1489 if(locName != null) { 1490 location = locations.filter(item => locName == item.locName); 1491 } 1492 if(location.length) { 1493 location = location[0]; 1494 console.log('new location: ',location.name); 1495 const priceListData = location.priceLists.find(p => p.default); 1496 const cateringPricelist = location.priceLists.find(p => p.pListName === "catering");
1497 const deliPricelist = location.priceLists.find(p => p.pListName === "deli"); 1498 // console.log('From Update Location'); 1499 setLocationData(location, priceListData, cateringPricelist, deliPricelist, response); 1500 } 1501 } 1502 }) 1503 .catch(console.error); 1504 } 1505} 1506 1507// Function to reinitialize location data and set cookies/localStorage 1508function initLocation() { 1509 const selectedLocation = getCookie('selectedLocation'); 1510 const cateringPriceListID = getCookie('cateringPriceListID'); 1511 const deliPriceListID = getCookie('deliPriceListID'); 1512 // updateCurrentLocation(); 1513 const lsLocation = JSON.parse(localStorage.getItem('ls.location')); 1514 1515 const locName = getUrlParameter('locName'); 1516 1517 if(locName != null) { 1518 updateCurrentLocation(); 1519 } 1520 else { 1521 if (!lsLocation && (!selectedLocation || !cateringPriceListID || !deliPriceListID)) { 1522 const api = new HomesomeAPI(hsdata.base_url, hsdata.hs_api_key); 1523 let headers = { 1524 'apikey': hsdata.hs_api_key 1525 }; 1526 1527 const loggedIn = isUserLoggedIn(); 1528 1529 if(loggedIn) { 1530 const user = JSON.parse(localStorage.getItem('user')); 1531 if(user) { 1532 headers.emailid = user.email; 1533 headers.authToken = user.authToken; 1534 } 1535 } 1536 api.getData('/locations', headers) 1537 .then(response => { 1538 if (response.length) { 1539 const location = response[0]; 1540 const priceListData = location.priceLists.find(p => p.default); 1541 const cateringPricelist = location.priceLists.find(p => p.pListName === "catering"); 1542 const deliPricelist = location.priceLists.find(p => p.pListName === "deli"); 1543 // console.log('From API Location data'); 1544 setLocationData(location, priceListData, cateringPricelist, deliPricelist, response); 1545 } 1546 }) 1547 .catch(console.error); 1548 } else { 1549 const location = JSON.parse(sessionStorage.getItem('ls.location'));; 1550 if(location == null) { 1551 // console.log('Updating location info'); 1552 updateCurrentLocation(); 1553 } 1554 else { 1555 const priceListData = location.priceLists.find(p => p.default); 1556 const cateringPricelist = location.priceLists.find(p => p.pListName === "catering"); 1557 const deliPricelist = location.priceLists.find(p => p.pListName === "deli"); 1558 // console.log('When ls found'); 1559 setLocationData(location, priceListData, cateringPricelist, deliPricelist, JSON.parse(sessionStorage.getItem('ls.allLocations'))); 1560 } 1561 } 1562 } 1563} 1564 1565// Initial load function to check both localStorage and cookies 1566function checkAndInitOnLoad() { 1567 checkStorageAndCookie(); // Check localStorage and cookie presence on initial load 1568} 1569 1570// Set an interval to continuously check for both cookie and localStorage presence 1571// setInterval(checkStorageAndCookie, 5000); // Check every 5 seconds 1572 1573async function fetchCateringPriceList(selectedLocation) { 1574 try { 1575 // Construct the URL with query parameters 1576 const url = `${sitedata.svt_ajax_url}?action=init_catering_pricelist&locationID=${selectedLocation}`; 1577 1578 const response = await fetch(url, { 1579 method: 'GET', 1580 headers: { 1581 'Content-Type': 'application/json' 1582 } 1583 }); 1584 1585 if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); 1586 1587 // Parse the JSON response 1588 const data = await response.json(); 1589 1590 // Store the cateringPriceListID in the cookie 1591 cateringPriceListID = data.cateringPriceListID; 1592 document.cookie = `cateringPriceListID=${data.cateringPriceListID}; path=/`; 1593 1594 console.log('Catering Price List ID fetched and stored:', data.cateringPriceListID); 1595 1596 } catch (error) { 1597 console.error('Fetch Error:', error); 1598 } 1599} 1600 1601function showToastMsg( msg, type ) { 1602 jQuery.toast({ 1603 text: msg, 1604 icon: type, 1605 loader: false, 1606 position: 'bottom-center', 1607 bgColor: '#1E1E1E', 1608 hideAfter: 2000, 1609 textColor: '#fff', 1610 allowToastClose: false 1611 });
1612} 1613 1614function loadUserPoints() { 1615 const loggedIn = isUserLoggedIn(); 1616 if(loggedIn) { 1617 var user = localStorage.getItem('user'); 1618 if(user != null) { 1619 user = JSON.parse(user); 1620 jQuery('.reward-points-main').html(user.loyaltyAccount.pointbalance).removeClass('skeleton skeleton-text large'); 1621 jQuery('.total-reward-points strong').html(user.loyaltyAccount.pointbalance); 1622 jQuery('.total-reward-points').removeClass('skeleton skeleton-text large'); 1623 const lastName = user.lastName; 1624 const name = user.firstName+' '+lastName.substring(0,1)+'.'; 1625 jQuery('.short-name').html(name); 1626 } 1627 } 1628} 1629 1630function clearPointHistorySession() { 1631 sessionStorage.removeItem('pointHistory'); 1632} 1633 1634function loadPointsHistory() { 1635 const loggedIn = isUserLoggedIn(); 1636 if (loggedIn == false) return; // Early return to avoid unnecessary code execution 1637 1638 // Retrieve the point history from sessionStorage 1639 const pointHistory = sessionStorage.getItem('pointHistory'); 1640 1641 // Function to update the expiring points in the DOM 1642 const updateExpiringPoints = (expiringClub) => { 1643 const eventTS = expiringClub.eventTS; 1644 const rw = Math.abs(expiringClub.value); 1645 const pointExpiryDate = `Points expiring on ${new Date(eventTS).toLocaleDateString('en-US', { day: 'numeric', month: 'short', year: 'numeric' })}`; 1646 1647 // Update the DOM elements for expiring points in a single loop 1648 document.querySelectorAll('.point-expiring-date').forEach(el => el.innerHTML = pointExpiryDate); 1649 document.querySelectorAll('.expiring-points').forEach(el => el.innerHTML = rw); 1650 // document.querySelector('.mobile-account-points-wrap .total-reward-points strong').innerHTML = rw; 1651 1652 // Remove skeleton classes in bulk 1653 const skeletonClasses = ['skeleton', 'skeleton-text', 'large']; 1654 document.querySelectorAll('.expiring-points, .point-expiring-date').forEach(el => { 1655 skeletonClasses.forEach(cls => el.classList.remove(cls)); 1656 }); 1657 // document.querySelector('.mobile-account-points-wrap .total-reward-points').classList.remove(...skeletonClasses); 1658 }; 1659 1660 // If point history is not in sessionStorage, fetch it from the API 1661 if (!pointHistory) { 1662 const api = new HomesomeAPI(hsdata.base_url, hsdata.hs_api_key); 1663 let user = localStorage.getItem('user'); 1664 1665 if (user) { 1666 user = JSON.parse(user); 1667 const headers = { 1668 'emailid': user.email, 1669 'authToken': user.authToken, 1670 'location': getCookie('selectedLocation'), 1671 'pricelist': getCookie('selectedPriceList') 1672 }; 1673 1674 api.getData('/birdzi/clubs/details?clubPromotionId=0', headers) 1675 .then(response => { 1676 if (response.clubDetailsList) { 1677 const clubDetailsList = response.clubDetailsList; 1678 sessionStorage.setItem('pointHistory', JSON.stringify(clubDetailsList)); 1679 1680 // Filter expiring clubs 1681 const clubDetailsListExpire = clubDetailsList.filter(club => club.eventTypeName === 'Expiring'); 1682 if (clubDetailsListExpire.length) { 1683 updateExpiringPoints(clubDetailsListExpire[0]); 1684 } 1685 1686 // Filter non-expiring clubs and render them 1687 const nonExpiringClubs = clubDetailsList.filter(club => club.eventTypeName !== 'Expiring'); 1688 sessionStorage.setItem('clubDetailsList', JSON.stringify(nonExpiringClubs)); 1689 const html = nonExpiringClubs.map(club => generatePointHistoryHtml(club)).join(''); 1690 document.querySelector('.svt-profile-points-popup-content ul').innerHTML = html; 1691 } 1692 }) 1693 .catch(error => { 1694 console.error('Error fetching point history:', error); 1695 }); 1696 } 1697 } else { 1698 // Parse the point history from sessionStorage 1699 const parsedPointHistory = JSON.parse(pointHistory); 1700 1701 // Filter expiring clubs 1702 const clubDetailsListExpire = parsedPointHistory.filter(club => club.eventTypeName === 'Expiring'); 1703 if (clubDetailsListExpire.length) { 1704 updateExpiringPoints(clubDetailsListExpire[0]); 1705 } 1706 else {
1707 const skeletonClasses = ['skeleton', 'skeleton-text', 'large']; 1708 document.querySelectorAll('.expiring-points, .point-expiring-date').forEach(el => { 1709 skeletonClasses.forEach(cls => el.classList.remove(cls)); 1710 }); 1711 } 1712 1713 // Filter non-expiring clubs and render them 1714 const nonExpiringClubs = parsedPointHistory.filter(club => club.eventTypeName !== 'Expiring'); 1715 sessionStorage.setItem('clubDetailsList', JSON.stringify(nonExpiringClubs)); 1716 const html = nonExpiringClubs.map(club => generatePointHistoryHtml(club)).join(''); 1717 document.querySelector('.svt-profile-points-popup-content ul').innerHTML = html; 1718 } 1719} 1720 1721function clearLifetimeSavings() { 1722 sessionStorage.removeItem('lifetimeSaving'); 1723} 1724 1725function loadLifetimeSaving() { 1726 const loggedIn = isUserLoggedIn(); 1727 if(loggedIn) { 1728 const lifetimeSaving = sessionStorage.getItem('lifetimeSaving'); 1729 if(lifetimeSaving == null) { 1730 const api = new HomesomeAPI(hsdata.base_url, hsdata.hs_api_key); 1731 1732 var user = localStorage.getItem('user'); 1733 if(user != null) { 1734 user = JSON.parse(user); 1735 1736 let headers = { 1737 'emailid': user.email, 1738 'authToken': user.authToken, 1739 'location': getCookie('selectedLocation'), 1740 'pricelist': getCookie('selectedPriceList') 1741 }; 1742 1743 if(user != null) { 1744 headers.authToken = user.authToken 1745 } 1746 1747 api.getData('/birdzi/clubs/list',headers).then(response => { 1748 if(response.success) { 1749 const clubs = response.clubs; 1750 const saving = clubs.filter((club) => club.clubPromotionID == 0); 1751 if(saving.length) { 1752 let rewardBalance = '$'+saving[0].rewardBalance; 1753 if(typeof saving[0].rewardBalance == "undefined") { 1754 rewardBalance = '$0'; 1755 } 1756 sessionStorage.setItem('lifetimeSaving',rewardBalance); 1757 document.querySelectorAll('.lifetime-savings').forEach(el => el.innerHTML = rewardBalance); 1758 document.querySelectorAll('.lifetime-savings').forEach(el => el.classList.remove('skeleton', 'skeleton-text', 'large')); 1759 } 1760 } 1761 }) 1762 .catch(error => { 1763 console.error('Error posting data on point history 921:', error); 1764 }); 1765 } 1766 } 1767 else { 1768 document.querySelectorAll('.lifetime-savings').forEach(el => el.innerHTML = lifetimeSaving); 1769 document.querySelectorAll('.lifetime-savings').forEach(el => el.classList.remove('skeleton', 'skeleton-text', 'large')); 1770 } 1771 } 1772} 1773 1774function generatePointHistoryHtml( club ) { 1775 var date = new Date(club.eventTS).toLocaleString('en-US', { day: '2-digit', month: 'short', year: 'numeric', hour: 'numeric', minute: '2-digit', hour12: true }); 1776 var value = club.value; 1777 var info = club.info; 1778 if(value > 0) { 1779 value = '+'+value; 1780 } 1781 if(club.eventTypeName == "Expired") { 1782 if(info == '') { 1783 info = 'Points Expired'; 1784 } 1785 } 1786 if(info != '') { 1787 info = info.charAt(0).toUpperCase() + info.slice(1); 1788 } 1789 return `<li> 1790 <div class="points-info-left"> 1791 <span>${date}</span> 1792 <h6>${info}</h6> 1793 </div> 1794 <div class="points-info-right"> 1795 ${value} Pts 1796 </div> 1797 </li>`; 1798} 1799 1800function loadCategories( data ) { 1801 1802 const categoriesData = data.products.reduce((acc, { type, subType }) => { 1803 if (!acc[type]) acc[type] = []; 1804 if (!acc[type].includes(subType)) { 1805 acc[type].push(subType); 1806 } 1807 return acc; 1808 }, {}); 1809 1810 // Sort subcategories within each category
1811 Object.keys(categoriesData).forEach(type => { 1812 categoriesData[type].sort((a, b) => a.localeCompare(b)); 1813 }); 1814 1815 // Sort main categories and reassign to a new sorted object 1816 const sortedCategoriesData = Object.keys(categoriesData) 1817 .sort((a, b) => a.localeCompare(b)) 1818 .reduce((sortedAcc, key) => { 1819 sortedAcc[key] = categoriesData[key]; 1820 return sortedAcc; 1821 }, {}); 1822 1823 // Base URL for categories 1824 const baseUrl = `${sitedata.home_url}/category/?cat=`; 1825 1826 // Build HTML structure 1827 let html = ` 1828 <div class="svt-catgory-mm"> 1829 <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> 1830 <path d="M0.75 2C0.75 1.30964 1.30964 0.75 2 0.75H6C6.69036 0.75 7.25 1.30964 7.25 2V6C7.25 6.69036 6.69036 7.25 6 7.25H2C1.30964 7.25 0.75 6.69036 0.75 6V2Z" stroke="white" stroke-width="1.5" /> 1831 <path d="M0.75 12C0.75 11.3096 1.30964 10.75 2 10.75H6C6.69036 10.75 7.25 11.3096 7.25 12V16C7.25 16.6904 6.69036 17.25 6 17.25H2C1.30964 17.25 0.75 16.6904 0.75 16V12Z" stroke="white" stroke-width="1.5" /> 1832 <path d="M10.75 2C10.75 1.30964 11.3096 0.75 12 0.75H16C16.6904 0.75 17.25 1.30964 17.25 2V6C17.25 6.69036 16.6904 7.25 16 7.25H12C11.3096 7.25 10.75 6.69036 10.75 6V2Z" stroke="white" stroke-width="1.5" /> 1833 <path d="M10.75 12C10.75 11.3096 11.3096 10.75 12 10.75H16C16.6904 10.75 17.25 11.3096 17.25 12V16C17.25 16.6904 16.6904 17.25 16 17.25H12C11.3096 17.25 10.75 16.6904 10.75 16V12Z" stroke="white" stroke-width="1.5" /> 1834 </svg> 1835 <span>Categories</span> 1836 </div> 1837 <div class="svt-catgory-mm-popup"> 1838 <div class="svt-catgory-mm-popup-content"> 1839 <div class="svt-catgory-mm-popup-content-wrap"> 1840 <ul> 1841 `; 1842 1843 let mobileHtml = ` 1844 <div class="svt-mobile-categories-mm-toggle"> 1845 <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> 1846 <path d="M0.75 2C0.75 1.30964 1.30964 0.75 2 0.75H6C6.69036 0.75 7.25 1.30964 7.25 2V6C7.25 6.69036 6.69036 7.25 6 7.25H2C1.30964 7.25 0.75 6.69036 0.75 6V2Z" stroke="currentColor" stroke-width="1.5" /> 1847 <path d="M0.75 12C0.75 11.3096 1.30964 10.75 2 10.75H6C6.69036 10.75 7.25 11.3096 7.25 12V16C7.25 16.6904 6.69036 17.25 6 17.25H2C1.30964 17.25 0.75 16.6904 0.75 16V12Z" stroke="currentColor" stroke-width="1.5" /> 1848 <path d="M10.75 2C10.75 1.30964 11.3096 0.75 12 0.75H16C16.6904 0.75 17.25 1.30964 17.25 2V6C17.25 6.69036 16.6904 7.25 16 7.25H12C11.3096 7.25 10.75 6.69036 10.75 6V2Z" stroke="currentColor" stroke-width="1.5" /> 1849 <path d="M10.75 12C10.75 11.3096 11.3096 10.75 12 10.75H16C16.6904 10.75 17.25 11.3096 17.25 12V16C17.25 16.6904 16.6904 17.25 16 17.25H12C11.3096 17.25 10.75 16.6904 10.75 16V12Z" stroke="currentColor" stroke-width="1.5" /> 1850 </svg> 1851 <span>Categories</span> 1852 </div> 1853 <div class="svt-mobile-catgory-mm-sub"> 1854 <div class="mobile-cat-back"> 1855 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> 1856 <path fill-rule="evenodd" clip-rule="evenodd" d="M15.5303 5.46967C15.2374 5.17678 14.7626 5.17678 14.4697 5.46967L8.46967 11.4697C8.17678 11.7626 8.17678 12.2374 8.46967 12.5303L14.4697 18.5303C14.7626 18.8232 15.2374 18.8232 15.5303 18.5303C15.8232 18.2374 15.8232 17.7626 15.5303 17.4697L10.0607 12L15.5303 6.53033C15.8232 6.23744 15.8232 5.76256 15.5303 5.46967Z" fill="black" /> 1857 </svg> 1858 Back to menu 1859 </div> 1860 <ul> 1861 `; 1862 1863 Object.entries(sortedCategoriesData).forEach(([cat, subCategories]) => { 1864 const encodedCat = encodeURIComponent(cat); 1865 html += `<li> 1866 <a href="${baseUrl}${encodedCat}">${cat}</a> 1867 <ul class="sub-cat">`; 1868 mobileHtml += `<li> 1869 <a href="javascript:void(0);" class="mobile-cat-toggle">${cat}</a> 1870 <ul class="sub-cat"> 1871 <li><a href="${baseUrl}${encodedCat}">All</a></li>`; 1872
1873 subCategories.forEach(subCat => { 1874 const encodedSubCat = encodeURIComponent(subCat); 1875 html += `<li><a href="${baseUrl}${encodedCat}&subcategory=${encodedSubCat}">${subCat}</a></li>`; 1876 mobileHtml += `<li><a href="${baseUrl}${encodedCat}&subcategory=${encodedSubCat}">${subCat}</a></li>`; 1877 }); 1878 1879 html += `</ul></li>`; 1880 mobileHtml += `</ul></li>`; 1881 }); 1882 1883 // Finalize and update DOM 1884 html += `</ul></div></div></div>`; 1885 mobileHtml += `</ul></div>`; 1886 jQuery('.svt-category-loader').hide(); 1887 jQuery('.svt-catgory-mm-wrap').html(html); 1888 jQuery('.svt-mobile-category-loader').hide(); 1889 jQuery('.svt-mobile-categories-mm').html(mobileHtml); 1890} 1891 1892async function fetchData() { 1893 try { 1894 const results = await Promise.all([ 1895 // checkAndFetchData('myItems'), 1896 // checkAndFetchData('products'), 1897 checkAndFetchData('cateringProducts'), 1898 ]); 1899 1900 const [myItemsData, productsData, cateringProductsData] = results; 1901 1902 if (myItemsData) { 1903 console.log("Retrieved my items data:", myItemsData); 1904 // loadMyItems(myItemsData); 1905 } else { 1906 console.log("No my items data found."); 1907 } 1908 1909 if (productsData) { 1910 // console.log("Retrieved products data:", productsData); 1911 // products = productsData; 1912 // loadBestSellingProducts(productsData); 1913 } else { 1914 console.log("No products data found."); 1915 } 1916 1917 if (cateringProductsData) { 1918 console.log("Retrieved catering products data:", cateringProductsData); 1919 } else { 1920 console.log("No catering products data found."); 1921 } 1922 1923 } catch (error) { 1924 console.error("Error fetching data:", error); 1925 } 1926} 1927 1928let isRefreshed = false; 1929 1930// Detect if the session is new (for tab/window close detection) 1931document.addEventListener('DOMContentLoaded', () => { 1932 // console.log(sessionStorage.getItem('isRefreshed')); 1933 if (!sessionStorage.getItem('isRefreshed')) { 1934 isRefreshed = true; 1935 sessionStorage.setItem('isRefreshed', 'true'); 1936 if(typeof navigator.serviceWorker != "undefined") { 1937 if (navigator.serviceWorker.controller) { 1938 console.log('service worker cache cleared'); 1939 navigator.serviceWorker.controller.postMessage({ action: 'clear-cache' }); 1940 } 1941 } 1942 } 1943}); 1944 1945 1946 1947function loadProductList( priceList ) { 1948 const api = new HomesomeAPI(hsdata.base_url, hsdata.hs_api_key); 1949 1950 var user = localStorage.getItem('user'); 1951 user = JSON.parse(user); 1952 1953 const loggedIn = isUserLoggedIn(); 1954 1955 if(typeof priceList == "undefined") { 1956 priceList = getCookie('selectedPriceList'); 1957 } 1958 1959 let headers = { 1960 'apikey': hsdata.hs_api_key, 1961 'location': getCookie('selectedLocation'), 1962 'pricelist': priceList 1963 }; 1964 1965 if(user != null && loggedIn) { 1966 headers.emailid = user.email; 1967 headers.authToken = user.authToken 1968 } 1969 1970 api.getData('/product/list?listType=ui',headers).then(response => { 1971 allProducts = response; 1972 productsArr[priceList] = response; 1973 loadBestDeals( allProducts ); 1974 loadBestSellingProducts(allProducts); 1975 loadHomeFeaturedProducts(allProducts); 1976 loadCategories( allProducts ); 1977 if(typeof navigator.serviceWorker != "undefined") { 1978 if (navigator.serviceWorker.controller) { 1979 console.log('Service Worker is active and controlling the page'); 1980 } else { 1981 const priceListType = priceList; 1982 const data = response; 1983 const customEvent = new CustomEvent('CACHE_DATA_READY', { 1984 detail: { priceListType, data } 1985 }); 1986 window.dispatchEvent(customEvent); 1987 } 1988 } 1989 else { 1990 const priceListType = priceList; 1991 const data = response; 1992 const customEvent = new CustomEvent('CACHE_DATA_READY', { 1993 detail: { priceListType, data } 1994 }); 1995 window.dispatchEvent(customEvent); 1996 } 1997 // window.dispatchEvent(new Event('CACHE_DATA_READY')); 1998 // sessionStorage.setItem('products', JSON.stringify(response)); 1999 }) 2000 .catch(error => { 2001 console.error('Error posting data:', error); 2002 });
2003} 2004 2005function loadProductListbyPL( priceList ) { 2006 const api = new HomesomeAPI(hsdata.base_url, hsdata.hs_api_key); 2007 2008 var user = localStorage.getItem('user'); 2009 user = JSON.parse(user); 2010 2011 const loggedIn = isUserLoggedIn(); 2012 2013 if(typeof priceList == "undefined") { 2014 priceList = getCookie('selectedPriceList'); 2015 } 2016 2017 let headers = { 2018 'apikey': hsdata.hs_api_key, 2019 'location': getCookie('selectedLocation'), 2020 'pricelist': priceList 2021 }; 2022 2023 if(user != null && loggedIn) { 2024 headers.emailid = user.email; 2025 headers.authToken = user.authToken 2026 } 2027 2028 api.getData('/product/list?listType=ui',headers).then(response => { 2029 productsArr[priceList] = response; 2030 if(typeof navigator.serviceWorker != "undefined") { 2031 if (navigator.serviceWorker.controller) { 2032 console.log('Service Worker is active and controlling the page'); 2033 } else { 2034 const priceListType = priceList; 2035 const data = response; 2036 const customEvent = new CustomEvent('CACHE_DATA_READY', { 2037 detail: { priceListType, data } 2038 }); 2039 window.dispatchEvent(customEvent); 2040 } 2041 } 2042 else { 2043 const priceListType = priceList; 2044 const data = response; 2045 const customEvent = new CustomEvent('CACHE_DATA_READY', { 2046 detail: { priceListType, data } 2047 }); 2048 window.dispatchEvent(customEvent); 2049 } 2050 }) 2051 .catch(error => { 2052 console.error('Error posting data:', error); 2053 }); 2054} 2055 2056function loadMyItems( allProductsData ) { 2057 const loggedIn = isUserLoggedIn(); 2058 if(loggedIn) { 2059 const myItemsListWrap = jQuery('.svt-my-items-listing-wrap'); 2060 const noItems = jQuery('.svt-no-items-wrapper'); 2061 const myItemsListContainer = jQuery('.svt-my-items-listing-container'); 2062 const myItemsList = jQuery('.svt-my-items-listing-wrap .svt-order-products-list'); 2063 const myItemsListSkeletonBoxes = jQuery('.svt-my-items-listing-wrap .svt-order-products-list .shimmer-product-boxes'); 2064 const api = new HomesomeAPI(hsdata.base_url, hsdata.hs_api_key); 2065 2066 var user = localStorage.getItem('user'); 2067 2068 if(user != null) { 2069 user = JSON.parse(user); 2070 2071 if(typeof priceList == "undefined") { 2072 priceList = getCookie('selectedPriceList'); 2073 } 2074 2075 let headers = { 2076 'apikey': hsdata.hs_api_key, 2077 'location': getCookie('selectedLocation'), 2078 'pricelist': priceList 2079 }; 2080 2081 if(user != null) { 2082 headers.emailid = user.email; 2083 headers.authToken = user.authToken; 2084 } 2085 2086 api.getData('/v2/user/shoppinglists',headers).then(response => { 2087 if(response.lists) { 2088 sessionStorage.setItem('shoppingLists', JSON.stringify(response)); 2089 } 2090 const fav = response.lists.filter((list) => list.displayName == "Favorites" ); 2091 if(fav.length) { 2092 const favID = fav[0].name; 2093 sessionStorage.setItem('favListID',favID); 2094 const productIDs = fav[0].contents; 2095 if(productIDs) { 2096 var productsData = allProductsData.products; 2097 var promotions = allProductsData.promotions; 2098 const ids = Object.keys(productIDs); 2099 const myItems = productsData.filter(product => ids.includes(product.name)); 2100 if(myItems.length) { 2101 let types = [...new Set(myItems.flatMap(product => product.type))].sort(); 2102 2103 // Build category filter HTML based on unique types 2104 if (types.length) { 2105 let catHtml = ` 2106 <div class="svt-profile-search-filter-wrapper"> 2107 <div class="svt-profile-category-filter-wrapper swiper-container swiper-my-items"> 2108 <div class="svt-profile-category-filter-carousel-el swiper-wrapper"> 2109 <div class="svt-profile-category-filter-box active swiper-slide"> 2110 <div class="svt-profile-category-filter-img"> 2111 <svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 26 26" fill="none"> 2112 <path d="M7.69809 6.63627C7.11234 6.63627 6.63749 7.11112 6.63749 7.69687C6.63749 8.28263 7.
211211234 8.75748 7.69809 8.75748H7.7087C8.29446 8.75748 8.76931 8.28263 8.76931 7.69687C8.76931 7.11112 8.29446 6.63627 7.7087 6.63627H7.69809Z" fill="#CB333B"/> 2113 <path fill-rule="evenodd" clip-rule="evenodd" d="M2.39506 1.59839C1.95575 1.59839 1.59961 1.95453 1.59961 2.39384V12.9999C1.59961 13.211 1.68354 13.4135 1.83292 13.5627L10.9429 22.6621C11.2137 22.9331 11.5356 23.1484 11.8895 23.2952C12.2436 23.4419 12.6231 23.5175 13.0064 23.5175C13.3897 23.5175 13.7693 23.4419 14.1233 23.2952C14.4774 23.1484 14.7991 22.9332 15.07 22.6621L22.6742 15.0578L22.6759 15.0562C23.2191 14.5097 23.524 13.7704 23.524 12.9999C23.524 12.2294 23.2191 11.4901 22.6759 10.9437L13.5636 1.83137C13.4144 1.6822 13.2121 1.59839 13.0011 1.59839H2.39506ZM3.19052 12.6701V3.1893H12.6716L21.5476 12.0652C21.7941 12.3136 21.9331 12.6499 21.9331 12.9999C21.9331 13.3499 21.7947 13.6856 21.5482 13.9339L13.9447 21.5374C13.8216 21.6607 13.6751 21.7588 13.5141 21.8255C13.3532 21.8922 13.1807 21.9266 13.0064 21.9266C12.8322 21.9266 12.6597 21.8922 12.4987 21.8255C12.3378 21.7588 12.1916 21.661 12.0685 21.5377L3.19052 12.6701Z" fill="#CB333B"/> 2114 </svg> 2115 </div> 2116 <h6>All</h6> 2117 </div>`; 2118 2119 // Convert Set to array, sanitize, and build the filter items 2120 types.forEach(cat => { 2121 let catSlug = sanitizeTitle(cat); 2122 $categoryImgs = JSON.parse(sitedata.categoryImgs); 2123 let catImg = $categoryImgs[catSlug] || ''; 2124 catHtml += ` 2125 <div class="svt-profile-category-filter-box swiper-slide" data-name="${catSlug}"> 2126 <div class="svt-profile-category-filter-img"> 2127 <img src="${catImg}" alt="${cat}"> 2128 </div> 2129 <h6>${cat}</h6> 2130 </div>`; 2131 }); 2132 2133 catHtml += `</div> 2134 </div> 2135 <!-- Add Pagination --> 2136 <div class="swiper-pagination"></div> 2137 2138 <!-- Add Navigation --> 2139 <div class="swiper-button-next"></div> 2140 <div class="swiper-button-prev"></div> 2141 </div>`; 2142 jQuery(catHtml).insertBefore(myItemsListContainer); 2143 2144 // console.log(catHtml); 2145 2146 // Initialize slick carousel 2147 if(myItemsListWrap.find('.svt-profile-category-filter-carousel-el').length) { 2148 var swiperMyItems = new Swiper('.swiper-my-items', { 2149 direction: 'horizontal', 2150 slidesPerView: 7, 2151 spaceBetween: 10, 2152 loop: false, 2153 navigation: { 2154 nextEl: '.swiper-button-next', 2155 prevEl: '.swiper-button-prev', 2156 }, 2157 breakpoints: { 2158 1100: { 2159 slidesPerView: 7, 2160 }, 2161 1024: { 2162 slidesPerView: 5.5, 2163 }, 2164 768: { 2165 slidesPerView: 5.5, 2166 }, 2167 640: { 2168 slidesPerView: 4.5, 2169 navigation: { 2170 enabled: false, // Disable navigation on mobile 2171 }, 2172 }, 2173 0: { 2174 slidesPerView: 4.5, 2175 navigation: { 2176 enabled: false, // Disable navigation on mobile 2177 }, 2178 }, 2179 }, 2180 }); 2181 2182 function checkArrowsVisibilityMyItems() { 2183 const totalSlidesMyItems = swiperMyItems.slides.length; // Total number of slides 2184 const slidesToShowMyItems = swiperMyItems.params.slidesPerView; // Slides per view 2185 2186 // Determine if arrows should be shown 2187 const showArrowsItems = totalSlidesMyItems > slidesToShowMyItems; 2188 2189 // Add or remove class on the Swiper container based on arrow visibility 2190 const swiperContainerMyItems = document.querySelector('.swiper-my-items'); 2191 if (!showArrowsItems) { 2192 swiperContainerMyItems.classList.add('no-arrows'); 2193 } else { 2194 swiperContainerMyItems.classList.remove('no-arrows'); 2195 } 2196 } 2197 2198 // Call this function on initialization and on window resize 2199 checkArrowsVisibilityMyItems();
2200 window.addEventListener('resize', checkArrowsVisibilityMyItems); 2201 } 2202 } 2203 var html = myItems.map(product => renderProductCard(product, promotions)).join(''); 2204 myItemsListSkeletonBoxes.hide(); 2205 myItemsList.append(html); 2206 initPriceInfoTip(); 2207 ids.forEach((productID) => { 2208 if(jQuery('.svt-product-box[data-id="'+productID+'"]').length) { 2209 jQuery('.svt-product-box[data-id="'+productID+'"]').addClass('in-fav'); 2210 } 2211 }); 2212 } 2213 else { 2214 myItemsListWrap.hide(); 2215 noItems.show(); 2216 } 2217 } 2218 else { 2219 myItemsListWrap.hide(); 2220 noItems.show(); 2221 } 2222 } 2223 else { 2224 myItemsListWrap.hide(); 2225 noItems.show(); 2226 } 2227 // window.dispatchEvent(new Event('CACHE_DATA_READY')); 2228 // sessionStorage.setItem('products', JSON.stringify(response)); 2229 }) 2230 .catch(error => { 2231 console.error('Error posting data:', error); 2232 }); 2233 } 2234 } 2235} 2236 2237function openPDPPopup(productID, pricelist) { 2238 jQuery('body').addClass('svt-popup-active'); 2239 jQuery('.svt-pdp-popup').fadeIn(); 2240 jQuery('.svt-pdp-popup').find('.bouncing-loader').show(); 2241 2242 // Retrieve the base source URL and append the productID 2243 let src = jQuery('.svt-pdp-popup').find('.svt-popup-embed').attr('data-src'); 2244 src = src + productID; 2245 2246 // Add location if available 2247 let selectedLocation = sessionStorage.getItem('ls.location'); 2248 if (selectedLocation !== null) { 2249 selectedLocation = JSON.parse(selectedLocation); 2250 // src += src.includes('?') ? '&locName=' + selectedLocation.locName : '?locName=' + selectedLocation.locName; 2251 } 2252 2253 // Add selected price list if available 2254 let selectedPricelist = sessionStorage.getItem('ls.selectedPriceList'); 2255 if (selectedPricelist !== null) { 2256 selectedPricelist = JSON.parse(selectedPricelist); 2257 if(typeof pricelist !== "undefined" && pricelist !== null && pricelist !== '') { 2258 selectedPricelist = selectedLocation.priceLists.find(p => p.uniqueName === pricelist); 2259 } 2260 let plist = getUrlParameter('plist'); 2261 // console.log(plist); 2262 if(plist !== null) { 2263 plist = plist.toLowerCase(); 2264 if(plist == 'catering') { 2265 const cateringPricelist = localStorage.getItem('ls.cateringPriceListID'); 2266 selectedPricelist = JSON.parse(cateringPricelist); 2267 } 2268 if(plist == 'deli') { 2269 const deliPriceList = localStorage.getItem('ls.deliPriceList'); 2270 selectedPricelist = JSON.parse(deliPriceList); 2271 } 2272 } 2273 // src += src.includes('?') ? '&pListName=' + selectedPricelist.pListName : '?pListName=' + selectedPricelist.pListName; 2274 } 2275 2276 // Set the updated src to the embed element 2277 jQuery('.svt-pdp-popup').find('.svt-popup-embed').attr('data-pricelist', JSON.stringify(selectedPricelist)); 2278 jQuery('.svt-pdp-popup').find('.svt-popup-embed').attr('src', src); 2279} 2280 2281function setUserCookie() { 2282 const date = new Date(); 2283 date.setFullYear(date.getFullYear() + 10); // Set expiration to 10 years in the future 2284 document.cookie = `userLoggedIn=1; path=/; expires=${date.toUTCString()};`; 2285} 2286 2287function removeUserCookie() { 2288 document.cookie = 'userLoggedIn=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 2289} 2290 2291function logoutUser() { 2292 jQuery('body').removeClass('hs-logged-in'); 2293 removeUserCookie(); 2294 localStorage.removeItem('user'); 2295 localStorage.removeItem('basket'); 2296 jQuery('.hs-cart-count').removeClass('active'); 2297} 2298 2299function isUserLoggedIn() { 2300 const loggedIn = getCookie('userLoggedIn'); 2301 const user = JSON.parse(localStorage.getItem('user')); 2302 if(loggedIn != null || user != null) { 2303 if(user != null && loggedIn == null) { 2304 setUserCookie(); 2305 } 2306 else if(user == null) { 2307 logoutUser(); 2308 } 2309 return true; 2310 } 2311 return false; 2312} 2313 2314function getUserData() { 2315 let user = JSON.parse(localStorage.getItem('user')); 2316 if(user != null) { 2317 return user; 2318 } 2319 return null; 2320} 2321 2322document.addEventListener('DOMContentLoaded', () => { 2323 const happyFormInputs = document.querySelectorAll('.happyforms-input input'); 2324 2325 if (happyFormInputs.length > 0) {
2326 happyFormInputs.forEach((input) => { 2327 const placeholderText = input.getAttribute('placeholder'); 2328 if (placeholderText) { 2329 input.setAttribute('aria-label', placeholderText); 2330 } else { 2331 input.setAttribute('aria-label', 'Input field'); 2332 } 2333 }); 2334 // console.log('ARIA labels have been added to Happy Form inputs.'); 2335 } else { 2336 // console.log('No Happy Form inputs found on the page.'); 2337 } 2338 2339 const happyFormTextarea = document.querySelectorAll('.happyforms-part__el textarea'); 2340 2341 if (happyFormTextarea.length > 0) { 2342 happyFormTextarea.forEach((input) => { 2343 const placeholderText = input.getAttribute('placeholder'); 2344 if (placeholderText) { 2345 input.setAttribute('aria-label', placeholderText); 2346 } else { 2347 input.setAttribute('aria-label', 'Input field'); 2348 } 2349 }); 2350 // console.log('ARIA labels have been added to Happy Form inputs.'); 2351 } else { 2352 // console.log('No Happy Form inputs found on the page.'); 2353 } 2354 2355 const hiddenFields = document.querySelectorAll('input[type="text"][tabindex="-1"]'); 2356 2357 if (hiddenFields.length > 0) { 2358 hiddenFields.forEach((input) => { 2359 input.setAttribute('aria-label', 'Hidden Field'); 2360 }); 2361 // console.log('ARIA labels have been added to Happy Form inputs.'); 2362 } 2363 2364 var skipLink = document.querySelector('.skip-link'); 2365 if (skipLink) { 2366 skipLink.remove(); 2367 } 2368}); 2369 2370function refreshLocationData() { 2371 const lsLocation = JSON.parse(sessionStorage.getItem('ls.location')); 2372 if (lsLocation) { 2373 const api = new HomesomeAPI(hsdata.base_url, hsdata.hs_api_key); 2374 let headers = { 2375 'apikey': hsdata.hs_api_key 2376 }; 2377 2378 const loggedIn = isUserLoggedIn(); 2379 2380 if(loggedIn) { 2381 const user = JSON.parse(localStorage.getItem('user')); 2382 if(user) { 2383 headers.emailid = user.email; 2384 headers.authToken = user.authToken; 2385 } 2386 } 2387 api.getData('/locations', headers) 2388 .then(response => { 2389 let locations = response; 2390 locations = locations.filter(item => item.isDisabled == false); 2391 let location = locations.filter(item => lsLocation.uniqueName == item.uniqueName); 2392 let locationData = location[0]; 2393 sessionStorage.setItem('ls.location',JSON.stringify(locationData)); 2394 sessionStorage.setItem('ls.allLocations',JSON.stringify(locations)); 2395 localStorage.setItem('ls.location',JSON.stringify(locationData)); 2396 }) 2397 .catch(console.error); 2398 } 2399} 2400 2401window.addEventListener("load", function () { 2402 let navigationType; 2403 2404 if (performance.getEntriesByType("navigation").length > 0) { 2405 // Modern browsers 2406 navigationType = performance.getEntriesByType("navigation")[0].type; 2407 } else { 2408 // Fallback for older browsers 2409 navigationType = performance.navigation.type === 1 ? 'reload' : 'navigate'; 2410 } 2411 2412 if (navigationType === "reload") { 2413 console.log("Page was refreshed"); 2414 setTimeout(function() { 2415 refreshLocationData(); 2416 },1000); 2417 } 2418}); 2419 2420(function($) { 2421 $(window).on('CACHE_DATA_READY',function(event) { 2422 if(allProducts.length) { 2423 loadMyItems(allProducts); 2424 loadBuyAgainProductsData(allProducts); 2425 } 2426 else { 2427 loadMyItems(event.detail.data); 2428 loadBuyAgainProductsData(event.detail.data); 2429 } 2430 }); 2431 window.addEventListener('locationSet',function() { 2432 setTimeout(function() { 2433 const links = document.querySelectorAll('a'); 2434 if(links) { 2435 const matchingLinks = Array.from(links).filter(link => link.href === sitedata.home_url+'/cakes/'); 2436 let location = sessionStorage.getItem('ls.location'); 2437 location = JSON.parse(location); 2438 let locationName = location.name; 2439 locationName = sanitizeTitle(locationName); 2440 let cakesLinks = sitedata.cakesLinks; 2441 cakesLinks = JSON.parse(cakesLinks); 2442 const url = cakesLinks[locationName]?.toString(); 2443 if(typeof url != "undefined") { 2444 matchingLinks.forEach(link => { 2445 link.href = url; 2446 link.target = '_blank'; 2447 }); 2448 } 2449 } 2450 // loadUserPoints();
2451 loadProductList(); 2452 if(jQuery('.svt-wa-digital-link').length) { 2453 let location = sessionStorage.getItem('ls.location'); 2454 location = JSON.parse(location); 2455 let locationName = location.name; 2456 // console.log(locationName); 2457 locationName = sanitizeTitle(locationName); 2458 let waDigital = sitedata.waDigital; 2459 waDigital = JSON.parse(waDigital); 2460 const url = waDigital[locationName]?.toString(); 2461 if(typeof url != "undefined") { 2462 const html = `Explore our new digital ad <a href="${url}" target="_blank"> 2463 <span>Switch to Digital View</span> 2464 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> 2465 <path fill-rule="evenodd" clip-rule="evenodd" d="M8.46967 5.46967C8.76256 5.17678 9.23744 5.17678 9.53033 5.46967L15.5303 11.4697C15.8232 11.7626 15.8232 12.2374 15.5303 12.5303L9.53033 18.5303C9.23744 18.8232 8.76256 18.8232 8.46967 18.5303C8.17678 18.2374 8.17678 17.7626 8.46967 17.4697L13.9393 12L8.46967 6.53033C8.17678 6.23744 8.17678 5.76256 8.46967 5.46967Z" fill="#CB333B"></path> 2466 </svg> 2467 </a>`; 2468 jQuery('.svt-wa-digital-link').html(html); 2469 } 2470 } 2471 2472 if($('.svt-contact-store-info').length) { 2473 let location = sessionStorage.getItem('ls.location'); 2474 let html = ''; 2475 if(location != null) { 2476 location = JSON.parse(location); 2477 let location_data; 2478 if ("locationImgUrl" in location) { 2479 location_data = location.locationImgUrl; 2480 } else { 2481 location_data = "/wp-content/uploads/no-store-image-large.jpg"; 2482 } 2483 let address = ''; 2484 if(location.address.aptUnit != '') { 2485 address += location.address.aptUnit+' '; 2486 } 2487 if(location.address.street != '') { 2488 address += location.address.street; 2489 } 2490 if(location.address.city != '') { 2491 address += '<br>'+location.address.city+', '; 2492 } 2493 if(location.address.state != '') { 2494 address += location.address.state+' '; 2495 } 2496 if(location.address.zip != '') { 2497 address += location.address.zip; 2498 } 2499 let hours = location.operatingHours; 2500 // console.log(hours); 2501 html += `<div class="svt-contact-store-info-top"> 2502 <div class="svt-contact-store-info-left"> 2503 <div class="svt-contact-store-address">${address}</div> 2504 <div class="svt-contact-change-store"> 2505 <a href="/select-the-location/?ref=contact-us"> 2506 Change Store 2507 <svg xmlns="http://www.w3.org/2000/svg" width="6" height="11" viewB
2507ox="0 0 6 11" fill="none"> 2508 <path d="M1 9.5L5 5.5L1 1.5" stroke="#232323" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/> 2509 </svg> 2510 </a> 2511 </div> 2512 <div class="svt-store-phone"> 2513 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> 2514 <path d="M14.2327 22C13.6889 22 13.1507 21.7996 12.7241 21.4141C10.3942 19.3092 8.46556 16.6775 7.14902 13.8057C5.81387 10.8955 5.09098 7.78668 5.00097 4.56845C4.97471 3.64768 5.48383 2.80322 6.2986 2.41584L8.82536 1.21548C9.37104 0.957849 9.98236 0.930174 10.5459 1.13819C11.1103 1.34715 11.5613 1.76794 11.8154 2.32233L13.084 5.0894C13.3381 5.64376 13.3653 6.26589 13.1599 6.84031C12.9546 7.41473 12.5411 7.87368 11.9964 8.13227L10.424 8.87843C10.5196 9.90321 10.7896 10.9156 11.2256 11.8678C11.6597 12.8143 12.2457 13.6731 12.9677 14.4192L14.5335 13.6654C15.6567 13.132 16.9993 13.6272 17.5245 14.7722L18.7931 17.5393C19.0603 18.1213 19.0687 18.7654 18.8184 19.3503C18.5699 19.9285 18.0945 20.398 17.442 20.7081L15.1758 21.7844C14.8739 21.9275 14.5513 21.9972 14.2307 21.9972L14.2327 22ZM9.7764 2.53013C9.66951 2.53013 9.56262 2.55303 9.46043 2.60169L6.93366 3.80205C6.66176 3.93086 6.49206 4.21616 6.50049 4.52626C6.58487 7.53564 7.26089 10.4402 8.50884 13.1616C9.73991 15.8466 11.5421 18.3057 13.7201 20.274C13.9498 20.481 14.2723 20.5326 14.5433 20.4047L16.8095 19.3284C17.1217 19.1805 17.3477 18.9725 17.4452 18.7435C17.522 18.5632 17.5192 18.3714 17.4358 18.1882L16.1672 15.4211C16.0828 15.236 15.9328 15.0967 15.7443 15.0261C15.5559 14.9555 15.3524 14.965 15.1705 15.0518L13.5991 15.798C13.0234 16.0709 12.3418 15.9488 11.9011 15.4927C11.0591 14.6215 10.3756 13.6206 9.86932 12.5155C9.36114 11.4049 9.04517 10.2246 8.93173 9.00712C8.8736 8.37642 9.21863 7.77051 9.79244 7.49761L11.3648 6.75049C11.7399 6.57302 11.903 6.11691 11.7267 5.73622L10.4581 2.96915C10.3316 2.69245 10.0596 2.52832 9.77744 2.52832L9.7764 2.53013Z" fill="#767676"/> 2515 </svg> 2516 Phone: ${location.phone} 2517 </div> 2518 </div> 2519 <div class="svt-contact-store-info-right"> 2520 <div class="svt-store-img-wrap"> 2521 <img fetchpriority="high" decoding="async" onerror="this.onerror=null; this.removeAttribute('srcset'); this.src='${embeddata.theme_url}/images/location-placeholder.svg'" src="${location_data}" alt="${location.name}" srcset="${location_data} 448w, ${location_data} 448w" /> 2522 </div> 2523 </div> 2524 </div> 2525 <div class="svt-contact-store-info-bottom"> 2526 <div class="svt-store-time"> 2527 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> 2528 <path d="M12.75 6C12.75 5.58579 12.4142 5.25 12 5.25C11.5858 5.25 11.25 5.58579 11.25 6V12C11.25 12.2841 11.4105 12.5438 11.6646 12.6708L15.6646 14.6708C16.0351 14.8561 16.4856 14.7059 16.6708 14.3354C16.8561 13.9649 16.7059 13.5144 16.3354 13.3292L12.75 11.5365V6Z" fill="#767676"/> 2529 <path fill-rule="evenodd" clip-rule="evenodd" d="M12 1.25C6.06294 1.25 1.25 6.06294 1.25 12C1.25 17.9371 6.06294 22.75 12 22.75C17.9371 22.75 22.75 17.9371 22.75 12C22.75 6.06294 17.9371 1.25 12 1.25ZM2.75 12C2.75 6.89137 6.89137 2.75 12 2.75C17.1086 2.75 21.25 6.89137 21.25 12C21.25 17.1086 17.1086 21.25 12 21.25C6.89137 21.25 2.75 17.1086 2.75 12Z" fill="#767676"/> 2530 </svg> 2531 Timings 2532 </div> 2533 <div class="svt-store-time-table"> 2534 <table id="dynamic-table" class="has-text-color has-link-color has-border-color has-theme-palette-9-border-color"> 2535 <tbody> 2536 ${(() => { 2537 let rows = '';
2538 hours.forEach((hour) => { 2539 rows += ` 2540 <tr> 2541 <td>${hour.day}</td> 2542 <td class="has-text-align-right" data-align="right">${hour.hours}</td> 2543 </tr> 2544 `; 2545 }); 2546 return rows; // Return the constructed rows 2547 })()} 2548 </tbody> 2549 </table> 2550 </div> 2551 </div> 2552 <div class="svt-contact-direction"> 2553 <a href="https://www.google.com/maps?q=${location.latitude},${location.longitude}" target="_blank"> 2554 <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none"> 2555 <path d="M12.5303 0.46967C12.2374 0.176777 11.7626 0.176777 11.4697 0.46967C11.1768 0.762563 11.1768 1.23744 11.4697 1.53033L15.1893 5.25H5C3.74022 5.25 2.53204 5.75044 1.64124 6.64124C0.750445 7.53204 0.25 8.74022 0.25 10V17C0.25 17.4142 0.585786 17.75 1 17.75C1.41421 17.75 1.75 17.4142 1.75 17V10C1.75 9.13805 2.09241 8.3114 2.7019 7.7019C3.3114 7.09241 4.13805 6.75 5 6.75H15.1893L11.4697 10.4697C11.1768 10.7626 11.1768 11.2374 11.4697 11.5303C11.7626 11.8232 12.2374 11.8232 12.5303 11.5303L17.5303 6.53033C17.8232 6.23744 17.8232 5.76256 17.5303 5.46967L12.5303 0.46967Z" fill="#CB333B"/> 2556 </svg> 2557 Get Directions 2558 </a> 2559 </div>`; 2560 $('.svt-contact-store-info').html(html); 2561 } 2562 } 2563 const updateCartCountFn = (items) => { 2564 const loggedIn = isUserLoggedIn(); 2565 const cartCount = items.length; 2566 if(cartCount > 0 && loggedIn) { 2567 $('.hs-cart-count').html(cartCount).addClass('active'); 2568 } 2569 else { 2570 $('.hs-cart-count').html('').removeClass('active'); 2571 } 2572 }; 2573 2574 const fetchBasketData = (user) => { 2575 const api = new HomesomeAPI(hsdata.base_url, hsdata.hs_api_key); 2576 const email = user.email; 2577 2578 let headers = { 2579 'emailid': email, 2580 'authToken': user.authToken, 2581 'location': getCookie('selectedLocation'), 2582 'pricelist': getCookie('selectedPriceList'), 2583 'Content-Type': 'application/json' 2584 }; 2585 2586 return api.getData('/user/basket?lite=true', headers) 2587 .then(response => { 2588 if (response.basketItems) { 2589 setBasket(response); 2590 updateCartCountFn(response.basketItems); 2591 } 2592 }) 2593 .catch(error => console.error('Error fetching basket data:', error)); 2594 }; 2595 2596 const loadUserSession = async () => { 2597 const user = JSON.parse(localStorage.getItem('user')); 2598 if(user != null) { 2599 try { 2600 const api = new HomesomeAPI(hsdata.base_url, hsdata.hs_api_key); 2601 const email = user.email; 2602 2603 let headers = { 2604 'emailid': email, 2605 'authToken': user.authToken, 2606 'location': getCookie('selectedLocation'), 2607 'Content-Type': 'application/json' 2608 }; 2609 2610 return await api.getData('/user', headers) 2611 .then(response => { 2612 if(!response.error) { 2613 const user = JSON.stringify(response); 2614 localStorage.setItem('user', user); 2615 setUserCookie(); 2616 return response; 2617 } 2618 return null; 2619 }) 2620 .catch(error => { 2621 console.error('Error fetching user data:', error); 2622 return null; // Return null if there's an error 2623 }); 2624 } catch (error) { 2625 console.error('Error fetching user session:', error); 2626 return null; // Return null if there's an exception 2627 } 2628 } 2629 }; 2630 2631 const initializeBasket = () => { 2632 let user = localStorage.getItem('user'); 2633 if (user) { 2634 user = JSON.parse(user); 2635 let basket = localStorage.getItem('basket'); 2636 if (!basket) { 2637 return fetchBasketData(user); 2638 } else { 2639 basket = JSON.parse(basket); 2640 if(typeof basket.items != "undefined") { 2641 updateCartCountFn(basket.items); 2642 } 2643 else { 2644 return fetchBasketData(user); 2645 } 2646 } 2647 } 2648 }; 2649 2650 const loggedIn = isUserLoggedIn(); 2651 2652 console.log('Logged in: ',loggedIn); 2653 if (loggedIn == false) { 2654 const user = localStorage.getItem('user'); 2655 // console.log(user); 2656 if (isRefreshed) { 2657 isRefreshed = false; 2658 loadUserSession().then(user => { 2659 // console.log('After load session: ',user); 2660 if (user) { 2661 // console.log('user session set'); 2662 initializeBasket(); 2663 // loadPointsHistory(); 2664 // loadLifetimeSaving(); 2665 } 2666 }); 2667 } else { 2668 initializeBasket(); 2669 } 2670 } 2671 else { 2672 jQuery('body').addClass('hs-logged-in'); 2673 const user = localStorage.getItem('user'); 2674 if (isRefreshed) { 2675 isRefreshed = false; 2676 loadUserSession().then(user => { 2677 // console.log('After load session: ',user); 2678 if (user) { 2679 // console.log('user session set'); 2680 initializeBasket(); 2681 // loadPointsHistory(); 2682 // loadLifetimeSaving(); 2683 } 2684 }); 2685 } else { 2686 initializeBasket(); 2687 } 2688 } 2689 },100); 2690 });
2691 $(document).ready(function() { 2692 initLocation(); 2693 $(document).on('click','.mobile-app-popup-close',function() { 2694 document.cookie = `mobileAppClosed=1; path=/`; 2695 $('.svt-mobile-app-popup').fadeOut(); 2696 }); 2697 let lastScrollY = $(window).scrollTop(); 2698 $(window).on('scroll', function () { 2699 const currentScrollY = $(window).scrollTop(); 2700 if (currentScrollY < lastScrollY) { 2701 // Scrolling up 2702 $('body').addClass('scrolling-up').removeClass('scrolling-down'); 2703 } else { 2704 // Scrolling down 2705 $('body').addClass('scrolling-down').removeClass('scrolling-up'); 2706 if(currentScrollY < 190) { 2707 $('body').removeClass('scrolling-down'); 2708 } 2709 } 2710 lastScrollY = currentScrollY <= 0 ? 0 : currentScrollY; // Prevent negative values 2711 }); 2712 }); 2713 $(window).load(function() { 2714 if($(window).width() < 768) { 2715 const mobileAppClosed = getCookie('mobileAppClosed'); 2716 if(mobileAppClosed == null) { 2717 $('.svt-mobile-app-popup').fadeIn(); 2718 } 2719 } 2720 }); 2721})(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.