-
{{ PRICE }}
@@ -22,7 +20,7 @@ const cardTemplateStr: string = `
-
+
@@ -45,7 +43,7 @@ function createProductImageElement(src: string): HTMLImageElement {
export function createProductCard(
product: Product,
onAddToBasketRequested: (productId: number, requestedQuantity: number) => void,
- onSetProductQuantity: (productId: number, requestedQuantity: number) => void
+ onSetProductQuantity: (productId: number, requestedQuantity: number) => void,
): HTMLDivElement {
const cardHTMLStr = cardTemplateStr
.replaceAll('{{ ID }}', product.id.toString())
@@ -59,68 +57,54 @@ export function createProductCard(
const inputBox = thisProductCard.querySelector('.buyInput') as HTMLInputElement
- inputBox?.addEventListener('change',
- () => {
- if (inputBox.value === "0" || inputBox.value === ""){
- const addToBasketBtn = thisProductCard.querySelector('.addToBasket');
- const adjustDiv = addToBasketBtn!.closest('.shop-product')!.querySelector('.adjustDiv');
- addToBasketBtn!.classList.remove('d-none');
- adjustDiv!.classList.add('d-none');
+ const onInputBoxChanged = () => {
+ if (inputBox.value === '0' || inputBox.value === '') {
+ const addToBasketBtn = thisProductCard.querySelector('.addToBasket') as HTMLDivElement
+ const adjustDiv = addToBasketBtn.nextElementSibling as HTMLDivElement
+ addToBasketBtn.classList.remove('d-none')
+ adjustDiv.classList.add('d-none')
}
- else{
+ else {
onSetProductQuantity(product.id, Number.parseInt(inputBox.value))
}
- })
+ }
- inputBox?.addEventListener('keyup',
- (e) => {
- if (e.key === 'Enter' || e.keyCode === 13){
- if (inputBox.value === "0" || inputBox.value ===""){
- const addToBasketBtn = thisProductCard.querySelector('.addToBasket');
- const adjustDiv = addToBasketBtn!.closest('.shop-product')!.querySelector('.adjustDiv');
- addToBasketBtn!.classList.remove('d-none');
- adjustDiv!.classList.add('d-none');
- }
- else{
- onSetProductQuantity(product.id, Number.parseInt(inputBox.value))
- }
- }
+ inputBox?.addEventListener('change', onInputBoxChanged)
+
+ inputBox?.addEventListener('keyup', (e) => {
+ if (e.key === 'Enter')
+ onInputBoxChanged()
})
-
- thisProductCard.querySelector('.adjustUp')?.addEventListener('click',
- () => {
+
+ thisProductCard.querySelector('.adjustUp')?.addEventListener('click', () => {
onAddToBasketRequested(product.id, 1)
inputBox.value = (Number.parseInt(inputBox.value) + 1).toString()
})
-
-
thisProductCard.querySelector('.adjustDown')?.addEventListener('click', () => {
onAddToBasketRequested(product.id, -1)
const newValue = Number.parseInt(inputBox.value) - 1
inputBox.value = newValue <= 0 ? '1' : newValue.toString()
- if (newValue === 0){
- const addToBasketBtn = thisProductCard.querySelector('.addToBasket');
- const adjustDiv = addToBasketBtn!.closest('.shop-product')!.querySelector('.adjustDiv');
- addToBasketBtn!.classList.remove('d-none');
- adjustDiv!.classList.add('d-none');
+ if (newValue === 0) {
+ const addToBasketBtn = thisProductCard.querySelector('.addToBasket') as HTMLDivElement
+ const adjustDiv = addToBasketBtn.nextElementSibling as HTMLDivElement
+ addToBasketBtn.classList.remove('d-none')
+ adjustDiv.classList.add('d-none')
}
})
thisProductCard.querySelector('.addToBasket')?.addEventListener(
'click',
- function(e) {
+ async (e) => {
onAddToBasketRequested(product.id, 1)
- const addToBasketBtn = e.target as HTMLDivElement;
- const adjustDiv = addToBasketBtn!.closest('.shop-product')!.querySelector('.adjustDiv');
- // window.alert(adjustDiv.classList);
- // window.alert(addToBasketBtn.classList)
- addToBasketBtn.classList.add('d-none');
- adjustDiv!.classList.remove('d-none');
+ const addToBasketBtn = e.target as HTMLButtonElement
+ const adjustDiv = addToBasketBtn.nextElementSibling as HTMLDivElement
+ addToBasketBtn.classList.add('d-none')
+ adjustDiv.classList.remove('d-none')
const newValue = Number.parseInt(inputBox.value)
inputBox.value = newValue <= 0 ? '1' : newValue.toString()
-
- Swal.fire({
+
+ await Swal.fire({
timerProgressBar: true,
icon: 'success',
title: `${product.name} was added to basket.`,
diff --git a/src/js/shop.js b/src/js/shop.js
deleted file mode 100644
index 5b24197..0000000
--- a/src/js/shop.js
+++ /dev/null
@@ -1,318 +0,0 @@
-import { getCookie, initProducts, productDetails, setCookie } from './products.js'
-
-
-let searchStr = ''
-const basket = {}
-// Each product is based on a 'card'; a box that contains information about that product.
-// You can change the card template here. The [EVEGPRODUCT#] will always be subsituted for
-// the element in the imagesArr (see fruit.js)
-// The classes can be styled using CSS
-// The adjustDown and adjustUp buttons have their behaviour specified below, but you can change this if you like
-// To change the quantity of a product, change the value of the input (with the class of buyInput), you can then recalculate the basket with refreshBasket()
-// Or you can adjust the basket object via javascript and call updateQuantityInputs() and refreshBasket()
-const cardTemplate = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
`
-
-
-function init() {
- const toggleButton = document.getElementsByClassName('toggle-button')[0]
- const hero = document.getElementsByClassName('hero')[0]
- const navbarLinks = document.getElementsByClassName('navbar-links')[0]
-
-
- // When the toggle button is pressed (if visible by the screen size, the menu is shown)
- toggleButton.addEventListener('click', () => {
- navbarLinks.classList.toggle('active')
- hero.classList.toggle('menuactive')
- })
-
-
- const searchBar = document.getElementsByClassName('search-bar')[0]
- // Show the search bar when the search link is pressed
- document.getElementById('search-link').addEventListener('click', () => {
- searchBar.classList.toggle('active')
- document.getElementById('searchbox').focus()
- })
-
-
- // Close the search bar
- document.getElementById('searchbutton').addEventListener('click', () => {
- searchStr = document.getElementById('searchbox').value
- redraw()
- })
-
-
- // Close the search bar
- document.getElementById('closesearchbutton').addEventListener('click', () => {
- searchStr = ''
- searchBar.classList.remove('active')
- redraw()
- })
-
-
- // Close the cookies message
- document.getElementById('acceptCookies').addEventListener('click', () => {
- setCookie('cookieMessageSeen', true)
- document.getElementById('cookieMessage').style.display = 'none'
- })
-
-
- if (getCookie('cookieMessageSeen') === 'true')
- document.getElementById('cookieMessage').style.display = 'none'
-
-
- initProducts(redraw)
-}
-
-
-/*
-* When changing the page, you should make sure that each adjust button has exactly one click event
-* (otherwise it might trigger multiple times)
-* So this function loops through each adjustment button and removes any existing event listeners
-* Then it adds another event listener
-*/
-function resetListeners() {
- let elements = document.getElementsByClassName('adjustUp')
- let eIn
- for (eIn = 0; eIn < elements.length; eIn++) {
- elements[eIn].removeEventListener('click', increment)
- elements[eIn].addEventListener('click', increment)
- }
- elements = document.getElementsByClassName('adjustDown')
- for (eIn = 0; eIn < elements.length; eIn++) {
- elements[eIn].removeEventListener('click', decrement)
- elements[eIn].addEventListener('click', decrement)
- }
- elements = document.getElementsByClassName('buyInput')
- for (eIn = 0; eIn < elements.length; eIn++) {
- elements[eIn].removeEventListener('change', inputchange)
- elements[eIn].addEventListener('change', inputchange)
- }
- elements = document.getElementsByClassName('addToBasket')
- for (eIn = 0; eIn < elements.length; eIn++) {
- elements[eIn].removeEventListener('click', increment)
- elements[eIn].addEventListener('click', increment)
- }
-}
-
-
-// When the input changes, add a 'bought' class if more than one is added
-function inputchange(ev) {
- const thisID = ev.target.parentElement.closest('.card__content').getAttribute('data-num')
- changeQuantity(thisID, ev.target.parentElement.closest('.shop-product-buying').getElementsByTagName('input')[0].value)
-}
-
-
-/*
-* Change the quantity of the product with productID
-*/
-function changeQuantity(productID, newQuantity) {
- basket[productID] = newQuantity
- if (newQuantity === 0)
- delete basket[productID]
- document.querySelector(`.buyInput[data-num='${productID}']`).value = newQuantity
- refreshBasket()
-}
-
-
-// Add 1 to the quantity
-function increment(ev) {
- const thisID = ev.target.parentElement.closest('.card__content').getAttribute('data-num')
- if (basket[thisID] === undefined)
- basket[thisID] = 0
-
-
- changeQuantity(thisID, Number.parseInt(basket[thisID]) + 1)
-}
-
-
-// Subtract 1 from the quantity
-function decrement(ev) {
- const thisID = ev.target.parentElement.closest('.card__content').getAttribute('data-num')
- if (basket[thisID] === undefined) {
- changeQuantity(thisID, 0)
- }
- else {
- if (basket[thisID] > 0)
- changeQuantity(thisID, Number.parseInt(basket[thisID]) - 1)
- }
-}
-
-
-function filterFunction(a) {
- /* This demonstrates how to filter based on the search term */
- return a.name.toLowerCase().includes(searchStr.toLowerCase())
-
-
- // If you wanted to just filter based on fruit/veg you could do something like this:
- // return a.type == 'veg';
- // return a.type == 'fruit';
- // return true;
-}
-
-
-function sortFunction(a, b) {
- return a.price > b.price
-}
-
-
-// Redraw all products based on the card template
-function redraw() {
- // Reset the product list (there are possibly more efficient ways of doing this, but this is simplest)
- document.querySelector('.productList').innerHTML = ''
-
-
- const shownProducts = productDetails.filter(filterFunction)
-
-
- shownProducts.sort(sortFunction)
-
-
- const numProducts = shownProducts.length
-
-
- for (let i = 0; i < numProducts; i++) {
- const cardHTML = cardTemplate.replaceAll('[EVEGPRODUCT#]', shownProducts[i].productID)
- const thisProduct = document.createElement('div')
- thisProduct.innerHTML = cardHTML
- document.querySelector('.productList').appendChild(thisProduct.firstChild)
- }
-
-
- document.querySelectorAll('.shop-product-details').forEach((element) => {
- const field = element.getAttribute('data-field')
- const num = element.getAttribute('data-num')
- switch (field) {
- case 'title':
- element.textContent = productDetails[num].name
- break
- case 'img':
- element.innerHTML = `

`
- break
- case 'weight':
- element.innerHTML = `
${productDetails[num].weight}
`
- break
- case 'price':
- element.innerHTML = `
£${(productDetails[num].price / 100).toFixed(2)}`
- break
- case 'units':
- element.innerHTML = `
${productDetails[num].packsize}/${productDetails[num].units}`
- break
- }
- })
- resetListeners()
- updateQuantityInputs()
-}
-
-
-document.addEventListener('DOMContentLoaded', () => {
- init();
-
-
- // Add event listener to toggle visibility
- document.querySelectorAll('.addToBasket').forEach((addToBasketBtn) => {
- addToBasketBtn.addEventListener('click', function () {
-
- const addToBasketBtn = this;
- const adjustDiv = addToBasketBtn.closest('.shop-product').querySelector('.adjustDiv');
- // window.alert(adjustDiv.classList);
- // window.alert(addToBasketBtn.classList)
- addToBasketBtn.classList.add('hidden');
- adjustDiv.classList.remove('hidden');
- // window.alert(adjustDiv.classList);
- // window.alert(addToBasketBtn.classList);
- });
- });
-
-
- document.querySelectorAll('.buyInput').forEach((buyInput) => {
- buyInput.addEventListener('change', function (event) {
- const currentValue = event.target.value;
- const addInput = this;
- const button = addInput.closest('.shop-product').querySelector('.addToBasket');
- const trio = addInput.closest('.shop-product').querySelector('.adjustDiv');
- if (Number(currentValue) === 0) {
- // window.alert(button.classList)
- // window.alert(trio.classList)
- trio.classList.add('hidden');
- button.classList.remove('hidden');
- // window.alert(button.classList)
- // window.alert(trio.classList)
- }
- // else {
- // addInput.classList.add('hidden');
- // adjustDiv.classList.remove('hidden');
- // }
-
-
- const thisID = this.getAttribute('data-num');
- changeQuantity(thisID, currentValue);
- });
- });
-
-
- document.querySelectorAll('.btn').forEach((adjustBtn) => {
- adjustBtn.addEventListener('click', function () {
- const button = this.closest('.shop-product').querySelector('.addToBasket');
- const adjustDiv = this.closest('.shop-product').querySelector('.adjustDiv');
- window.alert(Number(button.querySelector('.buyInput').value));
- if (Number(button.querySelector('.buyInput').value) === 0) {
- button.classList.remove('hidden');
- adjustDiv.classList.add('hidden');
- }
- });
- });
-});
-
-
-function updateQuantityInputs() {
- for (const buyInput of document.querySelectorAll('.buyInput')) {
- let quantity = basket[buyInput.getAttribute('data-num')]
- if (Number.isNaN(quantity))
- quantity = 0
-
-
- buyInput.value = quantity
- }
-}
-
-
-// Recalculate basket
-function refreshBasket() {
- let total = 0
- for (const productID in basket) {
- const quantity = basket[productID]
- const price = productDetails[productID].price
- total = total + (price * quantity)
- }
- setCookie('basket', JSON.stringify(basket))
- try {
- document.querySelector('#basketNumTotal').innerHTML = (total / 100).toFixed(2)
- }
- catch (e) {
-
-
- }
- return total
-}
-
-
-
diff --git a/src/js/shop.ts b/src/js/shop.ts
index 37b04a8..7edc9a5 100644
--- a/src/js/shop.ts
+++ b/src/js/shop.ts
@@ -73,7 +73,6 @@ function onAddToBasketClicked(productId: number, requestedQuantity: number) {
else
basket.set(productId, newQuantity)
- console.log(basket);
Cookies.set('basket', JSON.stringify(Object.fromEntries(basket)), cookieOptions)
}
@@ -83,11 +82,9 @@ function onSetProductQuantity(productId: number, requestedQuantity: number) {
else
basket.set(productId, requestedQuantity)
- console.log(basket);
Cookies.set('basket', JSON.stringify(Object.fromEntries(basket)), cookieOptions)
}
-
function onSearchSubmitted() {
const productContainer = document.querySelectorAll('.productList > .shop-product.card')
// toggle visibility of product cards in the productContainer based on search string
@@ -146,7 +143,6 @@ async function asyncMakeProductCardElements() {
if (result.status === 'fulfilled')
return result.value
- console.error(result.reason)
return document.createElement('div')
}))
}