123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Document</title>
- </head>
- <body>
- <select name="" id="selectItems"></select>
- <input type="number" name="" id="inputAmountToBuy" />
- <button type="button" id="buyBtn">Buy</button>
- <div id="container">
- <table id="stateTable" border="1"></table>
- </div>
- <script>
- const store = createStore(reducer);
- for ([key, value] of Object.entries(store.getState()["продукты"])) {
- let option = document.createElement("option");
- option.innerText = key;
- option.value = key;
- selectItems.append(option);
- }
- const buyItem = (amount, item) => ({
- type: "КУПИТЬ",
- ШО: item,
- СКОКА: amount,
- });
- buyBtn.onclick = () => {
- let amount = inputAmountToBuy.value;
- let item = selectItems.value;
- store.dispatch(buyItem(amount, item));
- console.log(amount);
- };
- const updateTable = () => {
- let str = "<tr><th>Название</th><th>Количество</th><th>Цена</th></tr>";
- let state = store.getState();
- for ([key, value] of Object.entries(state["продукты"])) {
- str += `<tr><th>${key}</th><td>${value.amount}</td><td>${value.cost}</td></tr>`;
- }
- str += `<th>касса</th><td colspan = "2">${state["касса"]}</td></tr>`;
- stateTable.innerHTML = str;
- };
- store.subscribe(updateTable);
- store.subscribe(() => console.log(store.getState()));
- updateTable();
- function reducer(state, { type, ШО, СКОКА }) {
- //объект action деструктуризируется на три переменных
- if (!state) {
- //начальная уборка в ларьке:
- return {
- продукты: {
- пиво: { amount: 100, cost: 33 },
- чипсы: { amount: 100, cost: 13 },
- сиги: { amount: 100, cost: 43 },
- },
- касса: 0,
- };
- }
- if (type.toUpperCase() === "КУПИТЬ") {
- let products = state["продукты"];
- if (СКОКА <= 0 || СКОКА > state["продукты"][ШО]["amount"]) {
- return state;
- }
- return {
- ...state, //берем все что было из ассортимента
- ["продукты"]: {
- ...products,
- [ШО]: {
- ...products[ШО],
- amount: products[ШО]["amount"] - СКОКА,
- },
- },
- касса: +state["касса"] + +products[ШО]["cost"] * +СКОКА, //и уменьшаем то, что покупается на количество
- };
- }
- return state; //если мы не поняли, что от нас просят в `action` - оставляем все как есть
- }
- function createStore(reducer) {
- let state = reducer(undefined, {}); //стартовая инициализация состояния, запуск редьюсера со state === undefined
- let cbs = []; //массив подписчиков
- const getState = () => state; //функция, возвращающая переменную из замыкания
- const subscribe = (cb) => (
- cbs.push(cb), //запоминаем подписчиков в массиве
- () => (cbs = cbs.filter((c) => c !== cb))
- ); //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
- const dispatch = (action) => {
- const newState = reducer(state, action); //пробуем запустить редьюсер
- if (newState !== state) {
- //проверяем, смог ли редьюсер обработать action
- state = newState; //если смог, то обновляем state
- for (let cb of cbs) cb(); //и запускаем подписчиков
- }
- };
- return {
- getState, //добавление функции getState в результирующий объект
- dispatch,
- subscribe, //добавление subscribe в объект
- };
- }
- </script>
- </body>
- </html>
|