product.js 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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. // -- update cart icon
  16. updateCartIcon(data);
  17. // -- display product availability
  18. const btnSubmit = document.querySelector('.btn-submit');
  19. const isProductSelectable = data.is_product_selectable;
  20. const isProductAvailable = data.is_product_available;
  21. displayProductSelectable(btnSubmit, isProductSelectable, isProductAvailable);
  22. // -- update URL
  23. updateProductURL(data.product_selected);
  24. });
  25. };
  26. async function checkProductAvailability(product_path, searchParams){
  27. const res = await fetch(`/${product_path}?js=true&${searchParams.toString()}`);
  28. if (res.ok) {
  29. return res.json();
  30. } else {
  31. return {status: res.status, error: res.statusText};
  32. }
  33. };
  34. async function changeProductURLOnInputRadio(form) {
  35. // add on-change listener to all .input-listen input fields
  36. // and update URL accordingly
  37. const inputs = Array.from(form.querySelectorAll('.input-listen'));
  38. await Promise.all(inputs.map(async(input) => {
  39. input.addEventListener('change', async(e) => {
  40. let key = e.target.name;
  41. let value = e.target.value;
  42. if ('URLSearchParams' in window) {
  43. // send request to `/products/<product-id>?<params>`
  44. // to get back an instant result for this and update UI
  45. const product_path = form.querySelector('#product_path').value;
  46. const searchParams = new URLSearchParams(window.location.search);
  47. searchParams.set(key, value);
  48. // update URL only if a key combination of size and style are selected,
  49. // else do nothing — otherwise the item would be seen as sold out.
  50. let size = searchParams.get('size');
  51. let style = searchParams.get('style');
  52. if (size || style) {
  53. const data = await checkProductAvailability(product_path, searchParams);
  54. // -- update product availability
  55. const btnSubmit = document.querySelector('.btn-submit');
  56. const isProductSelectable = data.is_product_selectable;
  57. const isProductAvailable = data.is_product_available;
  58. displayProductSelectable(btnSubmit, isProductSelectable, isProductAvailable);
  59. }
  60. history.pushState(null, '', `?${searchParams.toString()}`);
  61. };
  62. });
  63. }));
  64. }
  65. window.addEventListener('load', () => {
  66. ;(async() => {
  67. const forms = Array.from(document.querySelectorAll('.product-item'));
  68. await Promise.all(forms.map(async(form) => {
  69. processForm(form);
  70. changeProductURLOnInputRadio(form);
  71. }));
  72. })();
  73. });