index.html 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <header>KIOSK</header>
  2. <body>
  3. <script>
  4. const addCell = (row, value) => {
  5. let cell = document.createElement("td");
  6. cell.innerText = value;
  7. row.append(cell);
  8. return cell;
  9. }
  10. const createAssortTable = (store) => {
  11. let state = store.getState();
  12. let table = document.createElement("table");
  13. let row = document.createElement("tr");
  14. table.append(row);
  15. addCell(row, "NAME");
  16. addCell(row, "PRICE");
  17. addCell(row, "AMOUNT");
  18. for (const itemKey in state) {
  19. if (itemKey == "cashbox")
  20. continue;
  21. let item = state[itemKey];
  22. let row = document.createElement("tr");
  23. table.append(row);
  24. addCell(row, itemKey);
  25. addCell(row, item.price);
  26. let amountVal = addCell(row, item.amount);
  27. store.subscribe(() => {
  28. const state = store.getState();
  29. const item = state[itemKey];
  30. const amount = item.amount;
  31. amountVal.innerText = amount;
  32. });
  33. //store.getState()[itemKey].amount);
  34. }
  35. return table;
  36. }
  37. const createSale = (store) => {
  38. let state = store.getState();
  39. let resDiv = document.createElement("div")
  40. let select = document.createElement("select");
  41. resDiv.append(select);
  42. for (itemKey in state) {
  43. if (itemKey == "cashbox")
  44. continue;
  45. let option = document.createElement("option");
  46. option.value = itemKey;
  47. option.text = itemKey;
  48. select.append(option);
  49. }
  50. select.onchange = () => {
  51. priceDiv.innerText = state[select.value].price;
  52. }
  53. let priceDiv = document.createElement("div");
  54. priceDiv.innerText = state[select.value].price;
  55. resDiv.append(priceDiv);
  56. let amountInp = document.createElement("input");
  57. amountInp.value = 0;
  58. resDiv.append(amountInp);
  59. let cashInp = document.createElement("input");
  60. cashInp.value = 0;
  61. resDiv.append(cashInp);
  62. let buyBtn = document.createElement("button");
  63. buyBtn.innerText = "BUY";
  64. buyBtn.onclick = () => {
  65. store.dispatch({ type: 'BUY', item: select.value, amount: +amountInp.value, cash: +cashInp.value });
  66. }
  67. resDiv.append(buyBtn);
  68. return resDiv;
  69. }
  70. function createStore(reducer) {
  71. let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
  72. let cbs = [] //массив подписчиков
  73. const getState = () => state //функция, возвращающая переменную из замыкания
  74. const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
  75. () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
  76. const dispatch = action => {
  77. const newState = reducer(state, action) //пробуем запустить редьюсер
  78. if (newState !== state) { //проверяем, смог ли редьюсер обработать action
  79. state = newState //если смог, то обновляем state
  80. for (let cb of cbs) cb() //и запускаем подписчиков
  81. }
  82. }
  83. return {
  84. getState, //добавление функции getState в результирующий объект
  85. dispatch,
  86. subscribe //добавление subscribe в объект
  87. }
  88. }
  89. const seller = (state, { type, item, amount, cash, price }) => {
  90. if (state === undefined) {
  91. state = {
  92. beer: { amount: 20, price: 10 },
  93. vodka: { amount: 10, price: 30 },
  94. cigars: { amount: 100, price: 20 },
  95. cashbox: 0,
  96. }
  97. }
  98. if (type === 'BUY' &&
  99. item in state &&
  100. typeof amount == "number" &&
  101. typeof cash == "number" &&
  102. state[item].amount >= amount &&
  103. amount > 0 &&
  104. cash > 0 &&
  105. state[item].price <= cash / amount) { //если тип action - КУПИТЬ, то:
  106. /*let newState = {...state};
  107. newState[item] = state[item].amount - amount;
  108. newState.cashbox = state.cashbox + amount * price;
  109. return newState;*/
  110. return {
  111. ...state, //берем все что было из ассортимента
  112. [item]: { amount: state[item].amount - amount, price: state[item].price }, //и уменьшаем то, что покупается на количество
  113. cashbox: state.cashbox + amount * state[item].price,
  114. }
  115. }
  116. if (type === 'SUPPLY' &&
  117. typeof amount == "number" && amount > 0) {
  118. let newState = { ...state };
  119. let currItem = newState[item];
  120. if (!currItem) {
  121. if (typeof price != "number" || price <= 0)
  122. return state;
  123. newState[item] = { amount: 0, price: price };
  124. }
  125. else if (!(price === undefined))
  126. return state;
  127. newState[item] = { amount: newState[item].amount + amount, price: newState[item].price }; //и уменьшаем то, что покупается на количество
  128. return newState;
  129. }
  130. return state;
  131. }
  132. let store = createStore(seller);
  133. const unsubscribe = store.subscribe(() => console.log(store.getState()))
  134. /*store.dispatch({ type: 'BUY', item: 'cigars', amount: 3, cash: 58 })
  135. store.dispatch({ type: 'BUY', item: 'vodka', amount: 3, cash: 92 })
  136. store.dispatch({ type: 'SUPPLY', item: 'vodka', amount: 5 })
  137. store.dispatch({ type: 'SUPPLY', item: 'cukerky', amount: 5, price: 3 })*/
  138. document.body.append(createAssortTable(store));
  139. document.body.append(document.createElement("br"));
  140. document.body.append(createSale(store));
  141. </script>
  142. </body>
  143. <footer>
  144. </footer>