|
@@ -0,0 +1,170 @@
|
|
|
+//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)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|