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;
 | 
						|
}
 |