|
@@ -0,0 +1,152 @@
|
|
|
+const КУПИТЬ = 'КУПИТЬ'
|
|
|
+
|
|
|
+function reducer(state, { type, ШО, СКОКА, БАБЛО }) { //объект action деструктуризируется на три переменных
|
|
|
+ if (!state) { //начальная уборка в ларьке:
|
|
|
+ return {
|
|
|
+ пиво: {
|
|
|
+ quantity: 100,
|
|
|
+ price: 20
|
|
|
+ },
|
|
|
+ чипсы: {
|
|
|
+ quantity: 100,
|
|
|
+ price: 25
|
|
|
+ },
|
|
|
+ сиги: {
|
|
|
+ quantity: 100,
|
|
|
+ price: 60
|
|
|
+ },
|
|
|
+ сникерс: {
|
|
|
+ quantity: 100,
|
|
|
+ price: 15
|
|
|
+ },
|
|
|
+ вода: {
|
|
|
+ quantity: 100,
|
|
|
+ price: 10
|
|
|
+ },
|
|
|
+ касса: 0,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type === КУПИТЬ) { //если тип action - КУПИТЬ, то:
|
|
|
+ if ((state[ШО].quantity - СКОКА) < 0) {
|
|
|
+ alert('упс, вы ушли в минус, введите корректное количество')
|
|
|
+ return {
|
|
|
+ ...state, //берем все что было из ассортимента
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (БАБЛО < state[ШО].price * СКОКА) {
|
|
|
+ alert('упс, НЕ ХВАТАЕТ БАБЛА')
|
|
|
+ return {
|
|
|
+ ...state, //берем все что было из ассортимента
|
|
|
+ }
|
|
|
+ } else if ((БАБЛО > 0) && (СКОКА > 0)) {
|
|
|
+ {
|
|
|
+ return {
|
|
|
+ ...state, //берем все что было из ассортимента
|
|
|
+ [ШО]: {
|
|
|
+ ...state[ШО],
|
|
|
+ quantity: state[ШО].quantity - СКОКА
|
|
|
+ },
|
|
|
+ касса: state.касса + state[ШО].price * СКОКА,
|
|
|
+ БАБЛО: БАБЛО - state[ШО].price * СКОКА
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ } 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)
|
|
|
+store.subscribe(() => console.log(store.getState()))
|
|
|
+
|
|
|
+let selectProduct = document.createElement('select')
|
|
|
+selectProduct.id = "select"
|
|
|
+let input = document.createElement('input')
|
|
|
+input.placeholder = "quantity"
|
|
|
+input.type = "number"
|
|
|
+input.min = 0
|
|
|
+document.body.appendChild(input)
|
|
|
+let inputMoney = document.createElement('input')
|
|
|
+inputMoney.placeholder = "money"
|
|
|
+inputMoney.type = "number"
|
|
|
+inputMoney.min = 0
|
|
|
+document.body.appendChild(inputMoney)
|
|
|
+
|
|
|
+for (let key in (store.getState())) {
|
|
|
+ let option = document.createElement('option')
|
|
|
+ option.innerHTML = key
|
|
|
+ selectProduct.appendChild(option)
|
|
|
+}
|
|
|
+document.body.appendChild(selectProduct)
|
|
|
+let br = document.createElement("br")
|
|
|
+let table = document.createElement("table")
|
|
|
+document.body.append(table)
|
|
|
+
|
|
|
+function createTable() {
|
|
|
+ table.innerHTML = ""
|
|
|
+ for (let [keyName, storeValue] of Object.entries(store.getState())) {
|
|
|
+ let tr = document.createElement('tr')
|
|
|
+
|
|
|
+ if (typeof storeValue === "object") {
|
|
|
+ let thProduct = document.createElement('th')
|
|
|
+ thProduct.innerHTML = `${keyName}`
|
|
|
+ tr.appendChild(thProduct)
|
|
|
+
|
|
|
+ for (let [key, value] of Object.entries(storeValue)) {
|
|
|
+ let thKey = document.createElement('th')
|
|
|
+ let thValue = document.createElement('td')
|
|
|
+ thKey.innerHTML = ` ${key}`;
|
|
|
+ thValue.innerHTML = `${value}`
|
|
|
+ tr.appendChild(thKey)
|
|
|
+ tr.appendChild(thValue)
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ let thKey2 = document.createElement('th')
|
|
|
+ let thValue2 = document.createElement('td')
|
|
|
+ thKey2.innerHTML = `${keyName}`;
|
|
|
+ thValue2.innerHTML = ` ${storeValue}`
|
|
|
+ tr.appendChild(thKey2)
|
|
|
+ tr.appendChild(thValue2)
|
|
|
+ }
|
|
|
+ table.append(tr)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+createTable()
|
|
|
+store.subscribe(() => createTable())
|
|
|
+let labelProduct = document.createElement('label')
|
|
|
+document.body.appendChild(br)
|
|
|
+document.body.appendChild(labelProduct)
|
|
|
+
|
|
|
+let btn = document.getElementById("btn")
|
|
|
+btn.onclick = (e) => {
|
|
|
+ store.dispatch({ type: КУПИТЬ, ШО: selectProduct.value, СКОКА: input.value, БАБЛО: inputMoney.value })
|
|
|
+}
|