|
@@ -0,0 +1,154 @@
|
|
|
|
+<!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>
|
|
|
|
+ <link rel="stylesheet" href="style.css">
|
|
|
|
+</head>
|
|
|
|
+
|
|
|
|
+<body>
|
|
|
|
+ <div id="parampampam">
|
|
|
|
+ <div class="shop">
|
|
|
|
+ <select id='range'>
|
|
|
|
+ <option value="пиво">Пиво</option>
|
|
|
|
+ <option value="чипсы">Чипсы</option>
|
|
|
|
+ <option value="сиги">Сиги</option>
|
|
|
|
+ </select>
|
|
|
|
+ <input type='number' id='amount1' placeholder='количество' />
|
|
|
|
+ <input type='number' id='money' placeholder='сумма' />
|
|
|
|
+ <button id='buy'>Купить</button>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div id="tovar">
|
|
|
|
+
|
|
|
|
+ </div>
|
|
|
|
+ <div id="price">
|
|
|
|
+
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <p id="kassa">Собираюсь построить Зикурат: </p>
|
|
|
|
+ </div>
|
|
|
|
+ <script>
|
|
|
|
+ setTimeout(function () {
|
|
|
|
+ let parent = document.getElementById("price");
|
|
|
|
+ parent.lastElementChild.remove();
|
|
|
|
+ store.dispatch({ type: "КУПИТЬ", ШО: "пиво", СКОКА: 0 });
|
|
|
|
+ }, 1);
|
|
|
|
+ setTimeout(function () {
|
|
|
|
+ let parent = document.getElementById("tovar");
|
|
|
|
+ parent.lastElementChild.remove();
|
|
|
|
+ store.dispatch({ type: "КУПИТЬ", ШО: "пиво", СКОКА: 0 });
|
|
|
|
+ }, 1);
|
|
|
|
+
|
|
|
|
+ function reducer(state, { type, ШО, СКОКА, ДЕНЬГИ }) { //объект action деструктуризируется на три переменных
|
|
|
|
+ if (!state) { //начальная уборка в ларьке:
|
|
|
|
+ return {
|
|
|
|
+ пиво: { count: 100, price: 23 },
|
|
|
|
+ чипсы: { count: 100, price: 18 },
|
|
|
|
+ сиги: { count: 100, price: 41 },
|
|
|
|
+ касса: 0,
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (type === 'КУПИТЬ' && СКОКА >= 0) { //если тип action - КУПИТЬ, то:
|
|
|
|
+ if (state[ШО].count >= СКОКА) {
|
|
|
|
+ if (money.value >= (state[ШО].price * СКОКА)) {
|
|
|
|
+ return {
|
|
|
|
+ ...state, //берем все что было из ассортимента
|
|
|
|
+ [ШО]: { count: state[ШО].count - СКОКА, price: state[ШО].price }, //и уменьшаем то, что покупается на количество
|
|
|
|
+ касса: state.касса + +money.value
|
|
|
|
+ // state[ШО].price * СКОКА()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ alert("Нужно больше золота!")
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ alert('Извините товар едет!')
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ alert('Наверное вам хватит ');
|
|
|
|
+ }
|
|
|
|
+ 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 в объект
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const store = createStore(reducer)
|
|
|
|
+
|
|
|
|
+ //запомнит функцию во внутреннем массиве cbs.
|
|
|
|
+ //она будет запущена при любом успешном dispatch
|
|
|
|
+ const unsubscribe = store.subscribe(() => console.log(store.getState()))
|
|
|
|
+
|
|
|
|
+ // setTimeout(unsubscribe, 10000) //отпишемся через 10 секунд, например
|
|
|
|
+
|
|
|
|
+ //происходит запуск редьюсера, который создает новый state.
|
|
|
|
+ //dispatch запускает всех подписчиков из массива cbs
|
|
|
|
+ store.dispatch({ type: 'КУПИТЬ', ШО: "пиво", СКОКА: 0 })
|
|
|
|
+
|
|
|
|
+ // const buy = (ШО, СКОКА) => ({ type: 'КУПИТЬ', ШО, СКОКА })
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ for (let [good, amount] of Object.entries(store.getState())) {
|
|
|
|
+ console.log(good, amount);
|
|
|
|
+ let p = document.createElement("p");
|
|
|
|
+ let p1 = document.createElement("p")
|
|
|
|
+ p.innerHTML = `Количество ${good}: ${amount.count}`;
|
|
|
|
+ p1.innerHTML = `(Цена-${amount.price})`
|
|
|
|
+ price.append(p1)
|
|
|
|
+ tovar.append(p);
|
|
|
|
+ buy.onclick = () => {
|
|
|
|
+ store.dispatch({ type: "КУПИТЬ", ШО: range.value, СКОКА: amount1.value });
|
|
|
|
+ kassa.innerHTML =
|
|
|
|
+ "Собираюсь построить Зикурат: " + store.getState().касса
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+ store.subscribe(
|
|
|
|
+ () =>
|
|
|
|
+ (p.innerHTML = `Количество ${good}: ${store.getState()[good].count
|
|
|
|
+ }`)
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ </script>
|
|
|
|
+
|
|
|
|
+</body>
|
|
|
|
+
|
|
|
|
+</html>
|