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 reducer(state, {type, productName, productAmount, summ}){ if (!state){ //начальная уборка в ларьке: return { пиво: { amount: 100, price: 35, }, чипсы: { amount: 100, price: 28, }, сиги: { amount: 100, price: 90, }, касса: 0 } } if (type === 'Купить' && productAmount <= state[productName].amount && summ >= state[productName].price * productAmount){ //если тип action - КУПИТЬ, то: return { ...state, //берем все что было из ассортимента [productName]: { amount: state[productName].amount - productAmount, price: state[productName].price }, касса: state.касса + state[productName].price * productAmount //и уменьшаем то, что покупается на количество } } return state //если мы не поняли, что от нас просят в `action` - оставляем все как есть } function actionCreator (type, productName, productAmount, summ){ return { type, productName, productAmount, summ } } let store = createStore(reducer); myState = store.getState() const showCase = document.createElement('section') document.body.append(showCase) showCase.classList.add('showCase') const productSelect = document.createElement('select') document.body.append(productSelect) const productQuantityOrderTitle = document.createElement('div') productQuantityOrderTitle.innerText = 'Количество:' document.body.append(productQuantityOrderTitle) const productQuantityInput = document.createElement('input') productQuantityInput.type = 'number' productQuantityInput.min = '0' document.body.append(productQuantityInput) const moneyTitle = document.createElement('div') moneyTitle.innerText = 'Деньги:' document.body.append(moneyTitle) const money = document.createElement('input') money.type = 'number' money.min = '0' document.body.append(money) const buttonBuy = document.createElement('button') buttonBuy.value = 'Купить' buttonBuy.innerText = 'Купить' document.body.append(buttonBuy) buttonBuy.onclick = () => { store.dispatch(actionCreator(buttonBuy.value, productSelect.value, +productQuantityInput.value, +money.value)) } for (const product in store.getState()){ if (product === 'касса') continue const productCard = document.createElement('div') productCard.classList.add('productCard') const productName = document.createElement('h2') productName.innerText = product productName.classList.add('productName') const productPrice = document.createElement('div') productPrice.innerText = store.getState()[product].price + ' грн' productPrice.classList.add('productPrice') const productAmount = document.createElement('div') productAmount.innerText = store.getState()[product].amount + ' шт' productAmount.classList.add('productQuantity') productCard.append(productName, productAmount, productPrice) showCase.append(productCard) const productOption = document.createElement('option') productOption.value = productOption.innerText = product productSelect.append(productOption) const productPriceUnsubscribe = store.subscribe( () => { productPrice.innerText = store.getState()[product].price + ' грн' }) const productQuantityUnsubscribe = store.subscribe( () => { productAmount.innerText = store.getState()[product].amount + ' шт' } ) }