diff --git a/src/convertColours.html b/src/convertColours.html index 3f886e9..09d05ba 100644 --- a/src/convertColours.html +++ b/src/convertColours.html @@ -26,7 +26,6 @@ document.getElementById('cssResult').value = str; } catch (e) { alert(e); - console.log(e); } } diff --git a/src/js/productCard.ts b/src/js/productCard.ts index 5ecef37..a55a58d 100644 --- a/src/js/productCard.ts +++ b/src/js/productCard.ts @@ -2,14 +2,12 @@ import Swal from 'sweetalert2' import type { Product } from './typing.ts' const cardTemplateStr: string = ` -
-
-
+
+

{{ TITLE }}

- {{ 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') })) }