123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- //debugger;
- 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, ШО, СКОКА, БАБЛО}){ //объект action деструктуризируется на три переменных
- if (!state){ //начальная уборка в ларьке:
- return {
- пиво: {count: 100, price: 30},
- чипсы:{count: 100, price: 25},
- сиги: {count: 100, price: 35},
- касса:{count: 0, change: 0}, // касса: 0, при покупках увеличивается
- }
- }
- if (type === 'КУПИТЬ'){ //если тип action - КУПИТЬ, то:
- //проверить на:
- //наличие товара как такового (есть ли ключ в объекте)
- //количество денег в action
- //наличие нужного количества товара.
- //и только при соблюдении этих условий обновлять state.
- if((state[ШО]['count'] - СКОКА) < 0 ) {
- const div = document.getElementById('message');
- div.innerText = `столько ${ШО} нет в наличии, есть ${state[ШО]['count']}`;
- setTimeout( () => div.innerText = '', 2500);
- return state;
- }
- if ((БАБЛО - СКОКА* state[ШО]['price']) < 0) {
- const div = document.getElementById('message');
- div.innerText = `надо добавитть ${СКОКА * state[ШО]['price'] - БАБЛО} грн.`;
- setTimeout( () => div.innerText = '', 2500);
- return state;
- }
- if (state[ШО]) {
- return {
- ...state, //берем все что было из ассортимента
- [ШО]: {
- ...state[ШО],
- count: state[ШО]['count'] - СКОКА,
- } ,
- ['касса']: {
- ...state['касса'],
- count: state['касса']['count'] + (СКОКА * state[ШО]['price']),
- change: БАБЛО - СКОКА * state[ШО]['price'],
- } //и уменьшаем то, что покупается на количество
- }
- }
- }
- return state //если мы не поняли, что от нас просят в `action` - оставляем все как есть
- }
- const store = createStore(reducer);
- for (let [key, value] of Object.entries(store.getState())) {
- if(key === 'касса') {
- continue;
- }
- let option = document.createElement('option');
- option.innerHTML = `${key}`;
- goods.append(option);
- }
- function viewStore () {
- const table = document.createElement('table');
- table.id = 'table';
- document.body.prepend(table);
- const tr = document.createElement('tr');
- table.append(tr);
- const th1 = document.createElement('th');
- th1.innerText = 'Товар';
- tr.append(th1);
- const th2 = document.createElement('th');
- th2.innerText = 'Количество товара';
- tr.append(th2);
- const th3 = document.createElement('th');
- th3.innerText = 'Цена';
- tr.append(th3);
- for (let [key, value] of Object.entries(store.getState())) {
-
- const tr = document.createElement('tr');
- const th = document.createElement('th');
- th.style.width = '150px';
- table.append(tr);
- tr.appendChild(th).innerHTML = `${key}`;
- for (let [key1, value1] of Object.entries(value)) {
- const td = document.createElement('td');
- td.style.width = '70px';
- tr.appendChild(td).innerHTML =`${value1}`;
- }
- }
- }
- viewStore();
- function deleteTable () {
- const table = document.getElementById('table');
- table.remove();
- }
- store.subscribe(deleteTable);
- store.subscribe(viewStore);
- //надо бы напилить цикл, который в select напихивает ассортимент.
- //возможно, если вы собираетесь выводить (и обновлять) количество,
- //это надо делать где в subscribe, иначе оно не будет обновлять количество
- const купи = (ШО, СКОКА, БАБЛО) => ({type: 'КУПИТЬ', ШО, СКОКА, БАБЛО});
- buy.onclick = () => {
- let select = document.getElementById('goods');
- let valueSelect = select.options[select.selectedIndex].text;
- let input = document.getElementById('quantity');
- let valueInput = input.value;
- let cash = document.getElementById('cash').value;
- store.dispatch({type:'КУПИТЬ', ШО: `${valueSelect}`, СКОКА: `${valueInput}`, БАБЛО: `${cash}`});
- setTimeout(() => document.getElementById('quantity').value = '', 2500);
- setTimeout(() => document.getElementById('cash').value = '', 2500);
- };
-
- //достает выбранный товар и количество из DOM +
- // store.dispatch(купи(....,....)) +
- //запомнит функцию во внутреннем массиве cbs.
- //она будет запущена при любом успешном dispatch
- const unsubscribe = store.subscribe(() => console.log(store.getState()))
- //setTimeout(unsubscribe, 10000) //отпишемся через 10 секунд, например
- //происходит запуск редьюсера, который создает новый state.
- //dispatch запускает всех подписчиков из массива cbs
- // function smth(){
- // const h1 = document.createElement('h1')
- // shop.append(h1)
- // store.subscribe(() => h1.innerText = store.getState().пиво)
- // h1.innerText = store.getState().пиво
- // }
- // smth()
- // smth()
- //setTimeout(() => store.dispatch({type: 'КУПИТЬ', ШО: 'пиво', СКОКА: 3}), 5000)
|