The repo for Purrform's main BigCommerce store.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: bug with credit orders not having tax

+1398 -1406
+1 -1
config.json
··· 1 1 { 2 - "name": "diet-builder - new fields", 2 + "name": "fix credit orders", 3 3 "version": "6.10.0", 4 4 "template_engine": "handlebars_v4", 5 5 "meta": {
+1397 -1405
templates/pages/checkout.html
··· 1 1 {{#partial "head"}} 2 2 3 - {{{ checkout.checkout_head }}} 4 - {{{ stylesheet '/assets/css/optimized-checkout.css' }}} 3 + {{{ checkout.checkout_head }}} 4 + {{{ stylesheet '/assets/css/optimized-checkout.css' }}} 5 5 6 - {{ getFontsCollection }} 6 + {{ getFontsCollection }} 7 7 8 - <script type="text/javascript"> 9 - window.language = {{{langJson 'optimized_checkout'}}}; 10 - </script> 8 + <script type="text/javascript"> 9 + window.language = {{{langJson 'optimized_checkout' }}}; 10 + </script> 11 11 12 - {{{head.scripts}}} 12 + {{{head.scripts}}} 13 13 14 14 {{/partial}} 15 15 ··· 17 17 18 18 {{#partial "page"}} 19 19 20 - <!-- UIkit CSS --> 21 - <link 22 - rel="stylesheet" 23 - href="https://cdn.jsdelivr.net/npm/uikit@3.15.14/dist/css/uikit.min.css" 24 - /> 25 - <link rel="stylesheet" href="https://use.typekit.net/drc3iaj.css" /> 20 + <!-- UIkit CSS --> 21 + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.15.14/dist/css/uikit.min.css" /> 22 + <link rel="stylesheet" href="https://use.typekit.net/drc3iaj.css" /> 26 23 27 - <!-- UIkit JS --> 28 - <script src="https://cdn.jsdelivr.net/npm/uikit@3.15.14/dist/js/uikit.min.js"></script> 29 - <script src="https://cdn.jsdelivr.net/npm/uikit@3.15.14/dist/js/uikit-icons.min.js"></script> 24 + <!-- UIkit JS --> 25 + <script src="https://cdn.jsdelivr.net/npm/uikit@3.15.14/dist/js/uikit.min.js"></script> 26 + <script src="https://cdn.jsdelivr.net/npm/uikit@3.15.14/dist/js/uikit-icons.min.js"></script> 30 27 31 - <!-- CALL MOST RECENT JQUERY LIBRARY --> 32 - <script 33 - src="https://code.jquery.com/jquery-3.6.2.min.js" 34 - integrity="sha256-2krYZKh//PcchRtd+H+VyyQoZ/e3EcrkxhM8ycwASPA=" 35 - crossorigin="anonymous" 36 - ></script> 37 - <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> 38 - <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script> 28 + <!-- CALL MOST RECENT JQUERY LIBRARY --> 29 + <script src="https://code.jquery.com/jquery-3.6.2.min.js" 30 + integrity="sha256-2krYZKh//PcchRtd+H+VyyQoZ/e3EcrkxhM8ycwASPA=" crossorigin="anonymous"></script> 31 + <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> 32 + <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script> 39 33 40 - <link 41 - rel="stylesheet" 42 - href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" 43 - integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" 44 - crossorigin="anonymous" 45 - /> 46 - <link 47 - rel="stylesheet" 48 - href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.min.css" 49 - /> 34 + <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" 35 + integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous" /> 36 + <link rel="stylesheet" 37 + href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.min.css" /> 50 38 51 - {{inject "checkoutId" cart_id}} 39 + {{inject "checkoutId" cart_id}} 52 40 53 - <script> 54 - // This is a custom function to check if an element is ready in the DOM with MutationObserver (no timers) 55 - (function (win) { 56 - 'use strict'; 41 + <script> 42 + // This is a custom function to check if an element is ready in the DOM with MutationObserver (no timers) 43 + (function (win) { 44 + 'use strict'; 57 45 58 - var listeners = [], 59 - doc = win.document, 60 - MutationObserver = 61 - win.MutationObserver || win.WebKitMutationObserver, 62 - observer; 46 + var listeners = [], 47 + doc = win.document, 48 + MutationObserver = 49 + win.MutationObserver || win.WebKitMutationObserver, 50 + observer; 63 51 64 - function ready(selector, fn) { 65 - // Store the selector and callback to be monitored 66 - listeners.push({ 67 - selector: selector, 68 - fn: fn, 69 - }); 70 - if (!observer) { 71 - // Watch for changes in the document 72 - observer = new MutationObserver(check); 73 - observer.observe(doc.documentElement, { 74 - childList: true, 75 - subtree: true, 52 + function ready(selector, fn) { 53 + // Store the selector and callback to be monitored 54 + listeners.push({ 55 + selector: selector, 56 + fn: fn, 76 57 }); 58 + if (!observer) { 59 + // Watch for changes in the document 60 + observer = new MutationObserver(check); 61 + observer.observe(doc.documentElement, { 62 + childList: true, 63 + subtree: true, 64 + }); 65 + } 66 + // Check if the element is currently in the DOM 67 + check(); 77 68 } 78 - // Check if the element is currently in the DOM 79 - check(); 80 - } 81 69 82 - function check() { 83 - // Check the DOM for elements matching a stored selector 84 - for ( 85 - var i = 0, len = listeners.length, listener, elements; 86 - i < len; 87 - i++ 88 - ) { 89 - listener = listeners[i]; 90 - // Query for elements matching the specified selector 91 - elements = doc.querySelectorAll(listener.selector); 70 + function check() { 71 + // Check the DOM for elements matching a stored selector 92 72 for ( 93 - var j = 0, jLen = elements.length, element; 94 - j < jLen; 95 - j++ 73 + var i = 0, len = listeners.length, listener, elements; 74 + i < len; 75 + i++ 96 76 ) { 97 - element = elements[j]; 98 - // Make sure the callback isn't invoked with the 99 - // same element more than once 100 - if (!element.ready) { 101 - element.ready = true; 102 - // Invoke the callback with the element 103 - listener.fn.call(element, element); 77 + listener = listeners[i]; 78 + // Query for elements matching the specified selector 79 + elements = doc.querySelectorAll(listener.selector); 80 + for ( 81 + var j = 0, jLen = elements.length, element; 82 + j < jLen; 83 + j++ 84 + ) { 85 + element = elements[j]; 86 + // Make sure the callback isn't invoked with the 87 + // same element more than once 88 + if (!element.ready) { 89 + element.ready = true; 90 + // Invoke the callback with the element 91 + listener.fn.call(element, element); 92 + } 104 93 } 105 94 } 106 95 } 107 - } 108 96 109 - // Expose `ready` 110 - win.ready = ready; 111 - })(this); 112 - </script> 97 + // Expose `ready` 98 + win.ready = ready; 99 + })(this); 100 + </script> 113 101 114 - <script> 115 - // Handles non-cumulative discounts 116 - const couponsElSelector = 'a.redeemable-label'; 117 - ready(couponsElSelector, (couponsEl) => { 118 - // if discount el is present, customer used loyalty points, hide coupons 119 - const discountEl = document.querySelector( 120 - 'div[data-test="cart-discount"]' 121 - ); 122 - if (discountEl) { 123 - couponsEl.style.display = 'none'; 124 - } 102 + <script> 103 + // Handles non-cumulative discounts 104 + const couponsElSelector = 'a.redeemable-label'; 105 + ready(couponsElSelector, (couponsEl) => { 106 + // if discount el is present, customer used loyalty points, hide coupons 107 + const discountEl = document.querySelector( 108 + 'div[data-test="cart-discount"]' 109 + ); 110 + if (discountEl) { 111 + couponsEl.style.display = 'none'; 112 + } 125 113 126 - // if customer group is trade, hide coupons 127 - if ('{{customer_group_name}}' === 'Trade' || '{{customer_group_name}}' === 'New Trader' || '{{customer_group_name}}' === 'Trade TNC') { 128 - couponsEl.style.display = 'none'; 129 - } 130 - 131 - }) 132 - 133 - const loyaltyElSelector = 'section.loyalty-points'; 134 - ready(loyaltyElSelector, (loyaltyEl) => { 135 - const couponEl = document.querySelector( 136 - 'div[data-test="cart-coupon"]' 137 - ); 138 - 139 - if (couponEl) { 140 - const label = document.querySelector('.loyaltyLabel'); 141 - const input = loyaltyEl.querySelector('input'); 142 - const button = loyaltyEl.querySelector('#loyaltyPointsBtn'); 143 - label.style.display = 'none'; 144 - input.style.display = 'none'; 145 - button.style.display = 'none'; 114 + // if customer group is trade, hide coupons 115 + if ('{{customer_group_name}}' === 'Trade' || '{{customer_group_name}}' === 'New Trader' || '{{customer_group_name}}' === 'Trade TNC') { 116 + couponsEl.style.display = 'none'; 117 + } 146 118 147 - const removeCouponButton = couponEl.querySelector('a[data-test="cart-price-callback"]'); 148 - removeCouponButton.addEventListener('click', () => { 149 - label.style.display = 'block'; 150 - input.style.display = 'block'; 151 - button.style.display = 'block'; 152 - }); 153 - } 119 + }) 154 120 155 - // the standalone code above does not work on mobile, this is a fix for mobile 156 - const checkForCouponInterval = setInterval(() => { 121 + const loyaltyElSelector = 'section.loyalty-points'; 122 + ready(loyaltyElSelector, (loyaltyEl) => { 157 123 const couponEl = document.querySelector( 158 124 'div[data-test="cart-coupon"]' 159 125 ); ··· 167 133 button.style.display = 'none'; 168 134 169 135 const removeCouponButton = couponEl.querySelector('a[data-test="cart-price-callback"]'); 170 - 171 136 removeCouponButton.addEventListener('click', () => { 172 137 label.style.display = 'block'; 173 138 input.style.display = 'block'; 174 139 button.style.display = 'block'; 175 140 }); 176 - 177 - clearInterval(checkForCouponInterval); 178 141 } 179 - }, 100) 180 - }) 181 - </script> 182 142 183 - <script> 184 - // Handle hidding address creation for breeder group 143 + // the standalone code above does not work on mobile, this is a fix for mobile 144 + const checkForCouponInterval = setInterval(() => { 145 + const couponEl = document.querySelector( 146 + 'div[data-test="cart-coupon"]' 147 + ); 185 148 186 - const parentSelectorShipping = '#checkoutShippingAddress div.dropdownMenu'; 187 - const parentSelectorBilling = '#checkoutBillingAddress div.dropdownMenu'; 149 + if (couponEl) { 150 + const label = document.querySelector('.loyaltyLabel'); 151 + const input = loyaltyEl.querySelector('input'); 152 + const button = loyaltyEl.querySelector('#loyaltyPointsBtn'); 153 + label.style.display = 'none'; 154 + input.style.display = 'none'; 155 + button.style.display = 'none'; 188 156 189 - ready(parentSelectorShipping, (parentElement) => { 190 - // get the number of children 191 - const ul = parentElement.querySelector('ul'); 192 - const children = ul.children; 193 - const customerGroupName = '{{customer_group_name}}'; 194 - if (customerGroupName === 'Breeder' && children.length > 2) { 195 - // hide the first child (add new address) 196 - children[0].style.display = 'none'; 197 - } 198 - }); 157 + const removeCouponButton = couponEl.querySelector('a[data-test="cart-price-callback"]'); 158 + 159 + removeCouponButton.addEventListener('click', () => { 160 + label.style.display = 'block'; 161 + input.style.display = 'block'; 162 + button.style.display = 'block'; 163 + }); 164 + 165 + clearInterval(checkForCouponInterval); 166 + } 167 + }, 100) 168 + }) 169 + </script> 170 + 171 + <script> 172 + // Handle hidding address creation for breeder group 173 + 174 + const parentSelectorShipping = '#checkoutShippingAddress div.dropdownMenu'; 175 + const parentSelectorBilling = '#checkoutBillingAddress div.dropdownMenu'; 176 + 177 + ready(parentSelectorShipping, (parentElement) => { 178 + // get the number of children 179 + const ul = parentElement.querySelector('ul'); 180 + const children = ul.children; 181 + const customerGroupName = '{{customer_group_name}}'; 182 + if (customerGroupName === 'Breeder' && children.length > 2) { 183 + // hide the first child (add new address) 184 + children[0].style.display = 'none'; 185 + } 186 + }); 199 187 200 - ready(parentSelectorBilling, (parentElement) => { 201 - // get the number of children 202 - const ul = parentElement.querySelector('ul'); 203 - const children = ul.children; 204 - const customerGroupName = '{{customer_group_name}}'; 205 - if (customerGroupName === 'Breeder' && children.length > 2) { 206 - // hide the first child (add new address) 207 - children[0].style.display = 'none'; 208 - } 209 - }); 210 - </script> 188 + ready(parentSelectorBilling, (parentElement) => { 189 + // get the number of children 190 + const ul = parentElement.querySelector('ul'); 191 + const children = ul.children; 192 + const customerGroupName = '{{customer_group_name}}'; 193 + if (customerGroupName === 'Breeder' && children.length > 2) { 194 + // hide the first child (add new address) 195 + children[0].style.display = 'none'; 196 + } 197 + }); 198 + </script> 211 199 212 - {{#if customer_group_name '!==' 'trade_blocked'}} 213 - <div id="optimised_main_chout"> 214 - <header class="checkoutHeader optimizedCheckout-header"> 215 - <div class="checkoutHeader-content"> 216 - <h1 class="is-srOnly">{{lang 'checkout.title'}}</h1> 217 - <h2 class="checkoutHeader-heading"> 218 - <a class="checkoutHeader-link" href="{{urls.home}}"> 219 - {{#if checkout.header_image}} 220 - <img 221 - alt="{{settings.store_logo.title}}" 222 - class="checkoutHeader-logo" 223 - id="logoImage" 224 - src="https://cdn11.bigcommerce.com/s-lh9wfk05w0/images/stencil/original/image-manager/d-logo.png" 225 - title="{{settings.store_logo.title}}" 226 - /> 200 + {{#if customer_group_name '!==' 'trade_blocked'}} 201 + <div id="optimised_main_chout"> 202 + <header class="checkoutHeader optimizedCheckout-header"> 203 + <div class="checkoutHeader-content"> 204 + <h1 class="is-srOnly">{{lang 'checkout.title'}}</h1> 205 + <h2 class="checkoutHeader-heading"> 206 + <a class="checkoutHeader-link" href="{{urls.home}}"> 207 + {{#if checkout.header_image}} 208 + <img alt="{{settings.store_logo.title}}" class="checkoutHeader-logo" id="logoImage" 209 + src="https://cdn11.bigcommerce.com/s-lh9wfk05w0/images/stencil/original/image-manager/d-logo.png" 210 + title="{{settings.store_logo.title}}" /> 227 211 228 - {{ else }} 229 - <span class="header-logo-text">{{settings.store_logo.title}}</span> 230 - {{/if}} 231 - </a> 232 - </h2> 212 + {{ else }} 213 + <span class="header-logo-text">{{settings.store_logo.title}}</span> 214 + {{/if}} 215 + </a> 216 + </h2> 217 + </div> 218 + </header> 219 + {{{ checkout.checkout_content }}} 233 220 </div> 234 - </header> 235 - {{{ checkout.checkout_content }}} 236 - </div> 237 - {{else}} 238 - <div class="container" style="height: 200px; display: flex"> 239 - <p 240 - style=" 221 + {{else}} 222 + <div class="container" style="height: 200px; display: flex"> 223 + <p style=" 241 224 margin: 50px auto; 242 225 width: 80%; 243 226 text-align: center; 244 227 border: 1px solid; 245 228 height: 50px; 246 229 padding: 10px 5px; 247 - " 248 - >You are currently blocked for shopping. Please contact admin for more info</p> 249 - </div> 250 - {{/if}} {{#if customer}} 251 - {{#if customer_group_name '===' 'Personal'}} 230 + ">You are currently blocked for shopping. Please contact admin for more info</p> 231 + </div> 232 + {{/if}} {{#if customer}} 233 + {{#if customer_group_name '===' 'Personal'}} 252 234 253 - <script> 254 - // Handles the loyalty points 255 - const parentSelectorDesktop = '.cart.optimizedCheckout-orderSummary'; 256 - const parentSelectorMobile = 257 - '.cart-modal-body.optimizedCheckout-orderSummary'; 235 + <script> 236 + // Handles the loyalty points 237 + const parentSelectorDesktop = '.cart.optimizedCheckout-orderSummary'; 238 + const parentSelectorMobile = 239 + '.cart-modal-body.optimizedCheckout-orderSummary'; 258 240 259 - ready(parentSelectorDesktop, (parentElement) => { 260 - loyaltyInitialize(parentElement); 261 - }); 241 + ready(parentSelectorDesktop, (parentElement) => { 242 + loyaltyInitialize(parentElement); 243 + }); 262 244 263 - ready(parentSelectorMobile, (parentElement) => { 264 - loyaltyInitialize(parentElement); 265 - }); 245 + ready(parentSelectorMobile, (parentElement) => { 246 + loyaltyInitialize(parentElement); 247 + }); 266 248 267 - function loyaltyInitialize(elementToAppend) { 268 - // Fetch loyalty points 269 - fetchLoyalty().then((points) => { 270 - // Create a new div element for displaying loyalty points 271 - const pointsDiv = document.createElement('section'); 272 - const pointsDesc = document.createElement('p'); 273 - pointsDesc.id = 'pointsDesc'; 274 - if (points == null) { 275 - pointsDesc.innerHTML = "Could not find loyalty points for this account, make sure you are logged in or refresh the page."; 276 - } else { 277 - pointsDesc.innerHTML = `Loyalty points balance ${points}`; 278 - } 279 - pointsDiv.appendChild(pointsDesc); 280 - pointsDiv.className = 'cart-section optimizedCheckout-orderSummary-cartSection loyalty-points'; 249 + function loyaltyInitialize(elementToAppend) { 250 + // Fetch loyalty points 251 + fetchLoyalty().then((points) => { 252 + // Create a new div element for displaying loyalty points 253 + const pointsDiv = document.createElement('section'); 254 + const pointsDesc = document.createElement('p'); 255 + pointsDesc.id = 'pointsDesc'; 256 + if (points == null) { 257 + pointsDesc.innerHTML = "Could not find loyalty points for this account, make sure you are logged in or refresh the page."; 258 + } else { 259 + pointsDesc.innerHTML = `Loyalty points balance ${points}`; 260 + } 261 + pointsDiv.appendChild(pointsDesc); 262 + pointsDiv.className = 'cart-section optimizedCheckout-orderSummary-cartSection loyalty-points'; 281 263 282 - // Create a label and input for entering points to use 283 - const label = document.createElement('label'); 284 - label.setAttribute('for', 'points-input'); 285 - label.classList.add('loyaltyLabel'); 286 - pointsDiv.appendChild(label); 264 + // Create a label and input for entering points to use 265 + const label = document.createElement('label'); 266 + label.setAttribute('for', 'points-input'); 267 + label.classList.add('loyaltyLabel'); 268 + pointsDiv.appendChild(label); 287 269 288 - const pointsInput = document.createElement('input'); 289 - pointsInput.type = 'number'; 290 - pointsInput.id = 'points-input'; 291 - pointsInput.min = 0; 292 - pointsInput.max = points; 293 - pointsInput.placeholder = 'How many?'; 294 - pointsDiv.appendChild(pointsInput); 270 + const pointsInput = document.createElement('input'); 271 + pointsInput.type = 'number'; 272 + pointsInput.id = 'points-input'; 273 + pointsInput.min = 0; 274 + pointsInput.max = points; 275 + pointsInput.placeholder = 'How many?'; 276 + pointsDiv.appendChild(pointsInput); 295 277 296 - pointsInput.addEventListener('input', () => { 297 - if (Number(pointsInput.value) > points) { 298 - pointsInput.value = points; 299 - } 300 - }); 278 + pointsInput.addEventListener('input', () => { 279 + if (Number(pointsInput.value) > points) { 280 + pointsInput.value = points; 281 + } 282 + }); 301 283 302 - const confirmButton = document.createElement('button'); 303 - confirmButton.textContent = 'Apply discount'; 304 - confirmButton.id = 'loyaltyPointsBtn'; 305 - confirmButton.className = 'btn btn-primary'; 306 - pointsDiv.appendChild(confirmButton); 284 + const confirmButton = document.createElement('button'); 285 + confirmButton.textContent = 'Apply discount'; 286 + confirmButton.id = 'loyaltyPointsBtn'; 287 + confirmButton.className = 'btn btn-primary'; 288 + pointsDiv.appendChild(confirmButton); 307 289 308 - const cancelButton = document.createElement('button'); 309 - cancelButton.textContent = 'Cancel discount'; 310 - cancelButton.id = 'cancelLoyaltyPointsBtn'; 311 - cancelButton.className = 'btn btn-secondary'; 312 - cancelButton.style.display = document.querySelector( 313 - '[data-test="cart-discount"] [data-test="cart-price-value"]' 314 - ) 315 - ? 'block' 316 - : 'none'; 317 - pointsDiv.appendChild(cancelButton); 290 + const cancelButton = document.createElement('button'); 291 + cancelButton.textContent = 'Cancel discount'; 292 + cancelButton.id = 'cancelLoyaltyPointsBtn'; 293 + cancelButton.className = 'btn btn-secondary'; 294 + cancelButton.style.display = document.querySelector( 295 + '[data-test="cart-discount"] [data-test="cart-price-value"]' 296 + ) 297 + ? 'block' 298 + : 'none'; 299 + pointsDiv.appendChild(cancelButton); 318 300 319 - const errorMessage = document.createElement('p'); 320 - errorMessage.id = 'usedPointsError'; 321 - errorMessage.classList.add('warning'); 322 - errorMessage.textContent = 323 - 'There was an error applying the discount. Please try again later.'; 324 - errorMessage.style.display = 'none'; 325 - pointsDiv.appendChild(errorMessage); 301 + const errorMessage = document.createElement('p'); 302 + errorMessage.id = 'usedPointsError'; 303 + errorMessage.classList.add('warning'); 304 + errorMessage.textContent = 305 + 'There was an error applying the discount. Please try again later.'; 306 + errorMessage.style.display = 'none'; 307 + pointsDiv.appendChild(errorMessage); 326 308 327 - // Mount the entire loyalty points div to the parent element 328 - elementToAppend.appendChild(pointsDiv); 309 + // Mount the entire loyalty points div to the parent element 310 + elementToAppend.appendChild(pointsDiv); 329 311 330 - generateNewSummary(points); 312 + generateNewSummary(points); 331 313 332 - loyaltyPointsBtn.addEventListener('click', () => { 333 - if (pointsInput.value === '') { 334 - return; 335 - } 314 + loyaltyPointsBtn.addEventListener('click', () => { 315 + if (pointsInput.value === '') { 316 + return; 317 + } 336 318 337 - loyaltyPointsBtn.setAttribute('disabled', 'true'); 338 - loyaltyPointsBtn.textContent = 'Processing'; 319 + loyaltyPointsBtn.setAttribute('disabled', 'true'); 320 + loyaltyPointsBtn.textContent = 'Processing'; 339 321 340 - fetch( 341 - `https://purrform-apps-027e.onrender.com/applyDiscountToCheckout?checkoutId={{cart_id}}&loyaltyPointsUsed=${pointsInput.value}&max_points=${points}` 342 - ) 343 - .then((response) => { 344 - if (!response.ok) { 345 - // do something here to let the user know the discount failed 346 - throw new Error('Failed to apply discount'); 347 - } 322 + fetch( 323 + `https://purrform-apps-027e.onrender.com/applyDiscountToCheckout?checkoutId={{cart_id}}&loyaltyPointsUsed=${pointsInput.value}&max_points=${points}` 324 + ) 325 + .then((response) => { 326 + if (!response.ok) { 327 + // do something here to let the user know the discount failed 328 + throw new Error('Failed to apply discount'); 329 + } 348 330 349 - loyaltyPointsBtn.removeAttribute('disabled'); 350 - errorMessage.style.display = 'none'; 351 - cancelButton.style.display = 'block'; 352 - window.location.reload(); 353 - }) 354 - .catch((err) => { 355 - // do something here to let the user know the discount failed 356 - loyaltyPointsBtn.removeAttribute('disabled'); 357 - loyaltyPointsBtn.textContent = 'Apply discount'; 358 - pointsInput.value = ''; 359 - errorMessage.style.display = 'block'; 360 - }); 361 - }); 331 + loyaltyPointsBtn.removeAttribute('disabled'); 332 + errorMessage.style.display = 'none'; 333 + cancelButton.style.display = 'block'; 334 + window.location.reload(); 335 + }) 336 + .catch((err) => { 337 + // do something here to let the user know the discount failed 338 + loyaltyPointsBtn.removeAttribute('disabled'); 339 + loyaltyPointsBtn.textContent = 'Apply discount'; 340 + pointsInput.value = ''; 341 + errorMessage.style.display = 'block'; 342 + }); 343 + }); 362 344 363 - cancelButton.addEventListener('click', () => { 364 - cancelButton.setAttribute('disabled', 'true'); 365 - cancelButton.textContent = 'Removing...'; 366 - fetch( 367 - `https://purrform-apps-027e.onrender.com/applyDiscountToCheckout?checkoutId={{cart_id}}&loyaltyPointsUsed=0` 368 - ) 369 - .then((response) => { 370 - if (!response.ok) { 371 - throw new Error('Failed to remove discount'); 372 - } 373 - cancelButton.removeAttribute('disabled'); 374 - errorMessage.style.display = 'none'; 375 - cancelButton.style.display = 'none'; 376 - window.location.reload(); 377 - }) 378 - .catch((err) => { 379 - // do something here to let the user know the discount failed 380 - cancelButton.removeAttribute('disabled'); 381 - cancelButton.textContent = 'Remove Discount'; 382 - pointsInput.value = ''; 383 - errorMessage.style.display = 'block'; 345 + cancelButton.addEventListener('click', () => { 346 + cancelButton.setAttribute('disabled', 'true'); 347 + cancelButton.textContent = 'Removing...'; 348 + fetch( 349 + `https://purrform-apps-027e.onrender.com/applyDiscountToCheckout?checkoutId={{cart_id}}&loyaltyPointsUsed=0` 350 + ) 351 + .then((response) => { 352 + if (!response.ok) { 353 + throw new Error('Failed to remove discount'); 354 + } 355 + cancelButton.removeAttribute('disabled'); 356 + errorMessage.style.display = 'none'; 357 + cancelButton.style.display = 'none'; 358 + window.location.reload(); 359 + }) 360 + .catch((err) => { 361 + // do something here to let the user know the discount failed 362 + cancelButton.removeAttribute('disabled'); 363 + cancelButton.textContent = 'Remove Discount'; 364 + pointsInput.value = ''; 365 + errorMessage.style.display = 'block'; 366 + }); 367 + }); 384 368 }); 385 - }); 386 - }); 387 - } 369 + } 388 370 389 - function generateNewSummary(currentUserPoints) { 390 - const masterContainer = document.createElement('div'); 391 - const masterText = document.createElement('p'); 392 - masterText.classList.add('loyalty-summary'); 393 - masterText.textContent = 'Loyalty Points Summary'; 394 - masterContainer.appendChild(masterText); 371 + function generateNewSummary(currentUserPoints) { 372 + const masterContainer = document.createElement('div'); 373 + const masterText = document.createElement('p'); 374 + masterText.classList.add('loyalty-summary'); 375 + masterText.textContent = 'Loyalty Points Summary'; 376 + masterContainer.appendChild(masterText); 395 377 396 - const discountEl = document.querySelector( 397 - '[data-test="cart-discount"] [data-test="cart-price-value"]' 398 - ); 399 - const subtotalEl = document.querySelector( 400 - '[data-test="cart-subtotal"] [data-test="cart-price-value"]' 401 - ); 402 - const couponDiscountEl = document.querySelector( 403 - '[data-test="cart-coupon"] [data-test="cart-price-value"]' 404 - ); 405 - const pointsInput = document.getElementById('points-input'); 378 + const discountEl = document.querySelector( 379 + '[data-test="cart-discount"] [data-test="cart-price-value"]' 380 + ); 381 + const subtotalEl = document.querySelector( 382 + '[data-test="cart-subtotal"] [data-test="cart-price-value"]' 383 + ); 384 + const couponDiscountEl = document.querySelector( 385 + '[data-test="cart-coupon"] [data-test="cart-price-value"]' 386 + ); 387 + const pointsInput = document.getElementById('points-input'); 406 388 407 - let discountPriceValue = 0; 408 - let discountLoyalPointValue = 0; 409 - let earningPriceValue = 0; 410 - let earningLoyalPointValue = 0; 389 + let discountPriceValue = 0; 390 + let discountLoyalPointValue = 0; 391 + let earningPriceValue = 0; 392 + let earningLoyalPointValue = 0; 411 393 412 - if (discountEl) { 413 - // Discount Div 414 - const discountContainer = document.createElement('div'); 415 - discountContainer.classList.add('cart-summaryItem'); 394 + if (discountEl) { 395 + // Discount Div 396 + const discountContainer = document.createElement('div'); 397 + discountContainer.classList.add('cart-summaryItem'); 416 398 417 - const discountDescription = document.createElement('div'); 418 - const discountValue = document.createElement('div'); 399 + const discountDescription = document.createElement('div'); 400 + const discountValue = document.createElement('div'); 419 401 420 - discountDescription.textContent = 'Points redeemed'; 402 + discountDescription.textContent = 'Points redeemed'; 421 403 422 - discountPriceValue = discountEl.innerHTML.replace(/[^\d.-]/g, ''); 423 - discountPriceValue = Math.abs(Number(discountPriceValue)); 424 - discountLoyalPointValue = Math.floor(discountPriceValue * 100); 404 + discountPriceValue = discountEl.innerHTML.replace(/[^\d.-]/g, ''); 405 + discountPriceValue = Math.abs(Number(discountPriceValue)); 406 + discountLoyalPointValue = Math.floor(discountPriceValue * 100); 425 407 426 - discountValue.textContent = `-${discountLoyalPointValue}`; 408 + discountValue.textContent = `-${discountLoyalPointValue}`; 427 409 428 - discountContainer.appendChild(discountDescription); 429 - discountContainer.appendChild(discountValue); 430 - masterContainer.appendChild(discountContainer); 431 - } 432 - if (subtotalEl) { 433 - // Earning Div 434 - const earningContainer = document.createElement('div'); 435 - earningContainer.classList.add('cart-summaryItem'); 410 + discountContainer.appendChild(discountDescription); 411 + discountContainer.appendChild(discountValue); 412 + masterContainer.appendChild(discountContainer); 413 + } 414 + if (subtotalEl) { 415 + // Earning Div 416 + const earningContainer = document.createElement('div'); 417 + earningContainer.classList.add('cart-summaryItem'); 436 418 437 - const earningDescription = document.createElement('div'); 438 - const earningValue = document.createElement('div'); 419 + const earningDescription = document.createElement('div'); 420 + const earningValue = document.createElement('div'); 439 421 440 - earningDescription.textContent = 'Points earned'; 441 - earningPriceValue = subtotalEl.innerHTML.replace(/[^\d.-]/g, ''); 442 - earningPriceValue = Number(earningPriceValue); // Use parseFloat to handle decimal values 443 - if (discountEl) { 444 - earningPriceValue = earningPriceValue - discountPriceValue; 445 - } 422 + earningDescription.textContent = 'Points earned'; 423 + earningPriceValue = subtotalEl.innerHTML.replace(/[^\d.-]/g, ''); 424 + earningPriceValue = Number(earningPriceValue); // Use parseFloat to handle decimal values 425 + if (discountEl) { 426 + earningPriceValue = earningPriceValue - discountPriceValue; 427 + } 446 428 447 - if (couponDiscountEl) { 448 - earningPriceValue -= Math.floor( 449 - Math.abs( 450 - Number( 451 - couponDiscountEl.innerHTML.replace(/[^\d.-]/g, '') 452 - ) 453 - ) 454 - ); 455 - } 429 + if (couponDiscountEl) { 430 + earningPriceValue -= Math.floor( 431 + Math.abs( 432 + Number( 433 + couponDiscountEl.innerHTML.replace(/[^\d.-]/g, '') 434 + ) 435 + ) 436 + ); 437 + } 456 438 457 - earningLoyalPointValue = Math.floor(earningPriceValue / 2); 439 + earningLoyalPointValue = Math.floor(earningPriceValue / 2); 458 440 459 - if (earningLoyalPointValue < 0) { 460 - earningLoyalPointValue = 0; 461 - earningValue.textContent = `0`; 462 - } else { 463 - earningValue.textContent = `+${earningLoyalPointValue}`; 464 - } 441 + if (earningLoyalPointValue < 0) { 442 + earningLoyalPointValue = 0; 443 + earningValue.textContent = `0`; 444 + } else { 445 + earningValue.textContent = `+${earningLoyalPointValue}`; 446 + } 465 447 466 - earningContainer.appendChild(earningDescription); 467 - earningContainer.appendChild(earningValue); 468 - masterContainer.appendChild(earningContainer); 469 - } 448 + earningContainer.appendChild(earningDescription); 449 + earningContainer.appendChild(earningValue); 450 + masterContainer.appendChild(earningContainer); 451 + } 470 452 471 - const finalContainer = document.createElement('div'); 472 - const finalResult = document.createElement('div'); 473 - const finalResultText = document.createElement('p'); 453 + const finalContainer = document.createElement('div'); 454 + const finalResult = document.createElement('div'); 455 + const finalResultText = document.createElement('p'); 474 456 475 - const finalType = document.createElement('div'); 476 - const finalTypeText = document.createElement('p'); 477 - finalTypeText.textContent = 'Estimated total after purchase:'; 457 + const finalType = document.createElement('div'); 458 + const finalTypeText = document.createElement('p'); 459 + finalTypeText.textContent = 'Estimated total after purchase:'; 478 460 479 - if (discountEl) { 480 - finalResultText.textContent = `${ 481 - currentUserPoints + 482 - earningLoyalPointValue - 483 - discountLoyalPointValue 484 - }`; 485 - } else { 486 - finalResultText.textContent = `${ 487 - currentUserPoints + earningLoyalPointValue 488 - }`; 489 - } 461 + if (discountEl) { 462 + finalResultText.textContent = `${currentUserPoints + 463 + earningLoyalPointValue - 464 + discountLoyalPointValue 465 + }`; 466 + } else { 467 + finalResultText.textContent = `${currentUserPoints + earningLoyalPointValue 468 + }`; 469 + } 490 470 491 - finalType.appendChild(finalTypeText); 492 - finalResult.appendChild(finalResultText); 493 - finalContainer.appendChild(finalType); 494 - finalContainer.appendChild(finalResult); 495 - finalContainer.classList.add('cart-resultItem'); 471 + finalType.appendChild(finalTypeText); 472 + finalResult.appendChild(finalResultText); 473 + finalContainer.appendChild(finalType); 474 + finalContainer.appendChild(finalResult); 475 + finalContainer.classList.add('cart-resultItem'); 496 476 497 - masterContainer.appendChild(finalContainer); 498 - // pointsDiv.insertAdjacentHTML('afterend', finalContainer.innerHTML); 499 - pointsInput.insertAdjacentHTML('afterend', masterContainer.outerHTML); 477 + masterContainer.appendChild(finalContainer); 478 + // pointsDiv.insertAdjacentHTML('afterend', finalContainer.innerHTML); 479 + pointsInput.insertAdjacentHTML('afterend', masterContainer.outerHTML); 500 480 501 - // fix for mobile not showing button 502 - const parentSelectorMobile = 503 - '.cart-modal-body.optimizedCheckout-orderSummary'; 504 - if (document.querySelector(parentSelectorMobile)) { 505 - const confirmButton = document.querySelector('#loyaltyPointsBtn'); 506 - confirmButton.focus(); 507 - } 508 - } 481 + // fix for mobile not showing button 482 + const parentSelectorMobile = 483 + '.cart-modal-body.optimizedCheckout-orderSummary'; 484 + if (document.querySelector(parentSelectorMobile)) { 485 + const confirmButton = document.querySelector('#loyaltyPointsBtn'); 486 + confirmButton.focus(); 487 + } 488 + } 509 489 510 - function fetchLoyalty() { 511 - return fetch('/graphql', { 512 - method: 'POST', 513 - credentials: 'same-origin', 514 - headers: { 515 - 'Content-Type': 'application/json', 516 - Authorization: 'Bearer {{ settings.storefront_api.token }}', 517 - }, 518 - body: JSON.stringify({ 519 - query: ` 490 + function fetchLoyalty() { 491 + return fetch('/graphql', { 492 + method: 'POST', 493 + credentials: 'same-origin', 494 + headers: { 495 + 'Content-Type': 'application/json', 496 + Authorization: 'Bearer {{ settings.storefront_api.token }}', 497 + }, 498 + body: JSON.stringify({ 499 + query: ` 520 500 query loyaltyQuery{ 521 501 customer { 522 502 attributes { ··· 528 508 } 529 509 } 530 510 `, 531 - }), 532 - }) 533 - .then((res) => res.json()) 534 - .then((json) => { 535 - const attribute = json.data.customer.attributes.attribute; 536 - const points = attribute ? attribute.value : '0'; // Default to '0' if attribute is not found 537 - return Number(points); 538 - }) 539 - .catch((error) => { 540 - console.error('Error fetching loyalty points:', error); 541 - return 0; // Return '0' in case of error 542 - }); 543 - } 544 - </script> 545 - {{else if customer_group_name '===' 'Breeder'}} 546 - <script> 547 - // Handles the loyalty points 548 - const parentSelectorDesktop = '.cart.optimizedCheckout-orderSummary'; 549 - const parentSelectorMobile = 550 - '.cart-modal-body.optimizedCheckout-orderSummary'; 511 + }), 512 + }) 513 + .then((res) => res.json()) 514 + .then((json) => { 515 + const attribute = json.data.customer.attributes.attribute; 516 + const points = attribute ? attribute.value : '0'; // Default to '0' if attribute is not found 517 + return Number(points); 518 + }) 519 + .catch((error) => { 520 + console.error('Error fetching loyalty points:', error); 521 + return 0; // Return '0' in case of error 522 + }); 523 + } 524 + </script> 525 + {{else if customer_group_name '===' 'Breeder'}} 526 + <script> 527 + // Handles the loyalty points 528 + const parentSelectorDesktop = '.cart.optimizedCheckout-orderSummary'; 529 + const parentSelectorMobile = 530 + '.cart-modal-body.optimizedCheckout-orderSummary'; 551 531 552 - ready(parentSelectorDesktop, (parentElement) => { 553 - loyaltyInitialize(parentElement); 554 - }); 532 + ready(parentSelectorDesktop, (parentElement) => { 533 + loyaltyInitialize(parentElement); 534 + }); 555 535 556 - ready(parentSelectorMobile, (parentElement) => { 557 - loyaltyInitialize(parentElement); 558 - }); 536 + ready(parentSelectorMobile, (parentElement) => { 537 + loyaltyInitialize(parentElement); 538 + }); 559 539 560 - function loyaltyInitialize(elementToAppend) { 561 - // Fetch loyalty points 562 - fetchLoyalty().then((points) => { 563 - // Create a new div element for displaying loyalty points 564 - const pointsDiv = document.createElement('section'); 565 - const pointsDesc = document.createElement('p'); 566 - pointsDesc.id = 'pointsDesc'; 567 - if (points == null) { 568 - pointsDesc.innerHTML = "Could not find loyalty points for this account, make sure you are logged in or refresh the page."; 569 - } else { 570 - pointsDesc.innerHTML = `Loyalty points balance ${points}`; 571 - } 572 - pointsDiv.appendChild(pointsDesc); 573 - pointsDiv.className = 'cart-section optimizedCheckout-orderSummary-cartSection loyalty-points'; 540 + function loyaltyInitialize(elementToAppend) { 541 + // Fetch loyalty points 542 + fetchLoyalty().then((points) => { 543 + // Create a new div element for displaying loyalty points 544 + const pointsDiv = document.createElement('section'); 545 + const pointsDesc = document.createElement('p'); 546 + pointsDesc.id = 'pointsDesc'; 547 + if (points == null) { 548 + pointsDesc.innerHTML = "Could not find loyalty points for this account, make sure you are logged in or refresh the page."; 549 + } else { 550 + pointsDesc.innerHTML = `Loyalty points balance ${points}`; 551 + } 552 + pointsDiv.appendChild(pointsDesc); 553 + pointsDiv.className = 'cart-section optimizedCheckout-orderSummary-cartSection loyalty-points'; 574 554 575 - // Create a label and input for entering points to use 576 - const label = document.createElement('label'); 577 - label.setAttribute('for', 'points-input'); 578 - label.classList.add('loyaltyLabel'); 579 - pointsDiv.appendChild(label); 555 + // Create a label and input for entering points to use 556 + const label = document.createElement('label'); 557 + label.setAttribute('for', 'points-input'); 558 + label.classList.add('loyaltyLabel'); 559 + pointsDiv.appendChild(label); 580 560 581 - const pointsInput = document.createElement('input'); 582 - pointsInput.type = 'number'; 583 - pointsInput.id = 'points-input'; 584 - pointsInput.min = 0; 585 - pointsInput.max = points; 586 - pointsInput.placeholder = 'How many?'; 587 - pointsDiv.appendChild(pointsInput); 561 + const pointsInput = document.createElement('input'); 562 + pointsInput.type = 'number'; 563 + pointsInput.id = 'points-input'; 564 + pointsInput.min = 0; 565 + pointsInput.max = points; 566 + pointsInput.placeholder = 'How many?'; 567 + pointsDiv.appendChild(pointsInput); 588 568 589 - pointsInput.addEventListener('input', () => { 590 - if (Number(pointsInput.value) > points) { 591 - pointsInput.value = points; 592 - } 593 - }); 569 + pointsInput.addEventListener('input', () => { 570 + if (Number(pointsInput.value) > points) { 571 + pointsInput.value = points; 572 + } 573 + }); 594 574 595 - const confirmButton = document.createElement('button'); 596 - confirmButton.textContent = 'Apply discount'; 597 - confirmButton.id = 'loyaltyPointsBtn'; 598 - confirmButton.className = 'btn btn-primary'; 599 - pointsDiv.appendChild(confirmButton); 575 + const confirmButton = document.createElement('button'); 576 + confirmButton.textContent = 'Apply discount'; 577 + confirmButton.id = 'loyaltyPointsBtn'; 578 + confirmButton.className = 'btn btn-primary'; 579 + pointsDiv.appendChild(confirmButton); 600 580 601 - const cancelButton = document.createElement('button'); 602 - cancelButton.textContent = 'Cancel discount'; 603 - cancelButton.id = 'cancelLoyaltyPointsBtn'; 604 - cancelButton.className = 'btn btn-secondary'; 605 - cancelButton.style.display = document.querySelector( 606 - '[data-test="cart-discount"] [data-test="cart-price-value"]' 607 - ) 608 - ? 'block' 609 - : 'none'; 610 - pointsDiv.appendChild(cancelButton); 581 + const cancelButton = document.createElement('button'); 582 + cancelButton.textContent = 'Cancel discount'; 583 + cancelButton.id = 'cancelLoyaltyPointsBtn'; 584 + cancelButton.className = 'btn btn-secondary'; 585 + cancelButton.style.display = document.querySelector( 586 + '[data-test="cart-discount"] [data-test="cart-price-value"]' 587 + ) 588 + ? 'block' 589 + : 'none'; 590 + pointsDiv.appendChild(cancelButton); 611 591 612 - const errorMessage = document.createElement('p'); 613 - errorMessage.id = 'usedPointsError'; 614 - errorMessage.classList.add('warning'); 615 - errorMessage.textContent = 616 - 'There was an error applying the discount. Please try again later.'; 617 - errorMessage.style.display = 'none'; 618 - pointsDiv.appendChild(errorMessage); 592 + const errorMessage = document.createElement('p'); 593 + errorMessage.id = 'usedPointsError'; 594 + errorMessage.classList.add('warning'); 595 + errorMessage.textContent = 596 + 'There was an error applying the discount. Please try again later.'; 597 + errorMessage.style.display = 'none'; 598 + pointsDiv.appendChild(errorMessage); 619 599 620 - // Mount the entire loyalty points div to the parent element 621 - elementToAppend.appendChild(pointsDiv); 600 + // Mount the entire loyalty points div to the parent element 601 + elementToAppend.appendChild(pointsDiv); 622 602 623 - generateNewSummary(points); 603 + generateNewSummary(points); 624 604 625 - loyaltyPointsBtn.addEventListener('click', () => { 626 - if (pointsInput.value === '') { 627 - return; 628 - } 605 + loyaltyPointsBtn.addEventListener('click', () => { 606 + if (pointsInput.value === '') { 607 + return; 608 + } 629 609 630 - loyaltyPointsBtn.setAttribute('disabled', 'true'); 631 - loyaltyPointsBtn.textContent = 'Processing'; 610 + loyaltyPointsBtn.setAttribute('disabled', 'true'); 611 + loyaltyPointsBtn.textContent = 'Processing'; 632 612 633 - fetch( 634 - `https://purrform-apps-027e.onrender.com/applyDiscountToCheckout?checkoutId={{cart_id}}&loyaltyPointsUsed=${pointsInput.value}&max_points=${points}` 635 - ) 636 - .then((response) => { 637 - if (!response.ok) { 638 - // do something here to let the user know the discount failed 639 - throw new Error('Failed to apply discount'); 640 - } 613 + fetch( 614 + `https://purrform-apps-027e.onrender.com/applyDiscountToCheckout?checkoutId={{cart_id}}&loyaltyPointsUsed=${pointsInput.value}&max_points=${points}` 615 + ) 616 + .then((response) => { 617 + if (!response.ok) { 618 + // do something here to let the user know the discount failed 619 + throw new Error('Failed to apply discount'); 620 + } 641 621 642 - loyaltyPointsBtn.removeAttribute('disabled'); 643 - errorMessage.style.display = 'none'; 644 - cancelButton.style.display = 'block'; 645 - window.location.reload(); 646 - }) 647 - .catch((err) => { 648 - // do something here to let the user know the discount failed 649 - loyaltyPointsBtn.removeAttribute('disabled'); 650 - loyaltyPointsBtn.textContent = 'Apply discount'; 651 - pointsInput.value = ''; 652 - errorMessage.style.display = 'block'; 653 - }); 654 - }); 622 + loyaltyPointsBtn.removeAttribute('disabled'); 623 + errorMessage.style.display = 'none'; 624 + cancelButton.style.display = 'block'; 625 + window.location.reload(); 626 + }) 627 + .catch((err) => { 628 + // do something here to let the user know the discount failed 629 + loyaltyPointsBtn.removeAttribute('disabled'); 630 + loyaltyPointsBtn.textContent = 'Apply discount'; 631 + pointsInput.value = ''; 632 + errorMessage.style.display = 'block'; 633 + }); 634 + }); 655 635 656 - cancelButton.addEventListener('click', () => { 657 - cancelButton.setAttribute('disabled', 'true'); 658 - cancelButton.textContent = 'Removing...'; 659 - fetch( 660 - `https://purrform-apps-027e.onrender.com/applyDiscountToCheckout?checkoutId={{cart_id}}&loyaltyPointsUsed=0` 661 - ) 662 - .then((response) => { 663 - if (!response.ok) { 664 - throw new Error('Failed to remove discount'); 665 - } 666 - cancelButton.removeAttribute('disabled'); 667 - errorMessage.style.display = 'none'; 668 - cancelButton.style.display = 'none'; 669 - window.location.reload(); 670 - }) 671 - .catch((err) => { 672 - // do something here to let the user know the discount failed 673 - cancelButton.removeAttribute('disabled'); 674 - cancelButton.textContent = 'Remove Discount'; 675 - pointsInput.value = ''; 676 - errorMessage.style.display = 'block'; 636 + cancelButton.addEventListener('click', () => { 637 + cancelButton.setAttribute('disabled', 'true'); 638 + cancelButton.textContent = 'Removing...'; 639 + fetch( 640 + `https://purrform-apps-027e.onrender.com/applyDiscountToCheckout?checkoutId={{cart_id}}&loyaltyPointsUsed=0` 641 + ) 642 + .then((response) => { 643 + if (!response.ok) { 644 + throw new Error('Failed to remove discount'); 645 + } 646 + cancelButton.removeAttribute('disabled'); 647 + errorMessage.style.display = 'none'; 648 + cancelButton.style.display = 'none'; 649 + window.location.reload(); 650 + }) 651 + .catch((err) => { 652 + // do something here to let the user know the discount failed 653 + cancelButton.removeAttribute('disabled'); 654 + cancelButton.textContent = 'Remove Discount'; 655 + pointsInput.value = ''; 656 + errorMessage.style.display = 'block'; 657 + }); 658 + }); 677 659 }); 678 - }); 679 - }); 680 - } 660 + } 681 661 682 - function generateNewSummary(currentUserPoints) { 683 - const masterContainer = document.createElement('div'); 684 - const masterText = document.createElement('p'); 685 - masterText.classList.add('loyalty-summary'); 686 - masterText.textContent = 'Loyalty Points Summary'; 687 - masterContainer.appendChild(masterText); 662 + function generateNewSummary(currentUserPoints) { 663 + const masterContainer = document.createElement('div'); 664 + const masterText = document.createElement('p'); 665 + masterText.classList.add('loyalty-summary'); 666 + masterText.textContent = 'Loyalty Points Summary'; 667 + masterContainer.appendChild(masterText); 688 668 689 - const discountEl = document.querySelector( 690 - '[data-test="cart-discount"] [data-test="cart-price-value"]' 691 - ); 692 - const subtotalEl = document.querySelector( 693 - '[data-test="cart-subtotal"] [data-test="cart-price-value"]' 694 - ); 695 - const couponDiscountEl = document.querySelector( 696 - '[data-test="cart-coupon"] [data-test="cart-price-value"]' 697 - ); 698 - const pointsInput = document.getElementById('points-input'); 669 + const discountEl = document.querySelector( 670 + '[data-test="cart-discount"] [data-test="cart-price-value"]' 671 + ); 672 + const subtotalEl = document.querySelector( 673 + '[data-test="cart-subtotal"] [data-test="cart-price-value"]' 674 + ); 675 + const couponDiscountEl = document.querySelector( 676 + '[data-test="cart-coupon"] [data-test="cart-price-value"]' 677 + ); 678 + const pointsInput = document.getElementById('points-input'); 699 679 700 - let discountPriceValue = 0; 701 - let discountLoyalPointValue = 0; 702 - let earningPriceValue = 0; 703 - let earningLoyalPointValue = 0; 680 + let discountPriceValue = 0; 681 + let discountLoyalPointValue = 0; 682 + let earningPriceValue = 0; 683 + let earningLoyalPointValue = 0; 704 684 705 - if (discountEl) { 706 - // Discount Div 707 - const discountContainer = document.createElement('div'); 708 - discountContainer.classList.add('cart-summaryItem'); 685 + if (discountEl) { 686 + // Discount Div 687 + const discountContainer = document.createElement('div'); 688 + discountContainer.classList.add('cart-summaryItem'); 709 689 710 - const discountDescription = document.createElement('div'); 711 - const discountValue = document.createElement('div'); 690 + const discountDescription = document.createElement('div'); 691 + const discountValue = document.createElement('div'); 712 692 713 - discountDescription.textContent = 'Points redeemed'; 693 + discountDescription.textContent = 'Points redeemed'; 714 694 715 - discountPriceValue = discountEl.innerHTML.replace(/[^\d.-]/g, ''); 716 - discountPriceValue = Math.abs(Number(discountPriceValue)); 717 - discountLoyalPointValue = Math.floor(discountPriceValue * 100); 695 + discountPriceValue = discountEl.innerHTML.replace(/[^\d.-]/g, ''); 696 + discountPriceValue = Math.abs(Number(discountPriceValue)); 697 + discountLoyalPointValue = Math.floor(discountPriceValue * 100); 718 698 719 - discountValue.textContent = `-${discountLoyalPointValue}`; 699 + discountValue.textContent = `-${discountLoyalPointValue}`; 720 700 721 - discountContainer.appendChild(discountDescription); 722 - discountContainer.appendChild(discountValue); 723 - masterContainer.appendChild(discountContainer); 724 - } 725 - if (subtotalEl) { 726 - // Earning Div 727 - const earningContainer = document.createElement('div'); 728 - earningContainer.classList.add('cart-summaryItem'); 701 + discountContainer.appendChild(discountDescription); 702 + discountContainer.appendChild(discountValue); 703 + masterContainer.appendChild(discountContainer); 704 + } 705 + if (subtotalEl) { 706 + // Earning Div 707 + const earningContainer = document.createElement('div'); 708 + earningContainer.classList.add('cart-summaryItem'); 729 709 730 - const earningDescription = document.createElement('div'); 731 - const earningValue = document.createElement('div'); 710 + const earningDescription = document.createElement('div'); 711 + const earningValue = document.createElement('div'); 732 712 733 - earningDescription.textContent = 'Points earned'; 734 - earningPriceValue = subtotalEl.innerHTML.replace(/[^\d.-]/g, ''); 735 - earningPriceValue = Number(earningPriceValue); // Use parseFloat to handle decimal values 736 - if (discountEl) { 737 - earningPriceValue = earningPriceValue - discountPriceValue; 738 - } 713 + earningDescription.textContent = 'Points earned'; 714 + earningPriceValue = subtotalEl.innerHTML.replace(/[^\d.-]/g, ''); 715 + earningPriceValue = Number(earningPriceValue); // Use parseFloat to handle decimal values 716 + if (discountEl) { 717 + earningPriceValue = earningPriceValue - discountPriceValue; 718 + } 739 719 740 - if (couponDiscountEl) { 741 - earningPriceValue -= Math.floor( 742 - Math.abs( 743 - Number( 744 - couponDiscountEl.innerHTML.replace(/[^\d.-]/g, '') 745 - ) 746 - ) 747 - ); 748 - } 720 + if (couponDiscountEl) { 721 + earningPriceValue -= Math.floor( 722 + Math.abs( 723 + Number( 724 + couponDiscountEl.innerHTML.replace(/[^\d.-]/g, '') 725 + ) 726 + ) 727 + ); 728 + } 749 729 750 - earningLoyalPointValue = Math.floor(earningPriceValue / 2); 730 + earningLoyalPointValue = Math.floor(earningPriceValue / 2); 751 731 752 - if (earningLoyalPointValue < 0) { 753 - earningLoyalPointValue = 0; 754 - earningValue.textContent = `0`; 755 - } else { 756 - earningValue.textContent = `+${earningLoyalPointValue}`; 757 - } 732 + if (earningLoyalPointValue < 0) { 733 + earningLoyalPointValue = 0; 734 + earningValue.textContent = `0`; 735 + } else { 736 + earningValue.textContent = `+${earningLoyalPointValue}`; 737 + } 758 738 759 - earningContainer.appendChild(earningDescription); 760 - earningContainer.appendChild(earningValue); 761 - masterContainer.appendChild(earningContainer); 762 - } 739 + earningContainer.appendChild(earningDescription); 740 + earningContainer.appendChild(earningValue); 741 + masterContainer.appendChild(earningContainer); 742 + } 763 743 764 - const finalContainer = document.createElement('div'); 765 - const finalResult = document.createElement('div'); 766 - const finalResultText = document.createElement('p'); 744 + const finalContainer = document.createElement('div'); 745 + const finalResult = document.createElement('div'); 746 + const finalResultText = document.createElement('p'); 767 747 768 - const finalType = document.createElement('div'); 769 - const finalTypeText = document.createElement('p'); 770 - finalTypeText.textContent = 'Estimated total after purchase:'; 748 + const finalType = document.createElement('div'); 749 + const finalTypeText = document.createElement('p'); 750 + finalTypeText.textContent = 'Estimated total after purchase:'; 771 751 772 - if (discountEl) { 773 - finalResultText.textContent = `${ 774 - currentUserPoints + 775 - earningLoyalPointValue - 776 - discountLoyalPointValue 777 - }`; 778 - } else { 779 - finalResultText.textContent = `${ 780 - currentUserPoints + earningLoyalPointValue 781 - }`; 782 - } 752 + if (discountEl) { 753 + finalResultText.textContent = `${currentUserPoints + 754 + earningLoyalPointValue - 755 + discountLoyalPointValue 756 + }`; 757 + } else { 758 + finalResultText.textContent = `${currentUserPoints + earningLoyalPointValue 759 + }`; 760 + } 783 761 784 - finalType.appendChild(finalTypeText); 785 - finalResult.appendChild(finalResultText); 786 - finalContainer.appendChild(finalType); 787 - finalContainer.appendChild(finalResult); 788 - finalContainer.classList.add('cart-resultItem'); 762 + finalType.appendChild(finalTypeText); 763 + finalResult.appendChild(finalResultText); 764 + finalContainer.appendChild(finalType); 765 + finalContainer.appendChild(finalResult); 766 + finalContainer.classList.add('cart-resultItem'); 789 767 790 - masterContainer.appendChild(finalContainer); 791 - // pointsDiv.insertAdjacentHTML('afterend', finalContainer.innerHTML); 792 - pointsInput.insertAdjacentHTML('afterend', masterContainer.outerHTML); 768 + masterContainer.appendChild(finalContainer); 769 + // pointsDiv.insertAdjacentHTML('afterend', finalContainer.innerHTML); 770 + pointsInput.insertAdjacentHTML('afterend', masterContainer.outerHTML); 793 771 794 - // fix for mobile not showing button 795 - const parentSelectorMobile = 796 - '.cart-modal-body.optimizedCheckout-orderSummary'; 797 - if (document.querySelector(parentSelectorMobile)) { 798 - const confirmButton = document.querySelector('#loyaltyPointsBtn'); 799 - confirmButton.focus(); 800 - } 801 - } 772 + // fix for mobile not showing button 773 + const parentSelectorMobile = 774 + '.cart-modal-body.optimizedCheckout-orderSummary'; 775 + if (document.querySelector(parentSelectorMobile)) { 776 + const confirmButton = document.querySelector('#loyaltyPointsBtn'); 777 + confirmButton.focus(); 778 + } 779 + } 802 780 803 - function fetchLoyalty() { 804 - return fetch('/graphql', { 805 - method: 'POST', 806 - credentials: 'same-origin', 807 - headers: { 808 - 'Content-Type': 'application/json', 809 - Authorization: 'Bearer {{ settings.storefront_api.token }}', 810 - }, 811 - body: JSON.stringify({ 812 - query: ` 781 + function fetchLoyalty() { 782 + return fetch('/graphql', { 783 + method: 'POST', 784 + credentials: 'same-origin', 785 + headers: { 786 + 'Content-Type': 'application/json', 787 + Authorization: 'Bearer {{ settings.storefront_api.token }}', 788 + }, 789 + body: JSON.stringify({ 790 + query: ` 813 791 query loyaltyQuery{ 814 792 customer { 815 793 attributes { ··· 821 799 } 822 800 } 823 801 `, 824 - }), 825 - }) 826 - .then((res) => res.json()) 827 - .then((json) => { 828 - const attribute = json.data.customer.attributes.attribute; 829 - const points = attribute ? attribute.value : '0'; // Default to '0' if attribute is not found 830 - return Number(points); 831 - }) 832 - .catch((error) => { 833 - console.error('Error fetching loyalty points:', error); 834 - return 0; // Return '0' in case of error 835 - }); 836 - } 837 - </script> 838 - {{/if}} 839 - {{/if}} 802 + }), 803 + }) 804 + .then((res) => res.json()) 805 + .then((json) => { 806 + const attribute = json.data.customer.attributes.attribute; 807 + const points = attribute ? attribute.value : '0'; // Default to '0' if attribute is not found 808 + return Number(points); 809 + }) 810 + .catch((error) => { 811 + console.error('Error fetching loyalty points:', error); 812 + return 0; // Return '0' in case of error 813 + }); 814 + } 815 + </script> 816 + {{/if}} 817 + {{/if}} 840 818 841 - <script> 842 - // ------------------------------------------------------// 843 - // change the text on the mobile modal 844 - const mobileModalSelector = '.cartDrawer.optimizedCheckout-orderSummary'; 845 - ready(mobileModalSelector, (mobileModalElement) => { 846 - mobileModalElement.querySelector('.cartDrawer-body a').textContent = 847 - 'Show Details & Rewards'; 848 - }); 819 + <script> 820 + // ------------------------------------------------------// 821 + // change the text on the mobile modal 822 + const mobileModalSelector = '.cartDrawer.optimizedCheckout-orderSummary'; 823 + ready(mobileModalSelector, (mobileModalElement) => { 824 + mobileModalElement.querySelector('.cartDrawer-body a').textContent = 825 + 'Show Details & Rewards'; 826 + }); 849 827 850 - // ------------------------------------------------------// 851 - // This handles 'datepicker' in 'shipping' 852 - const shippingSelector = '#checkout-shipping-options'; 853 - ready(shippingSelector, (shippingOptionsElement) => { 854 - createCalendar(shippingOptionsElement); 855 - }); 828 + // ------------------------------------------------------// 829 + // This handles 'datepicker' in 'shipping' 830 + const shippingSelector = '#checkout-shipping-options'; 831 + ready(shippingSelector, (shippingOptionsElement) => { 832 + createCalendar(shippingOptionsElement); 833 + }); 856 834 857 - // Attach the datepicker to the shipping options 858 - function createCalendar(parent) { 859 - const existingInstructions = 860 - document.getElementById('datepicker-hoster'); 861 - if (existingInstructions) { 862 - return; 863 - } 835 + // Attach the datepicker to the shipping options 836 + function createCalendar(parent) { 837 + const existingInstructions = 838 + document.getElementById('datepicker-hoster'); 839 + if (existingInstructions) { 840 + return; 841 + } 864 842 865 - // Define the HTML code for the elements 866 - const datePickerHTML = ` 843 + // Define the HTML code for the elements 844 + const datePickerHTML = ` 867 845 <div id="datepicker-hoster" class="datepicker"> 868 846 <div class="cart-total-label"> 869 847 <strong style="color: #687d6a;">Delivery Date *</strong> ··· 876 854 </div> 877 855 `; 878 856 879 - parent.insertAdjacentHTML('beforeend', datePickerHTML); 880 - getCalendarData(); 881 - } 857 + parent.insertAdjacentHTML('beforeend', datePickerHTML); 858 + getCalendarData(); 859 + } 882 860 883 - // Get data for the calendar 884 - function getCalendarData() { 885 - // Create calendar and attach date picker logic here 886 - let dailyDeliveryLimit = 250; 887 - const dailySlotValues = {}; 888 - const disabledDates = []; 861 + // Get data for the calendar 862 + function getCalendarData() { 863 + // Create calendar and attach date picker logic here 864 + let dailyDeliveryLimit = 250; 865 + const dailySlotValues = {}; 866 + const disabledDates = []; 889 867 890 - // get delivery dates from middleware 891 - fetch('https://purrform-apps-027e.onrender.com/deliveryDates') 892 - .then((response) => { 893 - if (!response.ok) { 894 - throw new Error('Network response was not ok'); 895 - } 896 - return response.json(); 897 - }) 898 - .then((data) => { 899 - disabledDates.push(...data.unavailableDates); 900 - for (const [date, slots] of Object.entries(data.dateSlots)) { 901 - dailySlotValues[date] = slots; 902 - } 903 - if (data.perDay) { 904 - dailyDeliveryLimit = data.perDay; 905 - } 906 - attachDatePicker( 907 - dailyDeliveryLimit, 908 - dailySlotValues, 909 - disabledDates 868 + // get delivery dates from middleware 869 + fetch('https://purrform-apps-027e.onrender.com/deliveryDates') 870 + .then((response) => { 871 + if (!response.ok) { 872 + throw new Error('Network response was not ok'); 873 + } 874 + return response.json(); 875 + }) 876 + .then((data) => { 877 + disabledDates.push(...data.unavailableDates); 878 + for (const [date, slots] of Object.entries(data.dateSlots)) { 879 + dailySlotValues[date] = slots; 880 + } 881 + if (data.perDay) { 882 + dailyDeliveryLimit = data.perDay; 883 + } 884 + attachDatePicker( 885 + dailyDeliveryLimit, 886 + dailySlotValues, 887 + disabledDates 888 + ); 889 + }) 890 + .catch((error) => { 891 + console.log('Error calling delivery dates middleware endpoint:', error); 892 + // Handle error if necessary 893 + }); 894 + } 895 + 896 + // Attach the calendar to the datepicker and enable/disable dates 897 + function attachDatePicker( 898 + dailyDeliveryLimit, 899 + dailySlotValues, 900 + disabledDates 901 + ) { 902 + function disableDates(day) { 903 + // day gets implicitly passed by jQuery Calendar 904 + const selectedShippingMethod = document.querySelector( 905 + '.form-checklist-item--selected' 910 906 ); 911 - }) 912 - .catch((error) => { 913 - console.log('Error calling delivery dates middleware endpoint:', error); 914 - // Handle error if necessary 915 - }); 916 - } 917 907 918 - // Attach the calendar to the datepicker and enable/disable dates 919 - function attachDatePicker( 920 - dailyDeliveryLimit, 921 - dailySlotValues, 922 - disabledDates 923 - ) { 924 - function disableDates(day) { 925 - // day gets implicitly passed by jQuery Calendar 926 - const selectedShippingMethod = document.querySelector( 927 - '.form-checklist-item--selected' 928 - ); 908 + if (!selectedShippingMethod) { 909 + return enableWeekdays(day); 910 + } 911 + 912 + const isSaturdayDelivery = selectedShippingMethod 913 + .querySelector('.shippingOption-desc') 914 + .textContent.toLowerCase() 915 + .includes('saturday'); 929 916 930 - if (!selectedShippingMethod) { 931 - return enableWeekdays(day); 917 + return isSaturdayDelivery 918 + ? enableSaturday(day) 919 + : enableWeekdays(day); 932 920 } 933 921 934 - const isSaturdayDelivery = selectedShippingMethod 935 - .querySelector('.shippingOption-desc') 936 - .textContent.toLowerCase() 937 - .includes('saturday'); 922 + // Disable everything except Saturdays 923 + function enableSaturday(day) { 924 + const dayBeingCheckedFormatted = $.datepicker.formatDate( 925 + 'yy-mm-dd', 926 + day 927 + ); 938 928 939 - return isSaturdayDelivery 940 - ? enableSaturday(day) 941 - : enableWeekdays(day); 942 - } 929 + const dayOfTheWeek = day.getDay(); 930 + const saturdayDay = 6; 943 931 944 - // Disable everything except Saturdays 945 - function enableSaturday(day) { 946 - const dayBeingCheckedFormatted = $.datepicker.formatDate( 947 - 'yy-mm-dd', 948 - day 949 - ); 932 + if (dayOfTheWeek !== saturdayDay) { 933 + return [false, '', '']; // disabled boolean, css class, tooltip 934 + } 950 935 951 - const dayOfTheWeek = day.getDay(); 952 - const saturdayDay = 6; 936 + let slotsForThisDay = 937 + dailySlotValues[dayBeingCheckedFormatted] ?? dailyDeliveryLimit; 938 + if (slotsForThisDay > dailyDeliveryLimit) { 939 + // this should never happen, but just in case 940 + slotsForThisDay = dailyDeliveryLimit; 941 + } 953 942 954 - if (dayOfTheWeek !== saturdayDay) { 955 - return [false, '', '']; // disabled boolean, css class, tooltip 956 - } 943 + // Enable check 944 + const isSaturdayEnabled = 945 + slotsForThisDay > 0 && 946 + !disabledDates.includes(dayBeingCheckedFormatted); 957 947 958 - let slotsForThisDay = 959 - dailySlotValues[dayBeingCheckedFormatted] ?? dailyDeliveryLimit; 960 - if (slotsForThisDay > dailyDeliveryLimit) { 961 - // this should never happen, but just in case 962 - slotsForThisDay = dailyDeliveryLimit; 948 + return [ 949 + isSaturdayEnabled, 950 + '', 951 + `Slots available: ${slotsForThisDay}`, 952 + ]; // enabled boolean, css class, tooltip 963 953 } 964 954 965 - // Enable check 966 - const isSaturdayEnabled = 967 - slotsForThisDay > 0 && 968 - !disabledDates.includes(dayBeingCheckedFormatted); 955 + // Enable weekdays 956 + function enableWeekdays(day) { 957 + const dayBeingCheckedFormatted = $.datepicker.formatDate( 958 + 'yy-mm-dd', 959 + day 960 + ); 969 961 970 - return [ 971 - isSaturdayEnabled, 972 - '', 973 - `Slots available: ${slotsForThisDay}`, 974 - ]; // enabled boolean, css class, tooltip 975 - } 962 + const dayOfTheWeek = day.getDay(); 963 + // Disable if 6 (Saturday) 0 (Sunday) or 1 (Monday) 964 + if ( 965 + dayOfTheWeek === 6 || 966 + dayOfTheWeek === 0 || 967 + dayOfTheWeek === 1 968 + ) { 969 + return [false, '', '']; // disabled boolean, css class, tooltip 970 + } 976 971 977 - // Enable weekdays 978 - function enableWeekdays(day) { 979 - const dayBeingCheckedFormatted = $.datepicker.formatDate( 980 - 'yy-mm-dd', 981 - day 982 - ); 972 + let slotsForThisDay = 973 + dailySlotValues[dayBeingCheckedFormatted] ?? dailyDeliveryLimit; 974 + if (slotsForThisDay > dailyDeliveryLimit) { 975 + // this should never happen, but just in case 976 + slotsForThisDay = dailyDeliveryLimit; 977 + } 983 978 984 - const dayOfTheWeek = day.getDay(); 985 - // Disable if 6 (Saturday) 0 (Sunday) or 1 (Monday) 986 - if ( 987 - dayOfTheWeek === 6 || 988 - dayOfTheWeek === 0 || 989 - dayOfTheWeek === 1 990 - ) { 991 - return [false, '', '']; // disabled boolean, css class, tooltip 992 - } 979 + const isEnabledDay = 980 + slotsForThisDay > 0 && 981 + !disabledDates.includes(dayBeingCheckedFormatted); 993 982 994 - let slotsForThisDay = 995 - dailySlotValues[dayBeingCheckedFormatted] ?? dailyDeliveryLimit; 996 - if (slotsForThisDay > dailyDeliveryLimit) { 997 - // this should never happen, but just in case 998 - slotsForThisDay = dailyDeliveryLimit; 983 + return [isEnabledDay, '', `Slots available: ${slotsForThisDay}`]; // enabled boolean, css class, tooltip 999 984 } 1000 985 1001 - const isEnabledDay = 1002 - slotsForThisDay > 0 && 1003 - !disabledDates.includes(dayBeingCheckedFormatted); 986 + $('#datepicker').datepicker({ 987 + beforeShowDay: disableDates, 988 + onClose: function () { 989 + const datepicker = document.querySelector('#datepicker'); 990 + const deliveryDate = datepicker.value; 991 + if (deliveryDate) { 992 + sessionStorage.setItem('deliveryDate', deliveryDate); 993 + } 994 + }, 995 + defaultDate: '+1D', 996 + minDate: '+1D', 997 + maxDate: '+28D', 998 + dateFormat: 'd MM, yy', 999 + showOtherMonths: true, 1000 + firstDay: 1, 1001 + placeholder: 'Select Date', 1002 + }); 1004 1003 1005 - return [isEnabledDay, '', `Slots available: ${slotsForThisDay}`]; // enabled boolean, css class, tooltip 1004 + $('#datepicker').attr('placeholder', 'Select Date'); 1006 1005 } 1007 1006 1008 - $('#datepicker').datepicker({ 1009 - beforeShowDay: disableDates, 1010 - onClose: function () { 1011 - const datepicker = document.querySelector('#datepicker'); 1012 - const deliveryDate = datepicker.value; 1013 - if (deliveryDate) { 1014 - sessionStorage.setItem('deliveryDate', deliveryDate); 1015 - } 1016 - }, 1017 - defaultDate: '+1D', 1018 - minDate: '+1D', 1019 - maxDate: '+28D', 1020 - dateFormat: 'd MM, yy', 1021 - showOtherMonths: true, 1022 - firstDay: 1, 1023 - placeholder: 'Select Date', 1024 - }); 1007 + // ------------------------------------------------------// 1008 + // handle proceed button 1009 + const proceedButtonSelector = '#proceedButton'; 1010 + ready(proceedButtonSelector, (proceedButton) => { 1011 + proceedButton.addEventListener('click', function (e) { 1012 + e.preventDefault(); 1013 + const deliveryDate = sessionStorage.getItem('deliveryDate'); 1014 + const customerMessage = sessionStorage.getItem('customerMessage'); 1015 + const realContinueButton = document.querySelector( 1016 + '#checkout-shipping-continue' 1017 + ); 1025 1018 1026 - $('#datepicker').attr('placeholder', 'Select Date'); 1027 - } 1019 + const datepickerErrorElement = 1020 + document.getElementById('datepicker_err'); 1028 1021 1029 - // ------------------------------------------------------// 1030 - // handle proceed button 1031 - const proceedButtonSelector = '#proceedButton'; 1032 - ready(proceedButtonSelector, (proceedButton) => { 1033 - proceedButton.addEventListener('click', function (e) { 1034 - e.preventDefault(); 1035 - const deliveryDate = sessionStorage.getItem('deliveryDate'); 1036 - const customerMessage = sessionStorage.getItem('customerMessage'); 1037 - const realContinueButton = document.querySelector( 1038 - '#checkout-shipping-continue' 1039 - ); 1022 + if (!deliveryDate) { 1023 + datepickerErrorElement.textContent = 1024 + 'Please select a delivery date before proceeding.'; 1025 + datepickerErrorElement.style.display = 'block'; 1026 + return; 1027 + } 1028 + // Proceed with the form submission 1029 + datepickerErrorElement.style.display = 'none'; 1040 1030 1041 - const datepickerErrorElement = 1042 - document.getElementById('datepicker_err'); 1031 + const selectElement = document.querySelector('#delivery_inst_tag'); 1032 + const selectedValue = selectElement.value; 1033 + const deliveryInstructions = 1034 + selectedValue === 'user_instruction' && 1035 + customerMessage.length > 0 1036 + ? customerMessage 1037 + : 'Will be in'; 1043 1038 1044 - if (!deliveryDate) { 1045 - datepickerErrorElement.textContent = 1046 - 'Please select a delivery date before proceeding.'; 1047 - datepickerErrorElement.style.display = 'block'; 1048 - return; 1049 - } 1050 - // Proceed with the form submission 1051 - datepickerErrorElement.style.display = 'none'; 1039 + const fullInstructions = `${deliveryDate} | ${deliveryInstructions}`; 1052 1040 1053 - const selectElement = document.querySelector('#delivery_inst_tag'); 1054 - const selectedValue = selectElement.value; 1055 - const deliveryInstructions = 1056 - selectedValue === 'user_instruction' && 1057 - customerMessage.length > 0 1058 - ? customerMessage 1059 - : 'Will be in'; 1041 + // send the message to the middleware server to store in supabase as a backup if BC fails to store it 1042 + fetch( 1043 + `https://purrform-apps-027e.onrender.com/storeCustomerMessage?checkoutId={{cart_id}}&message=${fullInstructions}`, 1044 + { 1045 + method: 'GET', 1046 + headers: { 1047 + 'Content-Type': 'application/json', 1048 + }, 1049 + } 1050 + ) 1051 + .then((response) => { 1052 + if (!response.ok) { 1053 + throw new Error('Failed to store customer message'); 1054 + } 1055 + console.log('Customer message stored successfully'); 1056 + }) 1057 + .catch((error) => { 1058 + console.error( 1059 + 'Error storing customer message in supabase:', 1060 + error 1061 + ); 1062 + }); 1060 1063 1061 - const fullInstructions = `${deliveryDate} | ${deliveryInstructions}`; 1064 + const realCommentsInput = document.querySelector( 1065 + 'input[name="orderComment"]' 1066 + ); 1062 1067 1063 - // send the message to the middleware server to store in supabase as a backup if BC fails to store it 1064 - fetch( 1065 - `https://purrform-apps-027e.onrender.com/storeCustomerMessage?checkoutId={{cart_id}}&message=${fullInstructions}`, 1066 - { 1067 - method: 'GET', 1068 + // Update the customer message with the delivery instructions 1069 + fetch(`/api/storefront/checkouts/{{cart_id}}`, { 1070 + method: 'PUT', 1068 1071 headers: { 1069 1072 'Content-Type': 'application/json', 1070 1073 }, 1071 - } 1072 - ) 1073 - .then((response) => { 1074 - if (!response.ok) { 1075 - throw new Error('Failed to store customer message'); 1076 - } 1077 - console.log('Customer message stored successfully'); 1074 + body: JSON.stringify({ 1075 + customerMessage: fullInstructions, 1076 + }), 1078 1077 }) 1079 - .catch((error) => { 1080 - console.error( 1081 - 'Error storing customer message in supabase:', 1082 - error 1083 - ); 1084 - }); 1085 - 1086 - const realCommentsInput = document.querySelector( 1087 - 'input[name="orderComment"]' 1088 - ); 1089 - 1090 - // Update the customer message with the delivery instructions 1091 - fetch(`/api/storefront/checkouts/{{cart_id}}`, { 1092 - method: 'PUT', 1093 - headers: { 1094 - 'Content-Type': 'application/json', 1095 - }, 1096 - body: JSON.stringify({ 1097 - customerMessage: fullInstructions, 1098 - }), 1099 - }) 1100 - .then((response) => { 1101 - if (!response.ok) { 1102 - throw new Error('PUT request failed'); 1103 - } 1104 - sessionStorage.removeItem('deliveryDate'); 1105 - sessionStorage.removeItem('customerMessage'); 1106 - realCommentsInput.value = fullInstructions; 1107 - realContinueButton.click(); 1108 - }) 1109 - .catch((error) => { 1110 - console.error('Error:', error); 1111 - realCommentsInput.value = fullInstructions; 1112 - }); 1078 + .then((response) => { 1079 + if (!response.ok) { 1080 + throw new Error('PUT request failed'); 1081 + } 1082 + sessionStorage.removeItem('deliveryDate'); 1083 + sessionStorage.removeItem('customerMessage'); 1084 + realCommentsInput.value = fullInstructions; 1085 + realContinueButton.click(); 1086 + }) 1087 + .catch((error) => { 1088 + console.error('Error:', error); 1089 + realCommentsInput.value = fullInstructions; 1090 + }); 1091 + }); 1113 1092 }); 1114 - }); 1115 1093 1116 - // ------------------------------------------------------// 1117 - // This handles the delivery details / customer message 1118 - const deliveryDetailsSelector = 1119 - 'fieldset.form-fieldset[data-test="checkout-shipping-comments"]'; 1120 - ready(deliveryDetailsSelector, (deliveryDetailsElement) => { 1121 - const existingInstructions = 1122 - document.getElementById('instruction-wrap'); 1123 - if (existingInstructions) { 1124 - return; 1125 - } 1094 + // ------------------------------------------------------// 1095 + // This handles the delivery details / customer message 1096 + const deliveryDetailsSelector = 1097 + 'fieldset.form-fieldset[data-test="checkout-shipping-comments"]'; 1098 + ready(deliveryDetailsSelector, (deliveryDetailsElement) => { 1099 + const existingInstructions = 1100 + document.getElementById('instruction-wrap'); 1101 + if (existingInstructions) { 1102 + return; 1103 + } 1126 1104 1127 - // generate custom HTML 1128 - const instructionsDiv = ` 1105 + // generate custom HTML 1106 + const instructionsDiv = ` 1129 1107 <div id="instruction-wrap" class="delivery_instruction_wrapper"> 1130 1108 <div class="del_cont"> 1131 1109 <label class="form-legend optimizedCheckout-headingSecondary">Delivery Details</label> ··· 1140 1118 </div> 1141 1119 `; 1142 1120 1143 - deliveryDetailsElement.insertAdjacentHTML('afterend', instructionsDiv); 1121 + deliveryDetailsElement.insertAdjacentHTML('afterend', instructionsDiv); 1144 1122 1145 - const selectElement = document.getElementById('delivery_inst_tag'); 1146 - const textarea = document.getElementById('delivery_user_text'); 1147 - const wordLimit = document.getElementById('word_limit'); 1123 + const selectElement = document.getElementById('delivery_inst_tag'); 1124 + const textarea = document.getElementById('delivery_user_text'); 1125 + const wordLimit = document.getElementById('word_limit'); 1148 1126 1149 - selectElement.addEventListener('change', function () { 1150 - const selectedValue = selectElement.value; 1151 - if (selectedValue === 'user_instruction') { 1152 - textarea.style.display = 'block'; 1153 - wordLimit.style.display = 'block'; 1154 - textarea.focus(); 1155 - } else { 1156 - wordLimit.style.display = 'none'; 1157 - textarea.style.display = 'none'; 1158 - } 1159 - }); 1127 + selectElement.addEventListener('change', function () { 1128 + const selectedValue = selectElement.value; 1129 + if (selectedValue === 'user_instruction') { 1130 + textarea.style.display = 'block'; 1131 + wordLimit.style.display = 'block'; 1132 + textarea.focus(); 1133 + } else { 1134 + wordLimit.style.display = 'none'; 1135 + textarea.style.display = 'none'; 1136 + } 1137 + }); 1160 1138 1161 - textarea.addEventListener('input', function () { 1162 - wordLimit.textContent = `(${50 - textarea.value.length} characters)`; 1163 - const deliveryInstructions = textarea.value; 1164 - sessionStorage.setItem('customerMessage', deliveryInstructions); 1139 + textarea.addEventListener('input', function () { 1140 + wordLimit.textContent = `(${50 - textarea.value.length} characters)`; 1141 + const deliveryInstructions = textarea.value; 1142 + sessionStorage.setItem('customerMessage', deliveryInstructions); 1143 + }); 1165 1144 }); 1166 - }); 1167 1145 1168 - // ------------------------------------------------------// 1169 - // This handles the payment continue button 1170 - const paymentContinueButtonSelector = '#checkout-payment-continue'; 1171 - ready(paymentContinueButtonSelector, (paymentContinueButton) => { 1172 - if (document.getElementById('fakeButton')) { 1173 - document.getElementById('fakeButton').remove(); 1174 - } 1175 - const fakeButton = document.createElement('div'); 1176 - const missingWarn = document.createElement('p'); 1177 - const parent = document.querySelector( 1178 - '.checkout-step--payment .checkout-form .form-actions' 1179 - ); 1146 + // ------------------------------------------------------// 1147 + // This handles the payment continue button 1148 + const paymentContinueButtonSelector = '#checkout-payment-continue'; 1149 + ready(paymentContinueButtonSelector, (paymentContinueButton) => { 1150 + if (document.getElementById('fakeButton')) { 1151 + document.getElementById('fakeButton').remove(); 1152 + } 1153 + const fakeButton = document.createElement('div'); 1154 + const missingWarn = document.createElement('p'); 1155 + const parent = document.querySelector( 1156 + '.checkout-step--payment .checkout-form .form-actions' 1157 + ); 1180 1158 1181 - // hide the real button 1182 - paymentContinueButton.style.display = 'none'; 1159 + // hide the real button 1160 + paymentContinueButton.style.display = 'none'; 1183 1161 1184 - // Generate placeholder button 1185 - fakeButton.innerHTML = 'Place Order'; 1186 - fakeButton.id = 'fakeButton'; 1187 - fakeButton.style.display = 'block'; 1162 + // Generate placeholder button 1163 + fakeButton.innerHTML = 'Place Order'; 1164 + fakeButton.id = 'fakeButton'; 1165 + fakeButton.style.display = 'block'; 1188 1166 1189 - // Generate warning text 1190 - missingWarn.classList.add('warning'); 1191 - missingWarn.textContent = 1192 - "Cannot find delivery date. Please edit your Shipping details above and select a delivery date."; 1193 - missingWarn.style.display = 'none'; 1167 + // Generate warning text 1168 + missingWarn.classList.add('warning'); 1169 + missingWarn.textContent = 1170 + "Cannot find delivery date. Please edit your Shipping details above and select a delivery date."; 1171 + missingWarn.style.display = 'none'; 1194 1172 1195 - // Append the button to the body of the HTML document 1196 - parent.appendChild(missingWarn); 1197 - parent.appendChild(fakeButton); 1173 + // Append the button to the body of the HTML document 1174 + parent.appendChild(missingWarn); 1175 + parent.appendChild(fakeButton); 1198 1176 1199 - fakeButton.addEventListener('click', async () => { 1200 - const disabledDates = await fetch('https://purrform-apps-027e.onrender.com/deliveryDates') 1201 - .then((response) => { 1202 - if (!response.ok) { 1203 - throw new Error('Network response was not ok'); 1204 - } 1205 - return response.json(); 1206 - }) 1207 - .then((data) => { 1208 - return data.unavailableDates; 1209 - }) 1210 - .catch((error) => { 1211 - console.error('Error calling delivery dates middleware endpoint:', error); 1212 - }); 1177 + fakeButton.addEventListener('click', async () => { 1178 + const disabledDates = await fetch('https://purrform-apps-027e.onrender.com/deliveryDates') 1179 + .then((response) => { 1180 + if (!response.ok) { 1181 + throw new Error('Network response was not ok'); 1182 + } 1183 + return response.json(); 1184 + }) 1185 + .then((data) => { 1186 + return data.unavailableDates; 1187 + }) 1188 + .catch((error) => { 1189 + console.error('Error calling delivery dates middleware endpoint:', error); 1190 + }); 1213 1191 1214 - fetch(`/api/storefront/checkouts/{{cart_id}}`, { 1215 - method: 'GET', 1216 - headers: { 1217 - 'Content-Type': 'application/json', 1218 - }, 1219 - }) 1220 - .then((response) => { 1221 - if (!response.ok) { 1222 - throw new Error('GET request failed'); 1223 - } 1224 - return response.json(); // Parse the JSON response 1192 + fetch(`/api/storefront/checkouts/{{cart_id}}`, { 1193 + method: 'GET', 1194 + headers: { 1195 + 'Content-Type': 'application/json', 1196 + }, 1225 1197 }) 1226 - .then((data) => { 1227 - const deliveryInstructions = data.customerMessage; 1228 - const [selectedDate] = deliveryInstructions.split(' | ') 1229 - const maybeDate = new Date(selectedDate) // Ex: 3 April, 2025 1230 - const adjustForDaylightDate = new Date(maybeDate.getTime() + 3 * 60 * 60 * 1000); 1231 - const formattedDate = adjustForDaylightDate.toISOString().split('T')[0]; // Format the date for comparison 1198 + .then((response) => { 1199 + if (!response.ok) { 1200 + throw new Error('GET request failed'); 1201 + } 1202 + return response.json(); // Parse the JSON response 1203 + }) 1204 + .then((data) => { 1205 + const deliveryInstructions = data.customerMessage; 1206 + const [selectedDate] = deliveryInstructions.split(' | ') 1207 + const maybeDate = new Date(selectedDate) // Ex: 3 April, 2025 1208 + const adjustForDaylightDate = new Date(maybeDate.getTime() + 3 * 60 * 60 * 1000); 1209 + const formattedDate = adjustForDaylightDate.toISOString().split('T')[0]; // Format the date for comparison 1232 1210 1233 - if (disabledDates.includes(formattedDate)) { 1234 - missingWarn.textContent = 'The selected delivery date is not available. Please click the Edit button on the Shipping section above and then pick an available date on the delivery date calendar.'; 1235 - missingWarn.style.display = 'block'; 1236 - return; 1237 - } 1211 + if (disabledDates.includes(formattedDate)) { 1212 + missingWarn.textContent = 'The selected delivery date is not available. Please click the Edit button on the Shipping section above and then pick an available date on the delivery date calendar.'; 1213 + missingWarn.style.display = 'block'; 1214 + return; 1215 + } 1238 1216 1239 - if (deliveryInstructions?.trim()) { 1240 - paymentContinueButton.click(); 1241 - } else { 1242 - missingWarn.style.display = 'block'; 1243 - } 1217 + if (deliveryInstructions?.trim()) { 1218 + paymentContinueButton.click(); 1219 + } else { 1220 + missingWarn.style.display = 'block'; 1221 + } 1244 1222 1245 - }) 1246 - .catch((error) => { 1247 - console.error('Error:', error); 1248 - missingWarn.textContent = 1249 - 'Something went wrong. Check if you have set a delivery date in the Shipping section above and try again.'; 1250 - missingWarn.style.display = 'block'; 1251 - }); 1223 + }) 1224 + .catch((error) => { 1225 + console.error('Error:', error); 1226 + missingWarn.textContent = 1227 + 'Something went wrong. Check if you have set a delivery date in the Shipping section above and try again.'; 1228 + missingWarn.style.display = 'block'; 1229 + }); 1230 + }); 1252 1231 }); 1253 - }); 1254 - </script> 1232 + </script> 1255 1233 1256 - <script type="module"> 1257 - const customerGroupName = '{{customer_group_name}}'; 1258 - const tradeCustomerGroupNames = ['Trade', 'New Trader', 'Trader TNC']; 1259 - const isTraderGroup = tradeCustomerGroupNames.includes(customerGroupName); 1234 + <script type="module"> 1235 + const customerGroupName = '{{customer_group_name}}'; 1236 + const tradeCustomerGroupNames = ['Trade', 'New Trader', 'Trader TNC']; 1237 + const isTraderGroup = tradeCustomerGroupNames.includes(customerGroupName); 1260 1238 1261 - if (isTraderGroup) { 1262 - let hasOverdue = false; 1263 - let lowBalance = false; 1239 + if (isTraderGroup) { 1240 + let hasOverdue = false; 1241 + let lowBalance = false; 1264 1242 1265 - try { 1266 - const response = await fetch('https://purrform-apps-027e.onrender.com/getCreditSystemTraders', { 1267 - method: 'GET', 1268 - headers: { 1269 - 'Content-Type': 'application/json', 1270 - } 1271 - }); 1243 + try { 1244 + const response = await fetch('https://purrform-apps-027e.onrender.com/getCreditSystemTraders', { 1245 + method: 'GET', 1246 + headers: { 1247 + 'Content-Type': 'application/json', 1248 + } 1249 + }); 1272 1250 1273 - if (response.ok) { 1274 - const traders = await response.json(); // { bc_customer_email: string, credit_ceiling: number, current_balance: number, has_overdue: boolean, id: number }[] 1275 - const traderInCreditSystem = traders.find(t => t.bc_customer_email === '{{customer.email}}'); 1251 + if (response.ok) { 1252 + const traders = await response.json(); // { bc_customer_email: string, credit_ceiling: number, current_balance: number, has_overdue: boolean, id: number }[] 1253 + const traderInCreditSystem = traders.find(t => t.bc_customer_email === '{{customer.email}}'); 1276 1254 1277 - if (traderInCreditSystem) { 1278 - // Put the credit balance info before the cart subtotal 1279 - ready('div[data-test="cart-subtotal"]', (element) => { 1280 - element.insertAdjacentHTML( 1281 - 'beforebegin', 1282 - `<div class="creditBalanceInfo"> 1255 + if (traderInCreditSystem) { 1256 + // Put the credit balance info before the cart subtotal 1257 + ready('div[data-test="cart-subtotal"]', (element) => { 1258 + element.insertAdjacentHTML( 1259 + 'beforebegin', 1260 + `<div class="creditBalanceInfo"> 1283 1261 <div>Credit Balance </div> 1284 1262 <div class="creditBalanceAmount">£${traderInCreditSystem.current_balance.toFixed(2)}</div> 1285 1263 </div>` 1286 - ); 1287 - }); 1264 + ); 1265 + }); 1288 1266 1289 - // Add any overdue / low balance message to the cart total section 1290 - ready('div[data-test="cart-total"]', (element) => { 1291 - hasOverdue = traderInCreditSystem.has_overdue; 1267 + // Add any overdue / low balance message to the cart total section 1268 + ready('div[data-test="cart-total"]', (element) => { 1269 + hasOverdue = traderInCreditSystem.has_overdue; 1292 1270 1293 - if (hasOverdue) { 1294 - element.insertAdjacentHTML( 1295 - 'beforeend', 1296 - `<div class="credit-balance-message"> 1271 + if (hasOverdue) { 1272 + element.insertAdjacentHTML( 1273 + 'beforeend', 1274 + `<div class="credit-balance-message"> 1297 1275 You have overdue order(s) unpaid. New orders will not be processed until payment is made. <a href="/account.php?action=order_status">Click here</a> to see the overdue order(s) in your account. 1298 1276 </div>` 1299 - ); 1300 - } else { 1301 - const cartTotalText = document.querySelector( 1302 - 'div[data-test="cart-total"] span[data-test="cart-price-value"]' 1303 - ).textContent; 1304 - const cartTotal = Number(cartTotalText.replace('£', '')); 1305 - lowBalance = cartTotal > traderInCreditSystem.current_balance; 1277 + ); 1278 + } else { 1279 + const cartTotalText = document.querySelector( 1280 + 'div[data-test="cart-total"] span[data-test="cart-price-value"]' 1281 + ).textContent; 1282 + const cartTotal = Number(cartTotalText.replace('£', '')); 1283 + lowBalance = cartTotal > traderInCreditSystem.current_balance; 1306 1284 1307 - if (lowBalance) { 1308 - element.insertAdjacentHTML( 1309 - 'beforeend', 1310 - `<div class="credit-balance-message"> 1285 + if (lowBalance) { 1286 + element.insertAdjacentHTML( 1287 + 'beforeend', 1288 + `<div class="credit-balance-message"> 1311 1289 Your cart total exceeds your credit limit. You can either remove some items or pay the balance to process your order. 1312 1290 </div>` 1313 - ); 1291 + ); 1292 + } 1293 + 1314 1294 } 1315 1295 1316 - } 1296 + }); 1317 1297 1318 - }); 1319 1298 1299 + if (hasOverdue || lowBalance) { 1300 + // Hide the payment button if there is an overdue order or low balance 1301 + ready('#fakeButton', (element) => { 1302 + element.remove() 1303 + }); 1320 1304 1321 - if (hasOverdue || lowBalance) { 1322 - // Hide the payment button if there is an overdue order or low balance 1323 - ready('#fakeButton', (element) => { 1324 - element.remove() 1325 - }); 1305 + ready('#proceedButton', (element) => { 1306 + element.style.display = hasOverdue || lowBalance ? 'none' : 'block'; 1307 + }); 1326 1308 1327 - ready('#proceedButton', (element) => { 1328 - element.style.display = hasOverdue || lowBalance ? 'none' : 'block'; 1329 - }); 1309 + ready('#checkoutPaymentContinue', (element) => { 1310 + element.style.display = hasOverdue || lowBalance ? 'none' : 'block'; 1311 + }); 1312 + } else { 1313 + // change the fakeButton text to Pay Now 1314 + ready('#fakeButton', (element) => { 1315 + element.innerHTML = 'Pay Now'; 1316 + }); 1317 + // add a new button next to the fake button to allow payment on credit 1318 + ready('.checkout-step--payment .checkout-form .form-actions', (element) => { 1319 + const creditPaymentButton = document.createElement('div'); 1320 + creditPaymentButton.innerHTML = 'Pay on Credit'; 1321 + creditPaymentButton.id = 'creditPaymentButton'; 1330 1322 1331 - ready('#checkoutPaymentContinue', (element) => { 1332 - element.style.display = hasOverdue || lowBalance ? 'none' : 'block'; 1333 - }); 1334 - } else { 1335 - // change the fakeButton text to Pay Now 1336 - ready('#fakeButton', (element) => { 1337 - element.innerHTML = 'Pay Now'; 1338 - }); 1339 - // add a new button next to the fake button to allow payment on credit 1340 - ready('.checkout-step--payment .checkout-form .form-actions', (element) => { 1341 - const creditPaymentButton = document.createElement('div'); 1342 - creditPaymentButton.innerHTML = 'Pay on Credit'; 1343 - creditPaymentButton.id = 'creditPaymentButton'; 1323 + creditPaymentButton.addEventListener('click', function () { 1324 + // 1 - Put the button in loading state and disable the other button 1325 + $('#creditPaymentButton').text('Processing...').attr('disabled', 'true'); 1326 + $('#fakeButton').attr('disabled', 'true'); 1344 1327 1345 - creditPaymentButton.addEventListener('click', function () { 1346 - // 1 - Put the button in loading state and disable the other button 1347 - $('#creditPaymentButton').text('Processing...').attr('disabled', 'true'); 1348 - $('#fakeButton').attr('disabled', 'true'); 1349 1328 1329 + // get cart_id 1330 + const cartId = '{{cart_id}}'; 1350 1331 1351 - // get cart_id 1352 - const cartId = '{{cart_id}}'; 1353 1332 1333 + // 2 - Call the backend to process the credit payment 1334 + fetch(`https://purrform-apps-027e.onrender.com/processCreditPayment?cartId=${cartId}`, { 1335 + method: 'GET', 1336 + headers: { 1337 + 'Content-Type': 'application/json', 1338 + }, 1354 1339 1355 - // 2 - Call the backend to process the credit payment 1356 - fetch(`https://purrform-apps-027e.onrender.com/processCreditPayment?cartId=${cartId}`, { 1357 - method: 'GET', 1358 - headers: { 1359 - 'Content-Type': 'application/json', 1360 - }, 1340 + }).then(response => { 1341 + if (!response.ok) { 1342 + throw new Error('Network response was not ok'); 1343 + } 1344 + // remove both buttons and put a thank you message 1345 + $('#creditPaymentButton').remove(); 1346 + $('#fakeButton').remove(); 1347 + // remove any previous error message 1348 + $('.checkout-step--payment .checkout-form .form-actions .credit-balance-message').remove(); 1349 + const thankYouMessage = '<div class="credit-balance-message" style="background-color: #d4edda; color: #155724;">Your order has been placed successfully using credit payment. You can navigate away from this page. <a href="https://www.purrform.co.uk">Back to homepage.</a></div>'; 1350 + $('.checkout-step--payment .checkout-form .form-actions').append(thankYouMessage); 1351 + }).catch(error => { 1352 + // 3 - Show an error message 1353 + $('.checkout-step--payment .checkout-form .form-actions .credit-balance-message').remove(); 1354 + const errorMessage = '<div class="credit-balance-message" style="background-color: #f8d7da; color: #721c24;">There was an error processing your credit payment. Please try again or use another payment method.</div>'; 1355 + $('.checkout-step--payment .checkout-form .form-actions').append(errorMessage); 1356 + // Re-enable buttons 1357 + $('#creditPaymentButton').text('Pay on Credit').removeAttr('disabled'); 1358 + $('#fakeButton').removeAttr('disabled'); 1359 + }) 1361 1360 1362 - }).then(response => { 1363 - if (!response.ok) { 1364 - throw new Error('Network response was not ok'); 1365 - } 1366 - // remove both buttons and put a thank you message 1367 - $('#creditPaymentButton').remove(); 1368 - $('#fakeButton').remove(); 1369 - // remove any previous error message 1370 - $('.checkout-step--payment .checkout-form .form-actions .credit-balance-message').remove(); 1371 - const thankYouMessage = '<div class="credit-balance-message" style="background-color: #d4edda; color: #155724;">Your order has been placed successfully using credit payment. You can navigate away from this page. <a href="https://www.purrform.co.uk">Back to homepage.</a></div>'; 1372 - $('.checkout-step--payment .checkout-form .form-actions').append(thankYouMessage); 1373 - }).catch(error => { 1374 - // 3 - Show an error message 1375 - $('.checkout-step--payment .checkout-form .form-actions .credit-balance-message').remove(); 1376 - const errorMessage = '<div class="credit-balance-message" style="background-color: #f8d7da; color: #721c24;">There was an error processing your credit payment. Please try again or use another payment method.</div>'; 1377 - $('.checkout-step--payment .checkout-form .form-actions').append(errorMessage); 1378 - // Re-enable buttons 1379 - $('#creditPaymentButton').text('Pay on Credit').removeAttr('disabled'); 1380 - $('#fakeButton').removeAttr('disabled'); 1381 - }) 1361 + }); 1382 1362 1363 + element.appendChild(creditPaymentButton); 1383 1364 }); 1384 1365 1385 - element.appendChild(creditPaymentButton); 1386 - }); 1387 - 1366 + } 1388 1367 } 1389 1368 } 1369 + } catch (error) { 1370 + console.error('Error fetching trader data:', error); 1390 1371 } 1391 - } catch (error) { 1392 - console.error('Error fetching trader data:', error); 1393 1372 } 1394 - } 1395 - </script> 1373 + </script> 1396 1374 1397 1375 1398 - <style> 1399 - .creditBalanceInfo { 1400 - display: flex; 1401 - justify-content: space-between; 1402 - margin-bottom: 14px; 1403 - padding-bottom: 4px; 1404 - border-bottom: 1px solid #dbdada; 1405 - } 1376 + <style> 1377 + .creditBalanceInfo { 1378 + display: flex; 1379 + justify-content: space-between; 1380 + margin-bottom: 14px; 1381 + padding-bottom: 4px; 1382 + border-bottom: 1px solid #dbdada; 1383 + } 1406 1384 1407 - .credit-balance-message { 1385 + .credit-balance-message { 1408 1386 1409 - width: 100%; 1410 - padding: 10px; 1411 - background-color: #f8d7da; 1412 - color: #721c24; 1413 - border-radius: 4px; 1414 - font-size: 14px; 1415 - margin-top: 1rem; 1416 - text-align: center; 1417 - } 1418 - .optimizedCheckout-cart-modal .optimizedCheckout-orderSummary-cartSection { 1419 - padding: 20px; 1420 - } 1421 - .modal-body.cart-modal-body.optimizedCheckout-orderSummary { 1422 - height: 100vh; 1423 - } 1424 - .modal.modal--afterOpen.optimizedCheckout-cart-modal .modal-body { 1425 - height: auto !important; 1426 - max-height: 100vh; 1427 - overflow-y: auto !important; 1428 - -webkit-overflow-scrolling: touch; 1429 - } 1430 - .storeCreditOverlay { 1431 - z-index: 9 !important; 1432 - } 1433 - .loyalty-summary { 1434 - margin: 10px 0; 1435 - } 1436 - .cart-resultItem { 1437 - display: grid; 1438 - grid-template-columns: 1fr auto; 1439 - margin-top: 0.5rem; 1440 - padding-bottom: 0.2rem; 1441 - } 1442 - .cart-resultItem p { 1443 - font-weight: bold; 1444 - } 1445 - .cart-summaryItem { 1446 - display: grid; 1447 - grid-template-columns: 1fr auto; 1448 - border-bottom: 1px solid #333333; 1449 - margin-top: 0.5rem; 1450 - padding-bottom: 0.2rem; 1451 - } 1452 - #pointsDesc { 1453 - font-weight: bold; 1454 - margin-bottom: 20px; 1455 - } 1456 - #usedPointsDesc { 1457 - margin: 0; 1458 - } 1459 - .btn.btn-primary, 1460 - .btn.btn-secondary { 1461 - border: 1px solid #687d6a; 1462 - border-radius: 32px; 1463 - font-size: 16px; 1464 - background-color: #687d6a; 1465 - -webkit-transition: all 0.15s ease; 1466 - transition: all 0.15s ease; 1467 - padding: 16px 13px; 1468 - color: white; 1469 - text-transform: uppercase; 1470 - margin-top: 20px; 1471 - } 1472 - .btn.btn-primary:hover, 1473 - .btn.btn-secondary:hover { 1474 - background-color: white; 1475 - color: #687d6a; 1476 - } 1477 - .modal.modal--afterOpen.optimizedCheckout-cart-modal .modal-body { 1478 - box-shadow: none; 1479 - height: 100%; 1480 - padding-bottom: 0; 1481 - overflow-x: auto; 1482 - overflow-y: auto; 1483 - } 1484 - .loyalty-points { 1485 - display: flex; 1486 - flex-direction: column; 1487 - background-color: #ffedcd; 1488 - } 1387 + width: 100%; 1388 + padding: 10px; 1389 + background-color: #f8d7da; 1390 + color: #721c24; 1391 + border-radius: 4px; 1392 + font-size: 14px; 1393 + margin-top: 1rem; 1394 + text-align: center; 1395 + } 1489 1396 1490 - #points-input { 1491 - border: 1px solid #dbdada; 1492 - border-radius: 32px; 1493 - padding: 16px 12px; 1494 - } 1495 - fieldset[data-test='checkout-shipping-comments'], 1496 - #checkout-shipping-continue, 1497 - input[name='orderComment'], 1498 - #checkout-payment-continue { 1499 - display: none; 1500 - } 1501 - .warning { 1502 - color: red !important; 1503 - border-color: red !important; 1504 - } 1397 + .optimizedCheckout-cart-modal .optimizedCheckout-orderSummary-cartSection { 1398 + padding: 20px; 1399 + } 1505 1400 1506 - .warning * { 1507 - color: red !important; 1508 - border-color: red !important; 1509 - } 1401 + .modal-body.cart-modal-body.optimizedCheckout-orderSummary { 1402 + height: 100vh; 1403 + } 1510 1404 1511 - #fakeButton, 1512 - #creditPaymentButton, 1513 - #proceedButton { 1514 - color: white; 1515 - border: 1px solid #687d6a; 1516 - border-radius: 32px; 1517 - font-size: 16px; 1518 - background-color: #687d6a; 1519 - transition: all 0.15s ease; 1520 - font-family: 'Montserrat', Arial, Helvetica, sans-serif; 1521 - font-weight: 500; 1522 - padding: 14px 24px; 1523 - text-align: center; 1524 - width: 100%; 1525 - margin: 20px 0px; 1526 - cursor: pointer; 1527 - vertical-align: baseline; 1528 - display: inline-block; 1529 - text-transform: uppercase; 1530 - font-weight: bold; 1531 - } 1405 + .modal.modal--afterOpen.optimizedCheckout-cart-modal .modal-body { 1406 + height: auto !important; 1407 + max-height: 100vh; 1408 + overflow-y: auto !important; 1409 + -webkit-overflow-scrolling: touch; 1410 + } 1532 1411 1533 - #creditPaymentButton { 1534 - background-color: transparent; 1535 - color: #687d6a; 1536 - } 1412 + .storeCreditOverlay { 1413 + z-index: 9 !important; 1414 + } 1537 1415 1538 - #creditPaymentButton:hover { 1539 - background-color: #687d6a; 1540 - color: white; 1541 - } 1416 + .loyalty-summary { 1417 + margin: 10px 0; 1418 + } 1542 1419 1543 - #fakeButton:hover, 1544 - #proceedButton:hover { 1545 - background-color: transparent; 1546 - color: #687d6a; 1547 - } 1420 + .cart-resultItem { 1421 + display: grid; 1422 + grid-template-columns: 1fr auto; 1423 + margin-top: 0.5rem; 1424 + padding-bottom: 0.2rem; 1425 + } 1548 1426 1549 - #fakeButton[disabled], 1550 - #creditPaymentButton[disabled], 1551 - #proceedButton[disabled] { 1552 - background-color: #cccccc !important; 1553 - border-color: #999999 !important; 1554 - color: #666666 !important; 1555 - cursor: not-allowed !important; 1556 - } 1427 + .cart-resultItem p { 1428 + font-weight: bold; 1429 + } 1557 1430 1558 - /* DATE PICKER */ 1559 - .datepicker { 1560 - z-index: 1; 1561 - } 1431 + .cart-summaryItem { 1432 + display: grid; 1433 + grid-template-columns: 1fr auto; 1434 + border-bottom: 1px solid #333333; 1435 + margin-top: 0.5rem; 1436 + padding-bottom: 0.2rem; 1437 + } 1562 1438 1563 - .datepicker .voucher-section .warning #datepicker { 1564 - border-color: red; 1565 - } 1439 + #pointsDesc { 1440 + font-weight: bold; 1441 + margin-bottom: 20px; 1442 + } 1566 1443 1567 - .ui-datepicker, 1568 - .ui-datepicker table, 1569 - .ui-datepicker tr, 1570 - .ui-datepicker td, 1571 - .ui-datepicker th { 1572 - margin: 0; 1573 - padding: 0; 1574 - border: none; 1575 - border-spacing: 0; 1576 - } 1444 + #usedPointsDesc { 1445 + margin: 0; 1446 + } 1577 1447 1578 - .ui-datepicker { 1579 - box-shadow: 0 5px 12px rgb(0 0 0 / 15%); 1580 - display: none; 1581 - width: 100%; 1582 - padding: 15px; 1583 - cursor: default; 1584 - text-transform: uppercase; 1585 - font-family: Filson-Soft; 1586 - font-size: 24px; 1587 - background: #fff; 1588 - -webkit-border-radius: 4px; 1589 - -moz-border-radius: 4px; 1590 - border-radius: 4px; 1591 - border: solid 1px #bd9b60; 1592 - } 1448 + .btn.btn-primary, 1449 + .btn.btn-secondary { 1450 + border: 1px solid #687d6a; 1451 + border-radius: 32px; 1452 + font-size: 16px; 1453 + background-color: #687d6a; 1454 + -webkit-transition: all 0.15s ease; 1455 + transition: all 0.15s ease; 1456 + padding: 16px 13px; 1457 + color: white; 1458 + text-transform: uppercase; 1459 + margin-top: 20px; 1460 + } 1593 1461 1594 - .ui-datepicker .ui-datepicker-header { 1595 - position: relative; 1596 - border: 1px solid #bd9b60; 1597 - background: #bd9b60 !important; 1598 - font-size: 1.2rem; 1599 - } 1462 + .btn.btn-primary:hover, 1463 + .btn.btn-secondary:hover { 1464 + background-color: white; 1465 + color: #687d6a; 1466 + } 1600 1467 1601 - .ui-datepicker-title { 1602 - text-align: center; 1603 - font-family: Filson-Soft; 1604 - } 1468 + .modal.modal--afterOpen.optimizedCheckout-cart-modal .modal-body { 1469 + box-shadow: none; 1470 + height: 100%; 1471 + padding-bottom: 0; 1472 + overflow-x: auto; 1473 + overflow-y: auto; 1474 + } 1605 1475 1606 - .ui-datepicker-month { 1607 - position: relative; 1608 - padding-right: 15px; 1609 - color: #fff; 1610 - font-family: Filson-Soft; 1611 - } 1476 + .loyalty-points { 1477 + display: flex; 1478 + flex-direction: column; 1479 + background-color: #ffedcd; 1480 + } 1612 1481 1613 - /* .ui-datepicker-current-day .ui-state-default {background-color:#687d6a;color: #bd9b60;} */ 1614 - .ui-datepicker-year { 1615 - padding-left: 8px; 1616 - color: #fff; 1617 - font-family: Filson-Soft; 1618 - } 1482 + #points-input { 1483 + border: 1px solid #dbdada; 1484 + border-radius: 32px; 1485 + padding: 16px 12px; 1486 + } 1619 1487 1620 - .ui-datepicker-month:before { 1621 - display: block; 1622 - position: absolute; 1623 - top: 5px; 1624 - right: 0; 1625 - width: 5px; 1626 - height: 5px; 1627 - content: ''; 1628 - background: #bd9b60; 1629 - -webkit-border-radius: 5px; 1630 - -moz-border-radius: 5px; 1631 - border-radius: 5px; 1632 - } 1488 + fieldset[data-test='checkout-shipping-comments'], 1489 + #checkout-shipping-continue, 1490 + input[name='orderComment'], 1491 + #checkout-payment-continue { 1492 + display: none; 1493 + } 1633 1494 1634 - .ui-datepicker-prev, 1635 - .ui-datepicker-next { 1636 - position: absolute; 1637 - top: 4px !important; 1638 - padding: 5px; 1639 - cursor: pointer; 1640 - } 1495 + .warning { 1496 + color: red !important; 1497 + border-color: red !important; 1498 + } 1641 1499 1642 - .ui-datepicker-prev { 1643 - left: 0; 1644 - padding-left: 0; 1645 - } 1500 + .warning * { 1501 + color: red !important; 1502 + border-color: red !important; 1503 + } 1646 1504 1647 - .ui-datepicker-next { 1648 - right: 0; 1649 - padding-right: 0; 1650 - } 1505 + #fakeButton, 1506 + #creditPaymentButton, 1507 + #proceedButton { 1508 + color: white; 1509 + border: 1px solid #687d6a; 1510 + border-radius: 32px; 1511 + font-size: 16px; 1512 + background-color: #687d6a; 1513 + transition: all 0.15s ease; 1514 + font-family: 'Montserrat', Arial, Helvetica, sans-serif; 1515 + font-weight: 500; 1516 + padding: 14px 24px; 1517 + text-align: center; 1518 + width: 100%; 1519 + margin: 20px 0px; 1520 + cursor: pointer; 1521 + vertical-align: baseline; 1522 + display: inline-block; 1523 + text-transform: uppercase; 1524 + font-weight: bold; 1525 + } 1651 1526 1652 - .ui-state-hover { 1653 - background: rgba(255, 255, 255, 0.1) !important; 1654 - } 1527 + #creditPaymentButton { 1528 + background-color: transparent; 1529 + color: #687d6a; 1530 + } 1655 1531 1656 - .ui-datepicker-calendar th { 1657 - padding-top: 15px; 1658 - padding-bottom: 10px; 1659 - text-align: center; 1660 - font-weight: normal; 1661 - color: #a8a8a8; 1662 - font-size: 1rem; 1663 - } 1532 + #creditPaymentButton:hover { 1533 + background-color: #687d6a; 1534 + color: white; 1535 + } 1664 1536 1665 - .ui-datepicker-calendar td { 1666 - padding: 2px 2px; 1667 - text-align: center; 1668 - line-height: 26px; 1669 - } 1537 + #fakeButton:hover, 1538 + #proceedButton:hover { 1539 + background-color: transparent; 1540 + color: #687d6a; 1541 + } 1670 1542 1671 - .ui-datepicker-calendar .ui-state-default { 1672 - display: block; 1673 - width: 100%; 1674 - -webkit-border-radius: 50px; 1675 - -moz-border-radius: 50px; 1676 - border-radius: 50px; 1677 - outline: none; 1678 - text-decoration: none; 1679 - color: #000; 1680 - border: 1px solid transparent; 1681 - } 1543 + #fakeButton[disabled], 1544 + #creditPaymentButton[disabled], 1545 + #proceedButton[disabled] { 1546 + background-color: #cccccc !important; 1547 + border-color: #999999 !important; 1548 + color: #666666 !important; 1549 + cursor: not-allowed !important; 1550 + } 1682 1551 1683 - .ui-datepicker-calendar .ui-state-active { 1684 - border-color: #bd9b60 !important; 1685 - background-color: #bd9b60 !important; 1686 - } 1552 + /* DATE PICKER */ 1553 + .datepicker { 1554 + z-index: 1; 1555 + } 1687 1556 1688 - .ui-datepicker-other-month .ui-state-default { 1689 - color: #ccc; 1690 - } 1557 + .datepicker .voucher-section .warning #datepicker { 1558 + border-color: red; 1559 + } 1691 1560 1692 - .ui-datepicker-other-month { 1693 - opacity: 0 !important; 1694 - } 1561 + .ui-datepicker, 1562 + .ui-datepicker table, 1563 + .ui-datepicker tr, 1564 + .ui-datepicker td, 1565 + .ui-datepicker th { 1566 + margin: 0; 1567 + padding: 0; 1568 + border: none; 1569 + border-spacing: 0; 1570 + } 1571 + 1572 + .ui-datepicker { 1573 + box-shadow: 0 5px 12px rgb(0 0 0 / 15%); 1574 + display: none; 1575 + width: 100%; 1576 + padding: 15px; 1577 + cursor: default; 1578 + text-transform: uppercase; 1579 + font-family: Filson-Soft; 1580 + font-size: 24px; 1581 + background: #fff; 1582 + -webkit-border-radius: 4px; 1583 + -moz-border-radius: 4px; 1584 + border-radius: 4px; 1585 + border: solid 1px #bd9b60; 1586 + } 1587 + 1588 + .ui-datepicker .ui-datepicker-header { 1589 + position: relative; 1590 + border: 1px solid #bd9b60; 1591 + background: #bd9b60 !important; 1592 + font-size: 1.2rem; 1593 + } 1594 + 1595 + .ui-datepicker-title { 1596 + text-align: center; 1597 + font-family: Filson-Soft; 1598 + } 1599 + 1600 + .ui-datepicker-month { 1601 + position: relative; 1602 + padding-right: 15px; 1603 + color: #fff; 1604 + font-family: Filson-Soft; 1605 + } 1606 + 1607 + /* .ui-datepicker-current-day .ui-state-default {background-color:#687d6a;color: #bd9b60;} */ 1608 + .ui-datepicker-year { 1609 + padding-left: 8px; 1610 + color: #fff; 1611 + font-family: Filson-Soft; 1612 + } 1613 + 1614 + .ui-datepicker-month:before { 1615 + display: block; 1616 + position: absolute; 1617 + top: 5px; 1618 + right: 0; 1619 + width: 5px; 1620 + height: 5px; 1621 + content: ''; 1622 + background: #bd9b60; 1623 + -webkit-border-radius: 5px; 1624 + -moz-border-radius: 5px; 1625 + border-radius: 5px; 1626 + } 1627 + 1628 + .ui-datepicker-prev, 1629 + .ui-datepicker-next { 1630 + position: absolute; 1631 + top: 4px !important; 1632 + padding: 5px; 1633 + cursor: pointer; 1634 + } 1635 + 1636 + .ui-datepicker-prev { 1637 + left: 0; 1638 + padding-left: 0; 1639 + } 1640 + 1641 + .ui-datepicker-next { 1642 + right: 0; 1643 + padding-right: 0; 1644 + } 1645 + 1646 + .ui-state-hover { 1647 + background: rgba(255, 255, 255, 0.1) !important; 1648 + } 1695 1649 1696 - .ui-datepicker table { 1697 - margin: 0 auto; 1698 - } 1650 + .ui-datepicker-calendar th { 1651 + padding-top: 15px; 1652 + padding-bottom: 10px; 1653 + text-align: center; 1654 + font-weight: normal; 1655 + color: #a8a8a8; 1656 + font-size: 1rem; 1657 + } 1699 1658 1700 - .ui-datepicker-week-end .ui-state-default { 1701 - background-color: #bd9b60 !important; 1702 - border: 1px solid #bd9b60 !important; 1703 - } 1659 + .ui-datepicker-calendar td { 1660 + padding: 2px 2px; 1661 + text-align: center; 1662 + line-height: 26px; 1663 + } 1664 + 1665 + .ui-datepicker-calendar .ui-state-default { 1666 + display: block; 1667 + width: 100%; 1668 + -webkit-border-radius: 50px; 1669 + -moz-border-radius: 50px; 1670 + border-radius: 50px; 1671 + outline: none; 1672 + text-decoration: none; 1673 + color: #000; 1674 + border: 1px solid transparent; 1675 + } 1676 + 1677 + .ui-datepicker-calendar .ui-state-active { 1678 + border-color: #bd9b60 !important; 1679 + background-color: #bd9b60 !important; 1680 + } 1681 + 1682 + .ui-datepicker-other-month .ui-state-default { 1683 + color: #ccc; 1684 + } 1685 + 1686 + .ui-datepicker-other-month { 1687 + opacity: 0 !important; 1688 + } 1704 1689 1705 - .ui-widget.ui-widget-content { 1706 - border: 1px solid #fff !important; 1707 - max-width: 340px; 1708 - -webkit-border-radius: 20px; 1709 - -moz-border-radius: 20px; 1710 - border-radius: 20px; 1711 - } 1690 + .ui-datepicker table { 1691 + margin: 0 auto; 1692 + } 1712 1693 1713 - .ui-state-default, 1714 - .ui-widget-content .ui-state-default, 1715 - .ui-widget-header .ui-state-default, 1716 - .ui-button, 1717 - html .ui-button.ui-state-disabled:hover, 1718 - html .ui-button.ui-state-disabled:active { 1719 - text-align: center; 1720 - } 1694 + .ui-datepicker-week-end .ui-state-default { 1695 + background-color: #bd9b60 !important; 1696 + border: 1px solid #bd9b60 !important; 1697 + } 1721 1698 1699 + .ui-widget.ui-widget-content { 1700 + border: 1px solid #fff !important; 1701 + max-width: 340px; 1702 + -webkit-border-radius: 20px; 1703 + -moz-border-radius: 20px; 1704 + border-radius: 20px; 1705 + } 1722 1706 1723 - </style> 1707 + .ui-state-default, 1708 + .ui-widget-content .ui-state-default, 1709 + .ui-widget-header .ui-state-default, 1710 + .ui-button, 1711 + html .ui-button.ui-state-disabled:hover, 1712 + html .ui-button.ui-state-disabled:active { 1713 + text-align: center; 1714 + } 1715 + </style> 1724 1716 1725 - {{/partial}} {{> layout/empty}} 1717 + {{/partial}} {{> layout/empty}}