function reducer(state, {type, productName, productQuantity, summ}){ //объект action деструктуризируется на три переменных if (!state){ //начальная уборка в ларьке: return { пиво: { quantity: 100, price: 30, }, чипсы: { quantity: 100, price: 52, }, сиги: { quantity: 100, price: 89, }, касса: 0 } } if (type === 'КУПИТЬ' && productQuantity <= state[productName].quantity && summ >= state[productName].price * productQuantity){ //если тип action - КУПИТЬ, то: return { ...state, //берем все что было из ассортимента [productName]: { quantity: state[productName].quantity - productQuantity, price: state[productName].price }, касса: state.касса + state[productName].price * productQuantity //и уменьшаем то, что покупается на количество } } 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 в объект } } function actionCreator (type, productName, productQuantity, summ){ return { type, productName, productQuantity, summ } } const store = createStore(reducer) myState = store.getState() const showcase = document.createElement('section') document.body.append(showcase) showcase.classList.add('showcase') const orderSection = document.createElement('section') document.body.append(orderSection) orderSection.classList.add('orderSection') const orderSelectProd = document.createElement('select') orderSection.append(orderSelectProd) const orderInputQuantity = document.createElement('input') orderInputQuantity.type = 'number' orderInputQuantity.min = '0' orderSection.append(orderInputQuantity) const orderInputQuantityName = document.createElement('div') orderInputQuantity.before(orderInputQuantityName) orderInputQuantityName.innerText = 'количество товара:' const orderSendMoney = document.createElement('input') orderSendMoney.type = 'number' orderSendMoney.min = '0' orderSection.append(orderSendMoney) const orderSendMoneyName = document.createElement('div') orderSendMoney.before(orderSendMoneyName) orderSendMoneyName.innerText = 'сумма:' const orderBuyButton = document.createElement('input') orderBuyButton.type = 'button' orderBuyButton.value = 'КУПИТЬ' orderSection.append(orderBuyButton) orderBuyButton.onclick = () => { store.dispatch( actionCreator(orderBuyButton.value, orderSelectProd.value, +orderInputQuantity.value, +orderSendMoney.value ) ) } for (const elemProduct in store.getState()){ if (elemProduct === 'касса') continue const productCard = document.createElement('div') const productName = document.createElement('h2') const productPrice = document.createElement('div') const productQuantity = document.createElement('div') productCard.append(productName) productCard.append(productQuantity) productCard.append(productPrice) showcase.append(productCard) productCard.classList.add('productCard') productName.classList.add('productName') productPrice.classList.add('productPrice') productQuantity.classList.add('productQuantity') productName.innerText = elemProduct productPrice.innerText = store.getState()[elemProduct].price + ' грн' productQuantity.innerText = store.getState()[elemProduct].quantity + ' шт\nв наличии' const selectProdOption = document.createElement('option') selectProdOption.value = selectProdOption.innerText = elemProduct orderSelectProd.append(selectProdOption) const productPriceUnsubscribe = store.subscribe( () => { productPrice.innerText = store.getState()[elemProduct].price + ' грн' } ) const productQuantityUnsubscribe = store.subscribe( () => { productQuantity.innerText = store.getState()[elemProduct].quantity + ' шт\nв наличии' } ) }