main.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. //debugger;
  2. function createStore(reducer){
  3. let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
  4. let cbs = [] //массив подписчиков
  5. const getState = () => state //функция, возвращающая переменную из замыкания
  6. const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
  7. () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
  8. const dispatch = action => {
  9. const newState = reducer(state, action) //пробуем запустить редьюсер
  10. if (newState !== state){ //проверяем, смог ли редьюсер обработать action
  11. state = newState //если смог, то обновляем state
  12. for (let cb of cbs) cb() //и запускаем подписчиков
  13. }
  14. }
  15. return {
  16. getState, //добавление функции getState в результирующий объект
  17. dispatch,
  18. subscribe //добавление subscribe в объект
  19. }
  20. }
  21. function reducer(state, {type, ШО, СКОКА, БАБЛО}){ //объект action деструктуризируется на три переменных
  22. if (!state){ //начальная уборка в ларьке:
  23. return {
  24. пиво: {count: 100, price: 30},
  25. чипсы:{count: 100, price: 25},
  26. сиги: {count: 100, price: 35},
  27. касса:{count: 0, change: 0}, // касса: 0, при покупках увеличивается
  28. }
  29. }
  30. if (type === 'КУПИТЬ'){ //если тип action - КУПИТЬ, то:
  31. //проверить на:
  32. //наличие товара как такового (есть ли ключ в объекте)
  33. //количество денег в action
  34. //наличие нужного количества товара.
  35. //и только при соблюдении этих условий обновлять state.
  36. if((state[ШО]['count'] - СКОКА) < 0 ) {
  37. const div = document.getElementById('message');
  38. div.innerText = `столько ${ШО} нет в наличии, есть ${state[ШО]['count']}`;
  39. setTimeout( () => div.innerText = '', 2500);
  40. return state;
  41. }
  42. if ((БАБЛО - СКОКА* state[ШО]['price']) < 0) {
  43. const div = document.getElementById('message');
  44. div.innerText = `надо добавитть ${СКОКА * state[ШО]['price'] - БАБЛО} грн.`;
  45. setTimeout( () => div.innerText = '', 2500);
  46. return state;
  47. }
  48. if (state[ШО]) {
  49. return {
  50. ...state, //берем все что было из ассортимента
  51. [ШО]: {
  52. ...state[ШО],
  53. count: state[ШО]['count'] - СКОКА,
  54. } ,
  55. ['касса']: {
  56. ...state['касса'],
  57. count: state['касса']['count'] + (СКОКА * state[ШО]['price']),
  58. change: БАБЛО - СКОКА * state[ШО]['price'],
  59. } //и уменьшаем то, что покупается на количество
  60. }
  61. }
  62. }
  63. return state //если мы не поняли, что от нас просят в `action` - оставляем все как есть
  64. }
  65. const store = createStore(reducer);
  66. for (let [key, value] of Object.entries(store.getState())) {
  67. if(key === 'касса') {
  68. continue;
  69. }
  70. let option = document.createElement('option');
  71. option.innerHTML = `${key}`;
  72. goods.append(option);
  73. }
  74. function viewStore () {
  75. const table = document.createElement('table');
  76. table.id = 'table';
  77. document.body.prepend(table);
  78. const tr = document.createElement('tr');
  79. table.append(tr);
  80. const th1 = document.createElement('th');
  81. th1.innerText = 'Товар';
  82. tr.append(th1);
  83. const th2 = document.createElement('th');
  84. th2.innerText = 'Количество товара';
  85. tr.append(th2);
  86. const th3 = document.createElement('th');
  87. th3.innerText = 'Цена';
  88. tr.append(th3);
  89. for (let [key, value] of Object.entries(store.getState())) {
  90. const tr = document.createElement('tr');
  91. const th = document.createElement('th');
  92. th.style.width = '150px';
  93. table.append(tr);
  94. tr.appendChild(th).innerHTML = `${key}`;
  95. for (let [key1, value1] of Object.entries(value)) {
  96. const td = document.createElement('td');
  97. td.style.width = '70px';
  98. tr.appendChild(td).innerHTML =`${value1}`;
  99. }
  100. }
  101. }
  102. viewStore();
  103. function deleteTable () {
  104. const table = document.getElementById('table');
  105. table.remove();
  106. }
  107. store.subscribe(deleteTable);
  108. store.subscribe(viewStore);
  109. //надо бы напилить цикл, который в select напихивает ассортимент.
  110. //возможно, если вы собираетесь выводить (и обновлять) количество,
  111. //это надо делать где в subscribe, иначе оно не будет обновлять количество
  112. const купи = (ШО, СКОКА, БАБЛО) => ({type: 'КУПИТЬ', ШО, СКОКА, БАБЛО});
  113. buy.onclick = () => {
  114. let select = document.getElementById('goods');
  115. let valueSelect = select.options[select.selectedIndex].text;
  116. let input = document.getElementById('quantity');
  117. let valueInput = input.value;
  118. let cash = document.getElementById('cash').value;
  119. store.dispatch({type:'КУПИТЬ', ШО: `${valueSelect}`, СКОКА: `${valueInput}`, БАБЛО: `${cash}`});
  120. setTimeout(() => document.getElementById('quantity').value = '', 2500);
  121. setTimeout(() => document.getElementById('cash').value = '', 2500);
  122. };
  123. //достает выбранный товар и количество из DOM +
  124. // store.dispatch(купи(....,....)) +
  125. //запомнит функцию во внутреннем массиве cbs.
  126. //она будет запущена при любом успешном dispatch
  127. const unsubscribe = store.subscribe(() => console.log(store.getState()))
  128. //setTimeout(unsubscribe, 10000) //отпишемся через 10 секунд, например
  129. //происходит запуск редьюсера, который создает новый state.
  130. //dispatch запускает всех подписчиков из массива cbs
  131. // function smth(){
  132. // const h1 = document.createElement('h1')
  133. // shop.append(h1)
  134. // store.subscribe(() => h1.innerText = store.getState().пиво)
  135. // h1.innerText = store.getState().пиво
  136. // }
  137. // smth()
  138. // smth()
  139. //setTimeout(() => store.dispatch({type: 'КУПИТЬ', ШО: 'пиво', СКОКА: 3}), 5000)