product.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import { updateCart,
  2. updateCartIcon,
  3. updateTable,
  4. updateProductURL,
  5. displayProductSelectable } from './cart.js';
  6. async function processForm(form) {
  7. // handle form by preventing default behaviour
  8. // and instead manipulate data appropriately:
  9. // - send form to backend via POST
  10. // - receive response and update DOM w/o hard-refresh
  11. form.addEventListener('submit', async(e) => {
  12. e.preventDefault();
  13. // -- update form data
  14. const data = await updateCart(form);
  15. console.log("AJAX response from /checkout:", data);
  16. // -- update cart icon
  17. updateCartIcon(data);
  18. // -- display product availability
  19. const btnSubmit = form.querySelector('.btn-submit');
  20. const isProductSelectable = data.is_product_selectable;
  21. const isProductAvailable = data.is_product_available;
  22. displayProductSelectable(btnSubmit, isProductSelectable, isProductAvailable);
  23. console.log("displayProductSelectable called with:", isProductSelectable, isProductAvailable);
  24. // -- update URL
  25. updateProductURL(data.product_selected);
  26. });
  27. };
  28. async function checkProductAvailability(product_path, searchParams){
  29. const res = await fetch(`/${product_path}?js=true&${searchParams.toString()}`);
  30. if (res.ok) {
  31. return res.json();
  32. } else {
  33. return {status: res.status, error: res.statusText};
  34. }
  35. };
  36. async function changeProductURLOnInputRadio(form) {
  37. // add on-change listener to all .input-listen input fields
  38. // and update URL accordingly
  39. const inputs = Array.from(form.querySelectorAll('.input-listen'));
  40. await Promise.all(inputs.map(async(input) => {
  41. input.addEventListener('change', async(e) => {
  42. let key = e.target.name;
  43. let value = e.target.value;
  44. if ('URLSearchParams' in window) {
  45. // send request to `/products/<product-id>?<params>`
  46. // to get back an instant result for this and update UI
  47. const product_path = form.querySelector('#product_path').value;
  48. const searchParams = new URLSearchParams(window.location.search);
  49. searchParams.set(key, value);
  50. // update URL only if a key combination of size and style are selected,
  51. // else do nothing — otherwise the item would be seen as sold out.
  52. let size = searchParams.get('size');
  53. let style = searchParams.get('style');
  54. if (size || style) {
  55. const data = await checkProductAvailability(product_path, searchParams);
  56. // -- update product availability
  57. const btnSubmit = form.querySelector('.btn-submit');
  58. const isProductSelectable = data.is_product_selectable;
  59. const isProductAvailable = data.is_product_available;
  60. displayProductSelectable(btnSubmit, isProductSelectable, isProductAvailable);
  61. }
  62. history.pushState(null, '', `?${searchParams.toString()}`);
  63. };
  64. });
  65. }));
  66. }
  67. window.addEventListener('load', () => {
  68. ;(async() => {
  69. const forms = Array.from(document.querySelectorAll('.product-item'));
  70. await Promise.all(forms.map(async(form) => {
  71. processForm(form);
  72. changeProductURLOnInputRadio(form);
  73. }));
  74. })();
  75. });