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

Configure Feed

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

feat: register cat

+255 -123
+27 -1
assets/scss/custom/components/_accountsReward.scss
··· 28 28 color: whitesmoke !important; 29 29 pointer-events: none; 30 30 } 31 - input, 31 + input:not([type='radio']), 32 32 select { 33 33 height: 48px; 34 34 border-radius: 32px; ··· 126 126 border-bottom: 1px solid #ddd; 127 127 } 128 128 } 129 + 130 + .cat-birthdays { 131 + display: none; 132 + } 133 + .household-question { 134 + display: none; 135 + font-size: 1.3rem; 136 + color: #687d6a; 137 + } 138 + .household-question button { 139 + font-size: 1rem; 140 + color: initial; 141 + border: 1px solid #687d6a; 142 + padding: 0.5rem 1rem; 143 + margin: 0.5rem; 144 + border-radius: 5px; 145 + transition: background-color 0.2s, color 0.2s; 146 + } 147 + .household-question button:hover { 148 + background-color: #687d6a; 149 + color: white; 150 + } 151 + .birthday-error { 152 + display: none; 153 + color: red; 154 + }
+227 -93
templates/pages/account/inbox.html
··· 19 19 >Register up to 4 cats to receive a 10% discount voucher 20 20 when it's their birthday! The purrfect gift! 21 21 </p> 22 - <div class="reward-form"> 23 - <div> 24 - <label class="form-label" for="reward-cat-name" 25 - >Name</label 26 - > 27 - <input type="text" id="reward-cat-name" /> 28 - </div> 29 - <div> 30 - <label class="form-label" for="reward-cat-sex" 31 - >Sex</label 32 - > 33 - <select name="sex" id="reward-cat-sex"> 34 - <option value="Male">Male</option> 35 - <option value="Female">Female</option> 36 - </select> 37 - </div> 22 + <div class="birthday-error"></div> 23 + <div class="household-question"> 24 + How many cats do you have in your household? 38 25 <div> 39 - <label class="form-label" for="reward-cat-breed" 40 - >Breed</label 41 - > 42 - <input type="text" id="reward-cat-breed" /> 26 + <button onclick="registerOwner(1)"> 1 </button> 27 + <button onclick="registerOwner(2)"> 2 </button> 28 + <button onclick="registerOwner(3)"> 3 </button> 29 + <button onclick="registerOwner(4)"> 4 </button> 43 30 </div> 44 - <div> 45 - <label class="form-label" for="reward-cat-birthday" 46 - >Birthday</label 47 - > 48 - <input 49 - type="text" 50 - id="reward-cat-birthday" 51 - placeholder="DD/MM/YYYY" 52 - maxlength="10" 53 - /> 54 - </div> 55 - <button class="button button--primary">Add Cat</button> 56 31 </div> 57 - <div class="list-of-cats"> 58 - <div class="cat"> 59 - <div class="cat-header">Cat #1</div> 60 - <div class="cat-detail">Name: Josh</div> 61 - <div class="cat-detail">Age: 12</div> 62 - <div class="cat-detail" 63 - >Birthday: 10th of June, 1997</div 64 - > 65 - </div> 66 - <div class="cat"> 67 - <div class="cat-header">Cat #2</div> 68 - <div class="cat-detail">Name: Bella</div> 69 - <div class="cat-detail">Age: 8</div> 70 - <div class="cat-detail" 71 - >Birthday: 22nd of August, 2015</div 72 - > 73 - </div> 74 - <div class="cat"> 75 - <div class="cat-header">Cat #3</div> 76 - <div class="cat-detail">Name: Whiskers</div> 77 - <div class="cat-detail">Age: 4</div> 78 - <div class="cat-detail" 79 - >Birthday: 14th of March, 2019</div 80 - > 81 - </div> 82 - <div class="cat disabled"> 83 - <div class="cat-header">Cat #4</div> 84 - <!-- <div class="cat-detail">Name: --</div> 85 - <div class="cat-detail">Age: -</div> 86 - <div class="cat-detail">Birthday: ----</div> --> 87 - </div> 32 + <div class="cat-birthdays"> 33 + <form id="add-birthday-form"> 34 + <div class="reward-form"> 35 + <div> 36 + <label class="form-label" for="reward-cat-name" 37 + >Name</label 38 + > 39 + <input 40 + type="text" 41 + id="reward-cat-name" 42 + required 43 + minlength="2" 44 + /> 45 + </div> 46 + <div> 47 + <label class="form-label" for="reward-cat-sex" 48 + >Sex</label 49 + > 50 + <select name="sex" id="reward-cat-sex"> 51 + <option value="male">Male</option> 52 + <option value="female">Female</option> 53 + </select> 54 + </div> 55 + <div> 56 + <label class="form-label" for="reward-cat-breed" 57 + >Breed</label 58 + > 59 + <input 60 + type="text" 61 + id="reward-cat-breed" 62 + required 63 + minlength="2" 64 + /> 65 + </div> 66 + <div> 67 + <label 68 + class="form-label" 69 + for="reward-cat-birthday" 70 + >Birthday</label 71 + > 72 + <input 73 + type="date" 74 + id="reward-cat-birthday" 75 + required 76 + /> 77 + </div> 78 + <button 79 + class="button button--primary add-cat-btn" 80 + type="submit" 81 + >Add Cat</button 82 + > 83 + </div> 84 + </form> 85 + 86 + <div class="list-of-cats"> </div> 88 87 </div> 89 88 </div> 90 89 {{/if}} {{#if customer_group_name '===' 'Personal'}} ··· 398 397 </script> 399 398 {{/if}} 400 399 <script> 401 - document.addEventListener('DOMContentLoaded', (event) => { 402 - const dateInput = document.getElementById('reward-cat-birthday'); 403 - if (dateInput) { 404 - dateInput.addEventListener('input', function (e) { 405 - let value = e.target.value.replace(/\D/g, ''); // Remove all non-digit characters 406 - if (value.length > 8) { 407 - value = value.slice(0, 8); // Limit input to 8 digits 408 - } 409 - 410 - // Insert slashes 411 - if (value.length >= 5) { 412 - value = 413 - value.slice(0, 2) + 414 - '/' + 415 - value.slice(2, 4) + 416 - '/' + 417 - value.slice(4, 8); 418 - } else if (value.length >= 3) { 419 - value = value.slice(0, 2) + '/' + value.slice(2, 4); 420 - } else if (value.length >= 1) { 421 - value = value.slice(0, 2); 422 - } 423 - 424 - e.target.value = value; 425 - }); 426 - } 427 - }); 428 - </script> 429 - <script> 430 400 // Append the usePointsDiv to the target element 431 401 function fetchLoyalty() { 432 402 return fetch('/graphql', { ··· 471 441 fetchLoyalty(); 472 442 document.addEventListener('DOMContentLoaded', fetchLoyalty()); 473 443 </script> 474 - {{/partial}} {{> layout/base}} 444 + {{#if customer_group_name '===' 'Testing Group'}} 445 + <script> 446 + const householdQuestionDiv = document.querySelector('.household-question'); 447 + const birthdayErrorDiv = document.querySelector('.birthday-error'); 448 + const birthdayFormDiv = document.querySelector('.reward-form'); 449 + const catListDiv = document.querySelector('.list-of-cats'); 450 + const mainContainer = document.querySelector('.cat-birthdays'); 451 + 452 + let catsInHousehold, catsRegistered, changeSlotAvailable, registeredCats; 453 + 454 + // Call backend to see if customer has registered a cat 455 + fetch( 456 + 'https://e4c7-2a01-4b00-805d-b800-4869-64a3-a1d2-7f3b.ngrok-free.app/getCatOwnerInfo?ownerEmail={{customer.email}}&withCats=true' 457 + ) 458 + .then((response) => { 459 + if (!response.ok) { 460 + if (response.status === 404) { 461 + householdQuestionDiv.style.display = 'block'; 462 + return; 463 + } else { 464 + birthdayErrorDiv.style.display = 'block'; 465 + birthdayErrorDiv.textContent = 466 + 'Error connecting to the server, please try again later.'; 467 + return; 468 + } 469 + } 470 + return response.json(); 471 + }) 472 + .then((data) => { 473 + mainContainer.style.display = 'block'; 474 + householdQuestionDiv.style.display = 'none'; 475 + birthdayErrorDiv.style.display = 'none'; 476 + 477 + catsRegistered = data.cats_registered; 478 + catsInHousehold = data.cats_in_household; 479 + if (catsRegistered >= catsInHousehold) { 480 + birthdayFormDiv.style.display = 'none'; 481 + } 482 + changeSlotAvailable = data.change_slot_available; 483 + registeredCats = data.cats; 484 + 485 + if (catsRegistered === 0) { 486 + catListDiv.textContent = 'No cats registered yet.'; 487 + return; 488 + } 489 + 490 + const catListTitle = document.createElement('h4'); 491 + catListTitle.classList.add('cat-list-title'); 492 + catListTitle.textContent = `Your Registered Cats (${catsRegistered}/${catsInHousehold})`; 493 + catListDiv.appendChild(catListTitle); 494 + catListDiv.appendChild(document.createElement('br')); 495 + 496 + for (const registeredCat of registeredCats) { 497 + const catDiv = document.createElement('div'); 498 + catDiv.classList.add('cat'); 499 + catDiv.innerHTML = ` 500 + <div class="cat-header">${registeredCat.cat_name}</div> 501 + <div class="cat-detail">Breed: ${registeredCat.cat_breed}</div> 502 + <div class="cat-detail">Sex: ${registeredCat.cat_gender}</div> 503 + <div class="cat-detail">Birthday: ${registeredCat.cat_birthday}</div> 504 + `; 505 + catListDiv.appendChild(catDiv); 506 + } 507 + }) 508 + .catch((err) => { 509 + console.error(err); 510 + birthdayErrorDiv.style.display = 'block'; 511 + birthdayErrorDiv.textContent = 512 + 'Error connecting to the server, please try again later.'; 513 + }); 514 + 515 + function registerOwner(householdCats) { 516 + fetch( 517 + `https://e4c7-2a01-4b00-805d-b800-4869-64a3-a1d2-7f3b.ngrok-free.app/registerCatOwner?ownerEmail={{customer.email}}&catsInHousehold=${householdCats}` 518 + ) 519 + .then((response) => { 520 + if (!response.ok) { 521 + birthdayErrorDiv.style.display = 'block'; 522 + birthdayErrorDiv.textContent = 523 + 'Error connecting to the server, please try again later.'; 524 + return; 525 + } 526 + birthdayErrorDiv.style.display = 'none'; 527 + householdQuestionDiv.style.display = 'none'; 528 + document.querySelector('.cat-birthdays').style.display = 529 + 'block'; 530 + return; 531 + }) 532 + .catch((err) => { 533 + console.error(err); 534 + birthdayErrorDiv.style.display = 'block'; 535 + birthdayErrorDiv.textContent = 536 + 'Error connecting to the server, please try again later.'; 537 + return; 538 + }); 539 + } 540 + 541 + const addCatForm = document.querySelector('#add-birthday-form'); 542 + addCatForm.addEventListener('submit', (e) => { 543 + e.preventDefault(); 544 + 545 + const catName = document.querySelector('#reward-cat-name').value; 546 + const catBreed = document.querySelector('#reward-cat-breed').value; 547 + const catGender = document.querySelector('#reward-cat-sex').value; 548 + const catBirthday = document.querySelector( 549 + '#reward-cat-birthday' 550 + ).value; 551 + 552 + if ( 553 + catName.trim() === '' || 554 + catBreed.trim() === '' || 555 + catGender.trim() === '' || 556 + catBirthday.trim() === '' 557 + ) { 558 + birthdayErrorDiv.style.display = 'block'; 559 + birthdayErrorDiv.textContent = 'Please fill in all fields.'; 560 + return; 561 + } 562 + 563 + fetch( 564 + `https://e4c7-2a01-4b00-805d-b800-4869-64a3-a1d2-7f3b.ngrok-free.app/registerCatBirthday?ownerEmail={{customer.email}}&catName=${catName}&catBreed=${catBreed}&catGender=${catGender}&catBirthday=${catBirthday}` 565 + ) 566 + .then(async (response) => { 567 + if (!response.ok) { 568 + const message = await response.text(); 569 + birthdayErrorDiv.style.display = 'block'; 570 + birthdayErrorDiv.textContent = message; 571 + return; 572 + } 573 + birthdayErrorDiv.style.display = 'none'; 574 + const catDiv = document.createElement('div'); 575 + catDiv.classList.add('cat'); 576 + catDiv.innerHTML = ` 577 + <div class="cat-header">${catName}</div> 578 + <div class="cat-detail">Breed: ${catBreed}</div> 579 + <div class="cat-detail">Sex: ${catGender}</div> 580 + <div class="cat-detail">Birthday: ${catBirthday}</div> 581 + `; 582 + catListDiv.appendChild(catDiv); 583 + document.querySelector('#reward-cat-name').value = ''; 584 + document.querySelector('#reward-cat-breed').value = ''; 585 + document.querySelector('#reward-cat-birthday').value = ''; 586 + document.querySelector('#reward-cat-sex').value = ''; 587 + 588 + catsRegistered++; 589 + if (catsRegistered >= catsInHousehold) { 590 + birthdayFormDiv.style.display = 'none'; 591 + } 592 + 593 + document.querySelector( 594 + '.cat-list-title' 595 + ).textContent = `Your Registered Cats (${catsRegistered}/${catsInHousehold})`; 596 + 597 + return; 598 + }) 599 + .catch((err) => { 600 + console.error(err); 601 + birthdayErrorDiv.style.display = 'block'; 602 + birthdayErrorDiv.textContent = 603 + 'Error connecting to the server, please try again later.'; 604 + return; 605 + }); 606 + }); 607 + </script> 608 + {{/if}} {{/partial}} {{> layout/base}}
+1 -29
templates/pages/checkout.html
··· 437 437 }); 438 438 439 439 // ------------------------------------------------------// 440 - const disabledDates = []; // we will need to access this in multiple functions 441 - 442 - // ------------------------------------------------------// 443 440 // This handles 'datepicker' in 'shipping' 444 441 const shippingSelector = '#checkout-shipping-options'; 445 442 ready(shippingSelector, (shippingOptionsElement) => { ··· 476 473 // Create calendar and attach date picker logic here 477 474 let dailyDeliveryLimit = 250; 478 475 const dailySlotValues = {}; 476 + const disabledDates = []; 479 477 480 478 // get delivery dates from middleware 481 479 fetch('https://purrform-apps-027e.onrender.com/deliveryDates') ··· 798 796 const deliveryInstructions = data.customerMessage; 799 797 800 798 if (deliveryInstructions?.trim()) { 801 - // need to check if the date is valid 802 - if (!deliveryInstructions.includes(' | ')) { 803 - missingWarn.textContent = 804 - 'Invalid delivery date. Please edit your shipping details above and select a valid delivery date.'; 805 - missingWarn.style.display = 'block'; 806 - return; 807 - } 808 - 809 - const date = deliveryInstructions.split(' | ')[0]; 810 - if (disabledDates.includes(date)) { 811 - missingWarn.textContent = 812 - 'This delivery date cannot be selected. Please edit your shipping details above and select another delivery date.'; 813 - missingWarn.style.display = 'block'; 814 - return; 815 - } 816 - 817 - // check if the date is in the past 818 - const today = new Date(); 819 - const selectedDate = new Date(date); 820 - if (selectedDate < today) { 821 - missingWarn.textContent = 822 - 'This delivery date is in the past. Please edit your shipping details above and select another delivery date.'; 823 - missingWarn.style.display = 'block'; 824 - return; 825 - } 826 - 827 799 paymentContinueButton.click(); 828 800 } else { 829 801 missingWarn.style.display = 'block';