diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..eb7cacf3a --- /dev/null +++ b/docs/README.md @@ -0,0 +1,50 @@ +

+ +

+

자판기

+ +## 요구사항 +> 각 탭에 따라 적절한 기능을 수행할 수 있도록 구현한다. + +### 상품 관리 탭 +> 사용자는 자판기가 보유하고 있는 상품을 확인하고 추가할 수 있어야한다. + +- [x] 상품 관리 화면을 생성한다. +- [x] 상품명, 가격, 수량을 입력해 상품을 추가할 수 있다. +- [x] 상품 가격은 100원부터 시작하며 10원으로 나누어 떨어져야 한다. +- [x] 사용자는 추가한 상품을 확인할 수 있다. + +### 잔돈 충전 탭 +> 사용자는 자판기의 보유 금액을 확인하고 추가할 수 있어야한다. + +- [x] 잔돈 충전 화면을 생성한다. +- [x] 잔돈 충전 입력 요소에 금액을 입력 후, `충전하기` 버튼을 눌러 보유 금액을 충전할 수 있다. +- [x] 자판기 보유 금액만큼의 동전이 무작위로 생성된다. +- [x] 자판기가 이미 금액을 보유하고 있다면, 추가 금액 만큼의 동전을 생성하여 누적한다. +- [x] 사용자가 현재 동전의 개수를 확인할 수 있도록 화면을 업데이트 한다. + +- 단, 동전 생성은 `MissionUtils` 라이브러리의 `Random.pickNumberInList`를 사용해 구한다. +```js +Random.pickNumberInList([1, 3, 10]); // 1 +``` + +### 상품 구매 탭 +> 사용자는 자판기에서 상품을 구매하고, 잔돈을 반환 받을 수 있다. + +- [x] 상품 구매 화면을 생성한다. +- [x] 사용자는 투입할 금액을 입력한 후, `투입하기` 버튼을 눌러 금액을 투입할 수 있다. +- [x] 사용자는 금액을 여러 번 누적해서 투입할 수 있다. +- [x] 사용자는 `구매하기` 버튼을 눌러 상품을 구매할 수 있다. +- [x] 사용자는 `반환하기` 버튼을 눌러 잔돈을 반환 받을 수 있다. + +**반환 시 유의사항** +- 잔돈은 자판기가 가진 동전 중 최소 개수의 동전으로 반환한다. +- 지폐를 잔돈으로 반환하는 경우는 없다. +- 잔돈을 반환할 수 없는 경우 반환할 수 있는 만큼만 반환한다. + +### 공통 +> 상단의 탭 메뉴가 존재하며, 각 탭에 따라 적절한 기능을 수행해야 한다. + +- [x] 페이지 상단의 탭 메뉴를 생성한다. +- [x] 각 탭의 기능이 표시될 요소를 생성한다. +- [x] `localStorage`를 이용하여, 새로고침하더라도 가장 최근에 작업한 정보들을 불러올 수 있도록 한다. diff --git a/index.html b/index.html index 399816a6d..93cd7b0b0 100644 --- a/index.html +++ b/index.html @@ -7,5 +7,6 @@
+ diff --git a/src/constant/Constant.js b/src/constant/Constant.js new file mode 100644 index 000000000..521205a22 --- /dev/null +++ b/src/constant/Constant.js @@ -0,0 +1,52 @@ +export const TEXT = { + CHARGE_COIN_LABEL: "자판기 동전 충전하기", + MACHINE_CHARGE_PLACEHOLDER: "자판기가 보유할 금액", + MACHINE_CHARGE_BUTTON: "충전하기", + MACHINE_CHARGE_INFO_LABEL: "보유 금액: ", + MACHINE_COIN_INFO_LABEL: "자판기가 보유한 동전", + MACHINE_COIN_CATEGORY: "동전", + MACHINE_COIN_AMOUNT: "개수", + COIN_500: "500원", + COIN_100: "100원", + COIN_50: "50원", + COIN_10: "10원", + PRODUCT_ADD_LABEL: "상품 추가하기", + PRODUCT_NAME_PLACEHOLDER: "상품명", + PRODUCT_PRICE_PLACEHOLDER: "가격", + PRODUCT_QUANTITY_PLACEHOLDER: "수량", + PRODUCT_ADD_BUTTON: "추가하기", + PRODUCT_DISPLAY_LABEL: "상품 현황", + PRODUCT_ITEM_NAME: "상품명", + PRODUCT_ITEM_PRICE: "가격", + PRODUCT_ITEM_QUANTITY: "수량", + PRODUCT_ITEM_PURCHASE: "구매", + PRODUCT_ITEM_PURCHASE_BUTTON: "구매하기", + CHARGE_TO_PURCHASE_LABEL: "금액 투입", + CHARGE_TO_PURCHASE_PLACEHOLDER: "투입할 금액", + CHARGE_TO_PURCHASE_MONEY_LABEL: "투입한 금액: ", + PURCHASABLE_PRODUCE_LABEL: "구매할 수 있는 상품 현황", + RETURN_CHANGE_LABEL: "잔돈", + RETURN_CHANGE_BUTTON: "반환하기", + TAB_TITLE: "🥤자판기🥤", + TAB_PRODUCT_ADD_BUTTON: "상품 관리", + TAB_CHARGE_BUTTON: "잔돈 충전", + TAB_PURCHASE_BUTTON: "상품 구매", +} + +export const MSG = { + INVALID_CHARGE: "올바르지 않은 잔돈 값입니다.", + INVALID_PRICE: "가격을 다시 입력해주세요", + INVALID_QUANTITY: "재고가 없습니다.", + INVALID_MONEY: "잔액이 부족합니다.", + INVALID_INPUT: "잘못된 입력 값 :", +} + +export const NUMBER = { + MINIMUM_CHARGE: 10, + MINIMUM_COIN_UNIT: 10, + MINIMUM_PRICE: 100, + COIN_500: 500, + COIN_100: 100, + COIN_50: 50, + COIN_10: 10 +} diff --git a/src/dom/buildChargePage.js b/src/dom/buildChargePage.js new file mode 100644 index 000000000..da6c31d82 --- /dev/null +++ b/src/dom/buildChargePage.js @@ -0,0 +1,81 @@ +import VendingMachine from "../vendingMachine/VendingMachine.js"; +import createDocumentElement from "../util/createDocumentElement.js"; +import createTableRow from "../util/createTableRow.js"; +import validateCharge from "../util/validateCharge.js"; +import { TEXT, MSG } from "../constant/Constant.js"; + +const vendingMachine = new VendingMachine; + +function buildChargePage() { + const container = document.querySelector(".container"); + + vendingMachine.getFromLocalStorage(); + + clearContainer(container); + chargeElement(container); + coinDisplayElement(container); + updateCoin(); +} + +function chargeElement(container) { + const vendingMachineChargeLabel = createDocumentElement("h3", TEXT.CHARGE_COIN_LABEL); + const vendingMachineChargeInput = createDocumentElement("input", "", "vending-machine-charge-input", TEXT.MACHINE_CHARGE_PLACEHOLDER); + const vendingMachineChargeButton = createDocumentElement("button", TEXT.MACHINE_CHARGE_BUTTON, "vending-machine-charge-button"); + const vendingMachineMoneyLabel = createDocumentElement("p", TEXT.MACHINE_CHARGE_INFO_LABEL); + const vendingMachineChargeAmount = createDocumentElement("span", "", "vending-machine-charge-amount"); + const vendingMachineCoinDisplayLabel = createDocumentElement("h3", TEXT.MACHINE_COIN_INFO_LABEL); + + vendingMachineChargeButton.onclick = () => addCharge(); + + container.append(vendingMachineChargeLabel, vendingMachineChargeInput, vendingMachineChargeButton, vendingMachineMoneyLabel, vendingMachineCoinDisplayLabel); + vendingMachineMoneyLabel.appendChild(vendingMachineChargeAmount); +} + +function coinDisplayElement(container) { + const coinDisplayTable = document.createElement("table"); + const coinDisplayTableRow = document.createElement("tr"); + const coinCategory = createDocumentElement("td", TEXT.MACHINE_COIN_CATEGORY); + const coinAmount = createDocumentElement("td", TEXT.MACHINE_COIN_AMOUNT); + + container.appendChild(coinDisplayTable); + coinDisplayTable.appendChild(coinDisplayTableRow); + coinDisplayTableRow.append(coinCategory, coinAmount); + + createTableRow(coinDisplayTable, TEXT.COIN_500,"vending-machine-coin-500-quantity"); + createTableRow(coinDisplayTable, TEXT.COIN_100,"vending-machine-coin-100-quantity"); + createTableRow(coinDisplayTable, TEXT.COIN_50,"vending-machine-coin-50-quantity"); + createTableRow(coinDisplayTable, TEXT.COIN_10,"vending-machine-coin-10-quantity"); +} + +function addCharge() { + const vendingMachineChargeInput = document.querySelector("#vending-machine-charge-input"); + if(validateCharge(vendingMachineChargeInput.value)) { + vendingMachine.chargeChange(vendingMachineChargeInput.value); + } + else{ + alert(MSG.INVALID_CHARGE); + } + + vendingMachineChargeInput.value = ""; + updateCoin(); +} + +function updateCoin() { + const vendingMachineCoin500Quantity = document.querySelector("#vending-machine-coin-500-quantity"); + const vendingMachineCoin100Quantity = document.querySelector("#vending-machine-coin-100-quantity"); + const vendingMachineCoin50Quantity = document.querySelector("#vending-machine-coin-50-quantity"); + const vendingMachineCoin10Quantity = document.querySelector("#vending-machine-coin-10-quantity"); + + const coins = vendingMachine.getCoins(); + + vendingMachineCoin500Quantity.innerText = coins.coin500 + "개"; + vendingMachineCoin100Quantity.innerText = coins.coin100 + "개"; + vendingMachineCoin50Quantity.innerText = coins.coin50 + "개"; + vendingMachineCoin10Quantity.innerText = coins.coin10 + "개"; +} + +function clearContainer(container) { + container.innerHTML = ""; +} + +export default buildChargePage; diff --git a/src/dom/buildContainer.js b/src/dom/buildContainer.js new file mode 100644 index 000000000..ad87ac72d --- /dev/null +++ b/src/dom/buildContainer.js @@ -0,0 +1,9 @@ +function buildContainer() { + const app = document.getElementById("app"); + const container = document.createElement("div"); + + container.className = "container"; + app.appendChild(container); +} + +export default buildContainer; diff --git a/src/dom/buildProductPage.js b/src/dom/buildProductPage.js new file mode 100644 index 000000000..1dfa2ec41 --- /dev/null +++ b/src/dom/buildProductPage.js @@ -0,0 +1,92 @@ +import ProductList from "../product/ProductList.js"; +import createDocumentElement from "../util/createDocumentElement.js" +import validatePrice from "../util/validatePrice.js"; +import { TEXT, MSG } from "../constant/Constant.js"; + +const productList = new ProductList; + +function buildProductPage() { + const container = document.querySelector(".container"); + productList.getFromLocalStorage(); + + clearContainer(container); + productAddElement(container); + productItemElement(container); + productItemRefresh(); + bindButtonEvent(); +} + +function productAddElement(container) { + const productAddLabel = createDocumentElement("h3", TEXT.PRODUCT_ADD_LABEL); + const productNameInput = createDocumentElement("input", "", "product-name-input", TEXT.PRODUCT_NAME_PLACEHOLDER); + const productPriceInput = createDocumentElement("input", "", "product-price-input", TEXT.PRODUCT_PRICE_PLACEHOLDER); + const productQuantityInput = createDocumentElement("input", "", "product-quantity-input", TEXT.PRODUCT_QUANTITY_PLACEHOLDER); + const productAddButton = createDocumentElement("button", TEXT.PRODUCT_ADD_BUTTON, "product-add-button"); + const productDisplayLabel = createDocumentElement("h3", TEXT.PRODUCT_DISPLAY_LABEL); + + container.append(productAddLabel, productNameInput, productPriceInput, productQuantityInput, productAddButton, productDisplayLabel); +} + +function productItemElement(container) { + const productItemTable = document.createElement("table"); + const productItemTableRow = document.createElement("tr"); + const productItemName = createDocumentElement("td", TEXT.PRODUCT_ITEM_NAME); + const productItemPrice = createDocumentElement("td", TEXT.PRODUCT_ITEM_PRICE); + const productItemQuantity = createDocumentElement("td", TEXT.PRODUCT_ITEM_QUANTITY); + + container.appendChild(productItemTable); + productItemTable.appendChild(productItemTableRow); + productItemTableRow.append(productItemName, productItemPrice, productItemQuantity); +} + +function deleteItemElement() { + const productItemTable = document.querySelector("table"); + productItemTable.parentNode.removeChild(productItemTable); +} + +function addItemElement(name, price, quantity) { + const productItemTable = document.querySelector("table"); + const productItemTableRow = createDocumentElement("tr", "", "", "", "product-manage-item"); + const productItemName = createDocumentElement("td", name, "", "", "product-manage-name"); + const productItemPrice = createDocumentElement("td", price, "", "", "product-manage-price"); + const productItemQuantity = createDocumentElement("td", quantity, "", "", "product-manage-quantity"); + + productItemTable.appendChild(productItemTableRow); + productItemTableRow.append(productItemName, productItemPrice, productItemQuantity); +} + +function productItemRefresh() { + const container = document.querySelector(".container"); + + deleteItemElement(); + productItemElement(container); + if(productList.getItem() !== null) { + productList.getItem().map((item) => { + addItemElement(item.name, item.price, item.quantity); + }); + } +} + +function clearContainer(container) { + container.innerHTML = ""; +} + +function bindButtonEvent() { + const button = document.querySelector("#product-add-button"); + + button.onclick = () => { + const name = document.querySelector("#product-name-input").value; + const price = document.querySelector("#product-price-input").value; + const quantity = document.querySelector("#product-quantity-input").value; + + if(validatePrice(price)) { + productList.addItem(name, price, quantity); + productItemRefresh(); + } + else { + alert(MSG.INVALID_PRICE); + } + } +} + +export default buildProductPage; diff --git a/src/dom/buildPurchasePage.js b/src/dom/buildPurchasePage.js new file mode 100644 index 000000000..96a0b94cd --- /dev/null +++ b/src/dom/buildPurchasePage.js @@ -0,0 +1,139 @@ +import ProductList from "../product/ProductList.js"; +import VendingMachine from "../vendingMachine/VendingMachine.js"; +import createDocumentElement from "../util/createDocumentElement.js"; +import createTableRow from "../util/createTableRow.js"; +import { TEXT, MSG } from "../constant/Constant.js"; + +const productList = new ProductList; +const vendingMachine = new VendingMachine; + +function buildPurchasePage() { + const container = document.querySelector(".container"); + + productList.getFromLocalStorage(); + vendingMachine.getFromLocalStorage(); + + clearContainer(container) + productPurchaseElement(container); + productItemElement(container); + productList.getItem().map((item) => { + addItemElement(item.name, item.price, item.quantity); + }); + coinDisplayElement(container); +} + +function productPurchaseElement(container) { + const productPurchaseLabel = createDocumentElement("h3", TEXT.CHARGE_TO_PURCHASE_LABEL); + const chargeInput = createDocumentElement("input", "", "charge-input", TEXT.CHARGE_TO_PURCHASE_PLACEHOLDER); + const chargeButton = createDocumentElement("button", "투입하기", "charge-button"); + const moneyLabel = createDocumentElement("p", TEXT.CHARGE_TO_PURCHASE_MONEY_LABEL); + const chargeAmount = createDocumentElement("span", "", "charge-amount"); + const productDisplayLabel = createDocumentElement("h3", TEXT.PURCHASABLE_PRODUCE_LABEL); + + chargeButton.onclick = () => chargeUserInputMoney(); + + container.append(productPurchaseLabel, chargeInput, chargeButton, moneyLabel, productDisplayLabel); + moneyLabel.appendChild(chargeAmount); +} + +function productItemElement(container) { + const productItemTable = document.createElement("table"); + const productItemTableRow = document.createElement("tr"); + const productItemName = createDocumentElement("td", TEXT.PRODUCT_ITEM_NAME); + const productItemPrice = createDocumentElement("td", TEXT.PRODUCT_ITEM_PRICE); + const productItemQuantity = createDocumentElement("td", TEXT.PRODUCT_ITEM_QUANTITY); + const productItemPurchase = createDocumentElement("td", TEXT.PRODUCT_ITEM_PURCHASE); + + container.appendChild(productItemTable); + productItemTable.appendChild(productItemTableRow); + productItemTableRow.append(productItemName, productItemPrice, productItemQuantity, productItemPurchase); +} + +function addItemElement(name, price, quantity) { + const productItemTable = document.querySelector("table"); + const productItemTableRow = createDocumentElement("tr", "", "", "", "product-purchase-item"); + const productItemName = createDocumentElement("td", name, "", "", "product-purchase-name"); + const productItemPrice = createDocumentElement("td", price, "", "", "product-purchase-price"); + const productItemQuantity = createDocumentElement("td", quantity, "", "", "product-purchase-quantity"); + const productItemPurchase = createDocumentElement("td"); + const productItemPurchaseButton = createDocumentElement("button", TEXT.PRODUCT_ITEM_PURCHASE_BUTTON, "", "", "purchase-button"); + + productItemName.setAttribute("data-product-name", name); + productItemPrice.setAttribute("data-product-price", price); + productItemQuantity.setAttribute("data-product-quantity", quantity); + productItemPurchaseButton.onclick = () => purchaseItem(name, price); + + productItemTable.appendChild(productItemTableRow); + productItemTableRow.append(productItemName, productItemPrice, productItemQuantity, productItemPurchase); + productItemPurchase.appendChild(productItemPurchaseButton); +} + +function coinDisplayElement(container) { + const productPurchaseLabel = createDocumentElement("h3", TEXT.RETURN_CHANGE_LABEL); + const productItemPurchaseButton = createDocumentElement("button", TEXT.RETURN_CHANGE_BUTTON, "", "", "coin-return-button"); + const coinDisplayTable = document.createElement("table"); + const coinDisplayTableRow = document.createElement("tr"); + const coinCategory = createDocumentElement("td", TEXT.MACHINE_COIN_CATEGORY); + const coinAmount = createDocumentElement("td", TEXT.MACHINE_COIN_AMOUNT); + + productItemPurchaseButton.onclick = () => returnCharge(); + + container.append(productPurchaseLabel, productItemPurchaseButton, coinDisplayTable); + coinDisplayTable.appendChild(coinDisplayTableRow); + coinDisplayTableRow.append(coinCategory, coinAmount); + + createTableRow(coinDisplayTable, TEXT.COIN_500,"coin-500-quantity"); + createTableRow(coinDisplayTable, TEXT.COIN_100,"coin-100-quantity"); + createTableRow(coinDisplayTable, TEXT.COIN_50,"coin-50-quantity"); + createTableRow(coinDisplayTable, TEXT.COIN_10,"coin-10-quantity"); +} + +function chargeUserInputMoney() { + const chargeInput = document.querySelector("#charge-input"); + vendingMachine.chargeUserInputMoney((Number)(chargeInput.value)); + chargeInput.value = ""; + displayChargeAmount(); +} + +function displayChargeAmount() { + const chargeAmount = document.querySelector("#charge-amount"); + chargeAmount.innerText = vendingMachine.getUserInputMoney(); +} + +function returnCharge() { + const coins = vendingMachine.returnCharge(); + + const returnCoin500Quantity = document.querySelector("#coin-500-quantity"); + const returnCoin100Quantity = document.querySelector("#coin-100-quantity"); + const returnCoin50Quantity = document.querySelector("#coin-50-quantity"); + const returnCoin10Quantity = document.querySelector("#coin-10-quantity"); + + returnCoin500Quantity.innerText = coins.coin500 + "개"; + returnCoin100Quantity.innerText = coins.coin100 + "개"; + returnCoin50Quantity.innerText = coins.coin50 + "개"; + returnCoin10Quantity.innerText = coins.coin10 + "개"; + + displayChargeAmount(); +} + +function purchaseItem(name, price) { + if(vendingMachine.getUserInputMoney() >= price) { + if(productList.purchaseItem(name)) { + vendingMachine.reduceUserInputMoney(price); + } + else{ + alert(MSG.INVALID_QUANTITY); + } + } + else{ + alert(MSG.INVALID_MONEY); + } + buildPurchasePage(); + displayChargeAmount(); +} + +function clearContainer(container) { + container.innerHTML = ""; +} + +export default buildPurchasePage; diff --git a/src/dom/tabMenu.js b/src/dom/tabMenu.js new file mode 100644 index 000000000..a66058906 --- /dev/null +++ b/src/dom/tabMenu.js @@ -0,0 +1,42 @@ +import buildProductPage from "./buildProductPage.js"; +import buildChargePage from "./buildChargePage.js"; +import buildPurchasePage from "./buildPurchasePage.js"; +import { TEXT } from "../constant/Constant.js"; + +function tabMenu() { + const app = document.getElementById("app"); + const header = document.createElement("header"); + const title = document.createElement("h1"); + const productAddMenuButton = document.createElement("button"); + const vendingMachineManageMenuButton = document.createElement("button"); + const productPurchaseMenuButton = document.createElement("button"); + + title.innerText = TEXT.TAB_TITLE; + + productAddMenuButton.id = "product-add-menu"; + productAddMenuButton.innerText = TEXT.TAB_PRODUCT_ADD_BUTTON; + productAddMenuButton.onclick = () => { + buildProductPage(); + } + + vendingMachineManageMenuButton.id = "vending-machine-manage-menu"; + vendingMachineManageMenuButton.innerText = TEXT.TAB_CHARGE_BUTTON; + vendingMachineManageMenuButton.onclick = () => { + buildChargePage(); + } + + productPurchaseMenuButton.id = "product-purchase-menu"; + productPurchaseMenuButton.innerText = TEXT.TAB_PURCHASE_BUTTON; + productPurchaseMenuButton.onclick = () => { + buildPurchasePage(); + } + + header.appendChild(title); + header.appendChild(productAddMenuButton); + header.appendChild(vendingMachineManageMenuButton); + header.appendChild(productPurchaseMenuButton); + + app.appendChild(header); +} + +export default tabMenu; diff --git a/src/index.js b/src/index.js new file mode 100644 index 000000000..6725aa9df --- /dev/null +++ b/src/index.js @@ -0,0 +1,7 @@ +import tabMenu from "./dom/tabMenu.js"; +import buildContainer from "./dom/buildContainer.js"; +import buildProductPage from "./dom/buildProductPage.js"; + +tabMenu(); +buildContainer(); +buildProductPage(); diff --git a/src/product/Product.js b/src/product/Product.js new file mode 100644 index 000000000..6f0cced63 --- /dev/null +++ b/src/product/Product.js @@ -0,0 +1,9 @@ +class Product { + constructor(name, price, quantity) { + this.name = name; + this.price = price; + this.quantity = quantity; + } +} + +export default Product; diff --git a/src/product/ProductList.js b/src/product/ProductList.js new file mode 100644 index 000000000..0fafc7c5c --- /dev/null +++ b/src/product/ProductList.js @@ -0,0 +1,40 @@ +import Product from "./Product.js"; + +class ProductList { + item = []; + + constructor() { + this.item = []; + } + + addItem(name, price, quantity) { + const newItem = new Product(name, price, quantity); + this.item.push(newItem); + this.setLocalStorage(); + } + + getItem() { + return this.item; + } + + purchaseItem(name) { + const found = this.item.find(element => element.name === name); + if(found.quantity > 0) { + found.quantity -= 1; + this.setLocalStorage(); + return true; + } + return false; + } + + setLocalStorage() { + localStorage.setItem("productList", JSON.stringify(this.getItem())); + } + + getFromLocalStorage() { + this.item = JSON.parse(localStorage.getItem("productList")) ?? []; + } +} + + +export default ProductList; diff --git a/src/util/createDocumentElement.js b/src/util/createDocumentElement.js new file mode 100644 index 000000000..6844d9631 --- /dev/null +++ b/src/util/createDocumentElement.js @@ -0,0 +1,12 @@ +function createDocumentElement(tag, innerText='', id='', placeholder='', className='') { + const newElement = document.createElement(tag); + + newElement.id = id; + newElement.className = className; + newElement.placeholder = placeholder; + newElement.innerText = innerText; + + return newElement; +} + +export default createDocumentElement; diff --git a/src/util/createTableRow.js b/src/util/createTableRow.js new file mode 100644 index 000000000..a763fc42a --- /dev/null +++ b/src/util/createTableRow.js @@ -0,0 +1,13 @@ +import createDocumentElement from "./createDocumentElement.js"; + +function createTableRow(Table, innerText, id) { + const tableRow = document.createElement("tr"); + const coin = createDocumentElement("td", innerText); + const coinAmount = createDocumentElement("td", "", id); + + Table.appendChild(tableRow); + tableRow.appendChild(coin); + tableRow.appendChild(coinAmount); +} + +export default createTableRow; diff --git a/src/util/validateCharge.js b/src/util/validateCharge.js new file mode 100644 index 000000000..1415fdaa1 --- /dev/null +++ b/src/util/validateCharge.js @@ -0,0 +1,7 @@ +import { NUMBER } from "../constant/Constant.js"; + +function validateCharge(input) { + return (input % NUMBER.MINIMUM_COIN_UNIT) === 0 && input >= NUMBER.MINIMUM_CHARGE; +} + +export default validateCharge; diff --git a/src/util/validatePrice.js b/src/util/validatePrice.js new file mode 100644 index 000000000..8de96d227 --- /dev/null +++ b/src/util/validatePrice.js @@ -0,0 +1,7 @@ +import { NUMBER } from "../constant/Constant.js"; + +function validatePrice(input) { + return (input % NUMBER.MINIMUM_COIN_UNIT) === 0 && input >= NUMBER.MINIMUM_PRICE; +} + +export default validatePrice; diff --git a/src/vendingMachine/VendingMachine.js b/src/vendingMachine/VendingMachine.js new file mode 100644 index 000000000..899f1c5cd --- /dev/null +++ b/src/vendingMachine/VendingMachine.js @@ -0,0 +1,122 @@ +import { MSG, NUMBER } from "../constant/Constant.js"; + +class VendingMachine { + constructor() { + this.coin500 = 0; + this.coin100 = 0; + this.coin50 = 0; + this.coin10 = 0; + this.userInputMoney = 0; + } + + chargeChange(money) { + while(money > 0) { + let coin = MissionUtils.Random.pickNumberInList([NUMBER.COIN_10, NUMBER.COIN_50, NUMBER.COIN_100, NUMBER.COIN_500]); + if(coin <= money) { + this.addCoin(coin); + money -= coin; + } + } + this.setLocalStorage(); + } + + addCoin(coin) { + switch (coin) { + case NUMBER.COIN_10: + this.coin10++; + break; + case NUMBER.COIN_50: + this.coin50++; + break; + case NUMBER.COIN_100: + this.coin100++; + break; + case NUMBER.COIN_500: + this.coin500++; + break; + default: + console.log(MSG.INVALID_INPUT + coin); + } + } + + chargeUserInputMoney(input) { + this.userInputMoney += input; + this.setLocalStorage(); + } + + getUserInputMoney() { + return this.userInputMoney; + } + + reduceUserInputMoney(amount) { + this.userInputMoney -= amount; + this.setLocalStorage(); + } + + getCoins() { + const coins = { + coin500: this.coin500, + coin100: this.coin100, + coin50: this.coin50, + coin10: this.coin10 + } + return coins; + } + + getTotalChange() { + return (this.coin500)*NUMBER.COIN_500 + (this.coin100)*NUMBER.COIN_100 + (this.coin50)*NUMBER.COIN_50 + (this.coin10)*NUMBER.COIN_10; + } + + returnCharge() { + let returnCoins = { + coin500: 0, + coin100: 0, + coin50: 0, + coin10: 0 + } + + if(this.getTotalChange() > 0) { + while(this.coin500 > 0 && this.userInputMoney >= NUMBER.COIN_500) { + this.coin500--; + this.userInputMoney -= 500; + returnCoins.coin500++; + } + while(this.coin100 > 0 && this.userInputMoney >= NUMBER.COIN_100) { + this.coin100--; + this.userInputMoney -= 100; + returnCoins.coin100++; + } + while(this.coin50 > 0 && this.userInputMoney >= NUMBER.COIN_50) { + this.coin50--; + this.userInputMoney -= 50; + returnCoins.coin50++; + } + while(this.coin10 > 0 && this.userInputMoney >= NUMBER.COIN_10) { + this.coin10--; + this.userInputMoney -= 10; + returnCoins.coin10++; + } + } + + this.setLocalStorage(); + return returnCoins; + } + + getFromLocalStorage() { + this.coin500 = JSON.parse(localStorage.getItem("vendingMachine500")) ?? 0; + this.coin100 = JSON.parse(localStorage.getItem("vendingMachine100")) ?? 0; + this.coin50 = JSON.parse(localStorage.getItem("vendingMachine50")) ?? 0; + this.coin10 = JSON.parse(localStorage.getItem("vendingMachine10")) ?? 0; + this.userInputMoney = JSON.parse(localStorage.getItem("userInputMoney")) ?? 0; + } + + setLocalStorage() { + localStorage.setItem("vendingMachine500", this.coin500); + localStorage.setItem("vendingMachine100", this.coin100); + localStorage.setItem("vendingMachine50", this.coin50); + localStorage.setItem("vendingMachine10", this.coin10); + localStorage.setItem("userInputMoney", this.userInputMoney); + } +} + +export default VendingMachine;