478 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			478 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| const cache = {
 | |
|   basket: [],
 | |
|   shopItems: [],
 | |
|   totalCheckout: 0,
 | |
|   inCheckout: false,
 | |
|   paymentOption: null,
 | |
|   useBlackMoney: false,
 | |
|   texts: {}
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Opens the menu UI and initializes the shop state.
 | |
|  * @function openMenu
 | |
|  * @param {object[]} shopItems - Array of shop items to display.
 | |
|  * @param {string} shopName - The name of the shop.
 | |
|  * @param {string[]} categories - List of categories to display.
 | |
|  * @param {boolean} useBlackMoney - Whether or not to use black money.
 | |
|  */
 | |
| function openMenu(shopItems, shopName, categories, useBlackMoney) {
 | |
|   // Display the UI
 | |
|   $(".ui").fadeIn();
 | |
| 
 | |
|   // Set the shop title
 | |
|   $("#shopTitle").html(shopName);
 | |
| 
 | |
|   // Setup categories, items, and search functionality
 | |
|   setupCategories(categories);
 | |
|   setupShopItems(shopItems);
 | |
|   setupSearch(shopItems);
 | |
| 
 | |
|   // Initialize cache values
 | |
|   cache.useBlackMoney = useBlackMoney;
 | |
|   cache.inCheckout = false;
 | |
| 
 | |
|   // Clear the basket
 | |
|   clearBasket();
 | |
| 
 | |
|   // Show "No products added" message if the basket is empty
 | |
|   if (!cache.basket.length) $("#noProductsAdded").fadeIn();
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Sets up the categories in the shop.
 | |
|  * @function setupCategories
 | |
|  * @param {string[]} categories - The list of categories to display.
 | |
|  */
 | |
| function setupCategories(categories) {
 | |
|   // Get the shop categories container
 | |
|   const shopCategories = $("#shopCategorys");
 | |
| 
 | |
|   // Clear any existing categories
 | |
|   shopCategories.html("");
 | |
| 
 | |
|   // Add the "All" category with a reset function
 | |
|   shopCategories.append(`
 | |
|     <div class="shopCategory" id="category-all" onclick="resetCategory()">All</div>
 | |
|   `);
 | |
| 
 | |
|   // Iterate over each category in the categories list
 | |
|   categories.forEach((category) => {
 | |
|     const categoryID = `category-${category}`;
 | |
| 
 | |
|     // Append each category to the shop categories container
 | |
|     shopCategories.append(`
 | |
|       <div class="shopCategory" id="${categoryID}">${category}</div>
 | |
|     `);
 | |
| 
 | |
|     // Add a click event listener to each category
 | |
|     $(`#${categoryID}`).click(() => {
 | |
|       if (!cache.inCheckout) searchByCategory(category);
 | |
|     });
 | |
|   });
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Filters the shop items by category.
 | |
|  * @function searchByCategory
 | |
|  * @param {string} category The category to filter by.
 | |
|  */
 | |
| function searchByCategory(category) {
 | |
|   // Remove the active class from all categories
 | |
|   $(".shopCategory").removeClass("active");
 | |
|   
 | |
|   // Add the active class to the selected category
 | |
|   $(`#category-${category}`).addClass("active");
 | |
| 
 | |
|   // Loop through the shop items and show/hide based on the category
 | |
|   cache.shopItems.forEach((shopItem) => {
 | |
|       const shopItemElement = $(`#shopItem-${shopItem.itemID}`);
 | |
|       
 | |
|       // If the item matches the category, show it, otherwise hide it
 | |
|       if (shopItem.itemCategory === category) {
 | |
|           shopItemElement.show();
 | |
|       } else {
 | |
|           shopItemElement.hide();
 | |
|       }
 | |
|   });
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Resets the shop categories to show all items.
 | |
|  * @function resetCategory
 | |
|  */
 | |
| function resetCategory() {
 | |
|   // Remove the active class from all categories
 | |
|   $(".shopCategory").removeClass("active");
 | |
|   
 | |
|   // Add the active class to the 'All' category
 | |
|   $("#category-all").addClass("active");
 | |
| 
 | |
|   // Show all shop items
 | |
|   cache.shopItems.forEach((shopItem) => {
 | |
|       $(`#shopItem-${shopItem.itemID}`).show();
 | |
|   });
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Sets up the shop items container.
 | |
|  * @function setupShopItems
 | |
|  * @param {object[]} shopItems - The shop items.
 | |
|  */
 | |
| function setupShopItems(shopItems) {
 | |
|   const shopItemsContainer = $("#shopItems");
 | |
|   shopItemsContainer.html("");
 | |
|   cache.shopItems = shopItems;
 | |
| 
 | |
|   // Loop through the shop items
 | |
|   shopItems.forEach((shopItem) => {
 | |
|     const shopItemID = `shopItem-${shopItem.itemID}`;
 | |
|     // Check if the item is already in the container
 | |
|     if (!$(`#${shopItemID}`).hasClass('item-set')) {
 | |
|       // Add the item to the container
 | |
|       shopItemsContainer.append(`
 | |
|         <div class="shopItem vov fade-in infinite item-set" id="${shopItemID}">
 | |
|           <div class="shopItem-Header">${shopItem.itemPrice}$</div>
 | |
|           <div class="shopItem-Image">
 | |
|             <img src="assets/${shopItem.itemImage}" />
 | |
|           </div>
 | |
|           <div class="shopItem-Footer" style="margin-left: 40px; margin-top: 35px">${shopItem.itemLabel}</div>
 | |
|         </div>
 | |
|       `);
 | |
| 
 | |
|       // Add a click event to the item
 | |
|       $(`#${shopItemID}`).click(() => {
 | |
|         // Check if we are not in the checkout
 | |
|         if (!cache.inCheckout) {
 | |
|           // Add the item to the basket
 | |
|           addToBasket(shopItem);
 | |
|         }
 | |
|       });
 | |
|     }
 | |
|   });
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * Adds an item to the basket.
 | |
|  * @function addToBasket
 | |
|  * @param {object} shopItem - The shop item to add.
 | |
|  */
 | |
| function addToBasket(shopItem) {
 | |
|   // Hide the "No products added" message
 | |
|   $("#noProductsAdded").hide();
 | |
|   
 | |
|   // Search the shop item in the basket
 | |
|   let searchShopItem = cache.basket.find((product) => product.itemID === shopItem.itemID);
 | |
| 
 | |
|   // If the item is already in the basket, increase the quantity
 | |
|   if (searchShopItem) {
 | |
|     searchShopItem.itemQuantity++;
 | |
|     searchShopItem.itemTotal += shopItem.itemPrice;
 | |
| 
 | |
|     // Update the UI
 | |
|     updateBasketItemUI(searchShopItem);
 | |
|   } else {
 | |
|     // If the item is not in the basket, add it
 | |
|     searchShopItem = Object.assign({}, shopItem, {
 | |
|       itemQuantity: 1,
 | |
|       itemTotal: shopItem.itemPrice,
 | |
|     });
 | |
| 
 | |
|     // Add the item to the basket
 | |
|     cache.basket.push(searchShopItem);
 | |
| 
 | |
|     // Append the item to the basket UI
 | |
|     appendBasketItemUI(shopItem);
 | |
|   }
 | |
|   // Update the total checkout price
 | |
|   updateTotalCheckout(shopItem.itemPrice);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Updates the quantity and price of a basket item in the UI.
 | |
|  * @function updateBasketItemUI
 | |
|  * @param {object} item - The item to update.
 | |
|  */
 | |
| function updateBasketItemUI(item) {
 | |
|   // Update the quantity
 | |
|   $(`#basketItem-Quantity-${item.itemID}`).html(`x${item.itemQuantity}`);
 | |
| 
 | |
|   // Update the price
 | |
|   $(`#basketItem-Price-${item.itemID}`).html(`${item.itemTotal}$`);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Appends a new item to the basket UI.
 | |
|  * @function appendBasketItemUI
 | |
|  * @param {object} shopItem - The shop item to append.
 | |
|  */
 | |
| function appendBasketItemUI(shopItem) {
 | |
|   const backgroundStyle = cache.useBlackMoney ? "rgba(255, 84, 84, 0.7)" : "rgba(56, 168, 5, 0.71)";
 | |
|   $("#basketItems").append(`
 | |
|     <div class="basketItem vov slide-in-up infinite" id="basketItem-${shopItem.itemID}">
 | |
|       <div class="basketItem-Image"><img src="assets/${shopItem.itemImage}" /></div>
 | |
|       <div class="basketItem-header">${shopItem.itemLabel}<span id="basketItem-Quantity-${shopItem.itemID}" style="margin-left: 5px;">x1</span></div>
 | |
|       <div class="basketItem-footer"><span style="background: ${backgroundStyle}" id="basketItem-Price-${shopItem.itemID}">${shopItem.itemPrice}$</span></div>
 | |
|     </div>
 | |
|   `);
 | |
| 
 | |
|   // Add event listeners to the basket item
 | |
|   $(`#basketItem-${shopItem.itemID}`).click(() => {
 | |
|     if (!cache.inCheckout) removeFromBasket(shopItem);
 | |
|   });
 | |
| 
 | |
|   $(`#basketItem-${shopItem.itemID}`).on("contextmenu", (e) => {
 | |
|     if (!cache.inCheckout) removeFromBasketCompletamente(shopItem);
 | |
|   });
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Removes all items of a given shop item from the basket.
 | |
|  * @function removeFromBasketCompletamente
 | |
|  * @param {object} shopItem - The shop item to remove.
 | |
|  *
 | |
|  * This function removes all items of the given shop item from the basket.
 | |
|  * It also updates the total checkout price and removes the item from the UI.
 | |
|  */
 | |
| function removeFromBasketCompletamente(shopItem) {
 | |
|   // Find the item in the basket
 | |
|   const basketItem = cache.basket.find(item => item.itemID === shopItem.itemID);
 | |
| 
 | |
|   if (basketItem) {
 | |
|     // Update the total checkout price
 | |
|     updateTotalCheckout(-basketItem.itemTotal);
 | |
| 
 | |
|     // Remove the item from the basket
 | |
|     cache.basket = cache.basket.filter(item => item.itemID !== shopItem.itemID);
 | |
| 
 | |
|     // Remove the item from the UI
 | |
|     $(`#basketItem-${shopItem.itemID}`).remove();
 | |
| 
 | |
|     // Check if the basket is empty
 | |
|     if (cache.basket.length === 0) {
 | |
|       // Show the "No products added" message
 | |
|       $("#noProductsAdded").fadeIn();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| function updateTotalCheckout(amount) {
 | |
|   cache.totalCheckout += amount;
 | |
|   $("#totalcheckout").html(`${cache.totalCheckout}$`);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Removes one item from the basket.
 | |
|  * @function removeFromBasket
 | |
|  * @param {object} shopItem - The shop item to remove.
 | |
|  */
 | |
| function removeFromBasket(shopItem) {
 | |
|   // Search the shop item in the basket
 | |
|   const searchShopItem = cache.basket.find((product) => product.itemID === shopItem.itemID);
 | |
| 
 | |
|   if (searchShopItem) {
 | |
|     // Decrease the item quantity
 | |
|     searchShopItem.itemQuantity--;
 | |
|     // Decrease the item total price
 | |
|     searchShopItem.itemTotal -= shopItem.itemPrice;
 | |
|     // Update the UI
 | |
|     updateBasketItemUI(searchShopItem);
 | |
| 
 | |
|     // If the item quantity is 0, remove it from the basket
 | |
|     if (searchShopItem.itemQuantity === 0) {
 | |
|       cache.basket = cache.basket.filter(item => item.itemID !== shopItem.itemID);
 | |
|       // Remove the item HTML element
 | |
|       $(`#basketItem-${shopItem.itemID}`).remove();
 | |
|     }
 | |
|     // Update the total checkout price
 | |
|     updateTotalCheckout(-shopItem.itemPrice);
 | |
| 
 | |
|     // If the total checkout price is 0, show the "No products added" message
 | |
|     if (cache.totalCheckout === 0) {
 | |
|       $("#noProductsAdded").fadeIn();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Proceeds to checkout.
 | |
|  * @function proceedCheckout
 | |
|  */
 | |
| function proceedCheckout() {
 | |
|   // Check if the total checkout amount is greater than 0
 | |
|   if (cache.totalCheckout > 0) {
 | |
|     // If it is, toggle the checkout state
 | |
|     toggleCheckoutState();
 | |
|   } else {
 | |
|     // If it is not, flash a message indicating that there are no products added to the basket
 | |
|     flashNoProductsMessage();
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Toggles the checkout mode.
 | |
|  * @function toggleCheckoutState
 | |
|  */
 | |
| function toggleCheckoutState() {
 | |
|   // If we are currently in checkout mode, exit it
 | |
|   if (cache.inCheckout) {
 | |
|     exitCheckoutMode();
 | |
|   } 
 | |
|   // If we are not in checkout mode, enter it
 | |
|   else {
 | |
|     enterCheckoutMode();
 | |
|   }
 | |
|   
 | |
|   // Toggle the boolean value
 | |
|   cache.inCheckout = !cache.inCheckout;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Enters the checkout mode.
 | |
|  * @function enterCheckoutMode
 | |
|  */
 | |
| function enterCheckoutMode() {
 | |
|   // Clear the HTML of the more-btns element
 | |
|   $("#more-btns").html("");
 | |
|   // Get the current date
 | |
|   const date = Date.now();
 | |
|   // Declare the button template
 | |
|   const btnTemplate = cache.useBlackMoney ? ["blackmoney"] : ["cash", "bank"];
 | |
|   
 | |
|   // Loop through the button template and create a new button for each type
 | |
|   btnTemplate.forEach(type => {
 | |
|     // Append the button template to the more-btns element
 | |
|     $("#more-btns").append(`
 | |
|       <button class="shopButtonCheckout-Btn vov slide-in-left infinite" id="${type}-${date}" style="width: 10%; height: 70px; display: none;">
 | |
|         <i class="bi bi-${type === "blackmoney" ? "cash-stack" : "credit-card"}" style="font-size: 1.7em; color: ${type === "blackmoney" ? "rgba(255, 84, 84, 0.7)" : "inherit"};"></i>
 | |
|       </button>
 | |
|     `);
 | |
|     // Show the button and add a click event to it
 | |
|     $(`#${type}-${date}`).show().click(() => submitCheckout(type));
 | |
|   });
 | |
| 
 | |
|   // Set the opacity of the UI elements to 0.5
 | |
|   setUIOpacity(0.5);
 | |
|   // Show the more-btns element
 | |
|   $("#more-btns").show();
 | |
|   // Update the text of the checkout button
 | |
|   $("#checkout").html('CANCEL');
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Exits the checkout mode.
 | |
|  * @function exitCheckoutMode
 | |
|  */
 | |
| function exitCheckoutMode() {
 | |
|   // Reset the opacity of the UI elements
 | |
|   setUIOpacity(1);
 | |
|   // Reset the text of the checkout button
 | |
|   $("#checkout").html('CHECKOUT');
 | |
|   // Hide the additional buttons
 | |
|   $("#more-btns").hide();
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Sets the opacity of the UI elements to the given value.
 | |
|  * @param {number} opacity the opacity value (between 0 and 1)
 | |
|  */
 | |
| function setUIOpacity(opacity) {
 | |
|   // Set the opacity of the shop categories, shop items, basket items, and clear basket button
 | |
|   $("#shopCategorys, #shopItems, #basketItems, #shopSearch-ClearBasket").css("opacity", opacity);
 | |
| }
 | |
| 
 | |
| let checkoutSent = false;
 | |
| /**
 | |
|  * Submits the checkout to the server.
 | |
|  * @param {string} paymentType the type of payment used (cash, bank, blackmoney)
 | |
|  */
 | |
| function submitCheckout(paymentType) {
 | |
|   // Prevent the checkout from being sent multiple times
 | |
|   if (checkoutSent) return;
 | |
|   checkoutSent = true;
 | |
| 
 | |
|   $.post(`http://${GetParentResourceName()}/goToCheckout`, JSON.stringify({
 | |
|     // Total amount to be paid
 | |
|     totalPayment: cache.totalCheckout,
 | |
|     // Items in the basket
 | |
|     basket: cache.basket,
 | |
|     // Type of payment used
 | |
|     paymentType,
 | |
|     // Whether or not to use black money
 | |
|     useBlackMoney: cache.useBlackMoney
 | |
|   }));
 | |
| 
 | |
|   // Close the menu after checkout
 | |
|   closeMenu();
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Flashes a message indicating that there are no products added to the basket.
 | |
|  * Temporarily changes the color of the "no products" text to red and then reverts it to white.
 | |
|  */
 | |
| function flashNoProductsMessage() {
 | |
|   const noProductsText = $("#noProductsAdded-Text");
 | |
|   // Change text color to red
 | |
|   noProductsText.css("color", "red");
 | |
|   // Revert text color to white after 100 milliseconds
 | |
|   setTimeout(() => noProductsText.css("color", "white"), 100);
 | |
| }
 | |
| 
 | |
| function setupSearch(shopItems) {
 | |
|   const searchInput = $("#shopSearch-Input");
 | |
| 
 | |
|   searchInput.on("input", () => {
 | |
|     const searchValue = searchInput.val().toLowerCase();
 | |
| 
 | |
|     shopItems.forEach(({ itemID, itemLabel }) => {
 | |
|       const shouldDisplay = itemLabel.toLowerCase().startsWith(searchValue);
 | |
|       $(`#shopItem-${itemID}`).toggle(shouldDisplay);
 | |
|     });
 | |
|   });
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Clear the basket and reset the total checkout amount.
 | |
|  */
 | |
| function clearBasket() {
 | |
|   // Clear the basket.
 | |
|   cache.basket = [];
 | |
| 
 | |
|   // Reset the total checkout amount.
 | |
|   cache.totalCheckout = 0;
 | |
| 
 | |
|   // Clear the basket items UI.
 | |
|   $("#basketItems").html('');
 | |
| 
 | |
|   // Show the "no products added" message.
 | |
|   $("#noProductsAdded").fadeIn();
 | |
| 
 | |
|   // Reset the total checkout label.
 | |
|   $("#totalcheckout").html(`0$`);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Close the menu and reset the shop state.
 | |
|  */
 | |
| function closeMenu() {
 | |
|   // Notify the server that the menu was closed.
 | |
|   $.post(`http://${GetParentResourceName()}/CloseMenu`, JSON.stringify({}));
 | |
| 
 | |
|   // Reset the state of the shop.
 | |
|   cache.basket = []; // empty the basket
 | |
|   cache.shopItems = []; // remove all shop items
 | |
|   cache.totalCheckout = 0; // reset the total checkout amount
 | |
|   cache.inCheckout = false; // exit checkout mode
 | |
|   cache.useBlackMoney = false; // disable black money
 | |
| 
 | |
|   // Reset the UI
 | |
|   setUIOpacity(1); // set the opacity of the UI to 1
 | |
|   $("#checkout").html('CHECKOUT'); // reset the text of the checkout button
 | |
|   $(".shopButtonCheckout-Btn").hide(); // hide the checkout button
 | |
|   $("#totalcheckout").html(`0$`); // reset the total checkout label
 | |
|   $("#checkout").show(); // show the checkout button
 | |
| 
 | |
|   // Reset the checkout sent flag
 | |
|   checkoutSent = false;
 | |
| }
 | 
