|
@@ -0,0 +1,152 @@
|
|
|
+<header>KIOSK</header>
|
|
|
+
|
|
|
+<body>
|
|
|
+ <script>
|
|
|
+
|
|
|
+ const addCell = (row, value) => {
|
|
|
+ let cell = document.createElement("td");
|
|
|
+ cell.innerText = value;
|
|
|
+ row.append(cell);
|
|
|
+ return cell;
|
|
|
+ }
|
|
|
+ const createAssortTable = (store) => {
|
|
|
+ let state = store.getState();
|
|
|
+ let table = document.createElement("table");
|
|
|
+ let row = document.createElement("tr");
|
|
|
+ table.append(row);
|
|
|
+ addCell(row, "NAME");
|
|
|
+ addCell(row, "PRICE");
|
|
|
+ addCell(row, "AMOUNT");
|
|
|
+ for (const itemKey in state) {
|
|
|
+ if (itemKey == "cashbox")
|
|
|
+ continue;
|
|
|
+ let item = state[itemKey];
|
|
|
+ let row = document.createElement("tr");
|
|
|
+ table.append(row);
|
|
|
+
|
|
|
+ addCell(row, itemKey);
|
|
|
+ addCell(row, item.price);
|
|
|
+ let amountVal = addCell(row, item.amount);
|
|
|
+
|
|
|
+ store.subscribe(() => {
|
|
|
+ const state = store.getState();
|
|
|
+ const item = state[itemKey];
|
|
|
+ const amount = item.amount;
|
|
|
+ amountVal.innerText = amount;
|
|
|
+ });
|
|
|
+ //store.getState()[itemKey].amount);
|
|
|
+ }
|
|
|
+ return table;
|
|
|
+ }
|
|
|
+ const addLabel = (element, value) => {
|
|
|
+ let label = document.createElement("label");
|
|
|
+ label.htmlFor = element.id;
|
|
|
+ label.innerText = value + ": ";
|
|
|
+ element.parentElement.insertBefore(label, element);
|
|
|
+ }
|
|
|
+ const addBr = (element) => element.append(document.createElement("br"));
|
|
|
+
|
|
|
+ const createSale = (store) => {
|
|
|
+ let state = store.getState();
|
|
|
+ let resDiv = document.createElement("div")
|
|
|
+ let select = document.createElement("select");
|
|
|
+ resDiv.append(select);
|
|
|
+ for (itemKey in state) {
|
|
|
+ if (itemKey == "cashbox")
|
|
|
+ continue;
|
|
|
+ let option = document.createElement("option");
|
|
|
+ option.value = itemKey;
|
|
|
+ option.text = itemKey;
|
|
|
+ select.append(option);
|
|
|
+ }
|
|
|
+ select.onchange = () => {
|
|
|
+ priceDiv.innerText = state[select.value].price;
|
|
|
+ }
|
|
|
+ addLabel(select, "NAME");
|
|
|
+ addBr(resDiv);
|
|
|
+ let priceDiv = document.createElement("a");
|
|
|
+ priceDiv.innerText = state[select.value].price;
|
|
|
+ priceDiv.id = "priceId";
|
|
|
+
|
|
|
+ resDiv.append(priceDiv);
|
|
|
+ addLabel(priceDiv, "price");
|
|
|
+ addBr(resDiv);
|
|
|
+ let amountInp = document.createElement("input");
|
|
|
+ amountInp.id = "amountId";
|
|
|
+ amountInp.value = 0;
|
|
|
+
|
|
|
+ resDiv.append(amountInp);
|
|
|
+ addLabel(amountInp, "amount");
|
|
|
+ addBr(resDiv);
|
|
|
+ let cashInp = document.createElement("input");
|
|
|
+ cashInp.id = "cashId";
|
|
|
+ cashInp.value = 0;
|
|
|
+ resDiv.append(cashInp);
|
|
|
+ addLabel(cashInp, "cash");
|
|
|
+ addBr(resDiv);
|
|
|
+ let buyBtn = document.createElement("button");
|
|
|
+ buyBtn.innerText = "BUY";
|
|
|
+ buyBtn.onclick = () => {
|
|
|
+ store.dispatch({ type: 'BUY', item: select.value, amount: +amountInp.value, cash: +cashInp.value });
|
|
|
+ }
|
|
|
+ resDiv.append(buyBtn);
|
|
|
+
|
|
|
+ return resDiv;
|
|
|
+ }
|
|
|
+ function CreateStore(reducer) {
|
|
|
+ let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
|
|
|
+ let cbs = [] //массив подписчиков
|
|
|
+
|
|
|
+ this.getState = () => state //функция, возвращающая переменную из замыкания
|
|
|
+ this.subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
|
|
|
+ () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
|
|
|
+
|
|
|
+ this.dispatch = action => {
|
|
|
+ const newState = reducer(state, action) //пробуем запустить редьюсер
|
|
|
+ if (newState !== state) { //проверяем, смог ли редьюсер обработать action
|
|
|
+ state = newState //если смог, то обновляем state
|
|
|
+ for (let cb of cbs) cb() //и запускаем подписчиков
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const seller = (state, { type, item, amount, cash, price }) => {
|
|
|
+ if (state === undefined) {
|
|
|
+ state = {
|
|
|
+ beer: { amount: 20, price: 10 },
|
|
|
+ vodka: { amount: 10, price: 30 },
|
|
|
+ cigars: { amount: 100, price: 20 },
|
|
|
+ cashbox: 0,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (type === 'BUY' &&
|
|
|
+ item in state &&
|
|
|
+ typeof amount == "number" &&
|
|
|
+ typeof cash == "number" &&
|
|
|
+ state[item].amount >= amount &&
|
|
|
+ amount > 0 &&
|
|
|
+ cash > 0 &&
|
|
|
+ state[item].price <= cash / amount) { //если тип action - КУПИТЬ, то:
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...state, //берем все что было из ассортимента
|
|
|
+ [item]: { amount: state[item].amount - amount, price: state[item].price }, //и уменьшаем то, что покупается на количество
|
|
|
+ cashbox: state.cashbox + amount * state[item].price,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return state;
|
|
|
+ }
|
|
|
+ let store = new CreateStore(seller);
|
|
|
+ const unsubscribe = store.subscribe(() => console.log(store.getState()))
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ document.body.append(createAssortTable(store));
|
|
|
+ document.body.append(document.createElement("br"));
|
|
|
+ document.body.append(createSale(store));
|
|
|
+
|
|
|
+ </script>
|
|
|
+</body>
|
|
|
+<footer>
|
|
|
+
|
|
|
+</footer>
|