cart.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. "use strict";
  2. async function updateCart(form) {
  3. // make formData object with data from form
  4. // and send it to backend endpoint to be processed.
  5. // received updated dictionary to use for
  6. // updating DOM.
  7. const formData = new FormData(form);
  8. const res = await fetch("/checkout?js=true", {
  9. method: "POST",
  10. body: formData
  11. });
  12. if (res.ok) {
  13. return res.json();
  14. } else {
  15. return {status: res.status, error: res.statusText};
  16. }
  17. }
  18. function updateCartIcon(data) {
  19. const cart_icon = document.querySelector('.cart-icon');
  20. if (cart_icon.length !== null) {
  21. // update cart amount value
  22. let cart_icon_amount_list = cart_icon.querySelector(".cart-icon--amount");
  23. if (cart_icon_amount_list.length !== null) {
  24. cart_icon_amount_list.innerText = data.cart_breakdown.item_amount;
  25. }
  26. // -- show visual feedback for the cart icon action
  27. cart_icon.dataset.status = 'busy';
  28. cart_icon.style.color = '#FF7070';
  29. cart_icon.style.textDecorationColor = '#FF7070';
  30. setTimeout(() => {
  31. cart_icon.dataset.status = 'free';
  32. cart_icon.style.color = '#fff';
  33. cart_icon.style.textDecorationColor = '#fff';
  34. }, '2000');
  35. }
  36. }
  37. function updateItemRow(item_row, cart_items, item_amount) {
  38. // map over each item in the DOM and check if
  39. // it exists in the cart. update its quantity and total price.
  40. // if item quantity goes down to 0, remove it
  41. // from the DOM.
  42. // Getting the proper item to update on the car page
  43. let item = null;
  44. for (let i = 0; i < cart_items.length; i++) {
  45. if (cart_items[i].product_id == item_row.id) {
  46. if (!cart_items[i].options.product_variation_id || (cart_items[i].options.product_variation_id == item_row.querySelector("#product_id").value)) {
  47. item = cart_items[i];
  48. break;
  49. }
  50. }
  51. }
  52. if (item) {
  53. // update quantity value for input field quantity_manual
  54. item_row.querySelector("#quantity_manual").value = item.quantity;
  55. // check if item has been overbooked and disable + button
  56. // if on the other side, the item quantity has decreased below
  57. // the inventory amount, re-enable the + button
  58. let buttonPlus = item_row.querySelector('#button-plus');
  59. if (!item.is_selectable) {
  60. buttonPlus.setAttribute('disabled', 'disabled');
  61. buttonPlus.classList.add('cura');
  62. } else {
  63. buttonPlus.removeAttribute('disabled');
  64. buttonPlus.classList.remove('cura');
  65. }
  66. // update total
  67. let total = item_row.querySelector('.item-total');
  68. total.querySelector('.item-total--text').textContent = `${item.total}`;
  69. total.querySelector('#price').value = item.total;
  70. } else {
  71. // if item in DOM does not exists in the cart, remove it
  72. item_row.remove();
  73. }
  74. }
  75. function updateBreakdown(cart_breakdown) {
  76. // update checkout's breakdown price
  77. // subtotal + shipping + total
  78. let subtotal_amount = Array.from(document.querySelectorAll('.subtotal--amount > .amount'));
  79. subtotal_amount.forEach(subtotal => {
  80. subtotal.textContent = `${cart_breakdown.subtotal}`;
  81. });
  82. let shipping = document.querySelectorAll('.subtotal--shipping > .amount');
  83. shipping.forEach(shipping => {
  84. shipping.textContent = `${cart_breakdown.shipping.toFixed(1)}`;
  85. });
  86. let subtotal_total = document.querySelector('.subtotal--total > .amount');
  87. if (subtotal_total) {
  88. subtotal_total.textContent = `${cart_breakdown.total.toFixed(1)}`;
  89. };
  90. let weight = document.getElementById("weight");
  91. weight.value = `${cart_breakdown.total_weight}`;
  92. }
  93. function removeCheckoutTable() {
  94. // remove DOM elements that lay out the
  95. // checkout table.
  96. document.querySelector(".checkout-table-header").remove();
  97. document.querySelector(".checkout-shipping-info").remove();
  98. document.querySelector(".checkout-empty-message").classList.remove("dn");
  99. }
  100. function updateTable(cart_items, cart_item_rows, cart_breakdown) {
  101. // map over cart item in the DOM and update them
  102. // update breakdown price if cart item is not empty
  103. // else remove checkout table
  104. cart_item_rows.map(item_row => {
  105. updateItemRow(item_row, cart_items, cart_breakdown['item_amount']);
  106. });
  107. if (cart_items.length > 0) {
  108. updateBreakdown(cart_breakdown);
  109. } else {
  110. removeCheckoutTable();
  111. }
  112. }
  113. function displayProductSelectable(btnSubmit, isProductSelectable, isProductAvailable) {
  114. console.log("displayProductSelectable called with:", {isProductSelectable, isProductAvailable, btnSubmit, value: btnSubmit && btnSubmit.value});
  115. if (!btnSubmit) {
  116. return;
  117. }
  118. btnSubmit.classList.remove('btn-product-available',
  119. 'btn-product-unselectable',
  120. 'btn-product-soldout');
  121. if (!isProductAvailable || !isProductSelectable) {
  122. btnSubmit.setAttribute('disabled', 'disabled');
  123. btnSubmit.classList.add('btn-product-soldout');
  124. btnSubmit.value = "sold out";
  125. } else {
  126. btnSubmit.removeAttribute('disabled');
  127. btnSubmit.classList.add('btn-product-available');
  128. btnSubmit.value = "add to cart";
  129. }
  130. }
  131. function updateProductURL(product_selected) {
  132. if ('URLSearchParams' in window) {
  133. const searchParams = new URLSearchParams(product_selected);
  134. history.pushState(null, '', `?${searchParams.toString()}`);
  135. }
  136. }
  137. export { updateCart, updateCartIcon, updateTable, updateProductURL, displayProductSelectable, updateBreakdown };