index.html 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <select name="" id="selectItems"></select>
  11. <input type="number" name="" id="inputAmountToBuy" />
  12. <button type="button" id="buyBtn">Buy</button>
  13. <div id="container">
  14. <table id="stateTable" border="1"></table>
  15. </div>
  16. <script>
  17. const store = createStore(reducer);
  18. for ([key, value] of Object.entries(store.getState()["продукты"])) {
  19. let option = document.createElement("option");
  20. option.innerText = key;
  21. option.value = key;
  22. selectItems.append(option);
  23. }
  24. const buyItem = (amount, item) => ({
  25. type: "КУПИТЬ",
  26. ШО: item,
  27. СКОКА: amount,
  28. });
  29. buyBtn.onclick = () => {
  30. let amount = inputAmountToBuy.value;
  31. let item = selectItems.value;
  32. store.dispatch(buyItem(amount, item));
  33. console.log(amount);
  34. };
  35. const updateTable = () => {
  36. let str = "<tr><th>Название</th><th>Количество</th><th>Цена</th></tr>";
  37. let state = store.getState();
  38. for ([key, value] of Object.entries(state["продукты"])) {
  39. str += `<tr><th>${key}</th><td>${value.amount}</td><td>${value.cost}</td></tr>`;
  40. }
  41. str += `<th>касса</th><td colspan = "2">${state["касса"]}</td></tr>`;
  42. stateTable.innerHTML = str;
  43. };
  44. store.subscribe(updateTable);
  45. store.subscribe(() => console.log(store.getState()));
  46. updateTable();
  47. function reducer(state, { type, ШО, СКОКА }) {
  48. //объект action деструктуризируется на три переменных
  49. if (!state) {
  50. //начальная уборка в ларьке:
  51. return {
  52. продукты: {
  53. пиво: { amount: 100, cost: 33 },
  54. чипсы: { amount: 100, cost: 13 },
  55. сиги: { amount: 100, cost: 43 },
  56. },
  57. касса: 0,
  58. };
  59. }
  60. if (type.toUpperCase() === "КУПИТЬ") {
  61. let products = state["продукты"];
  62. if (СКОКА <= 0 || СКОКА > state["продукты"][ШО]["amount"]) {
  63. return state;
  64. }
  65. return {
  66. ...state, //берем все что было из ассортимента
  67. ["продукты"]: {
  68. ...products,
  69. [ШО]: {
  70. ...products[ШО],
  71. amount: products[ШО]["amount"] - СКОКА,
  72. },
  73. },
  74. касса: +state["касса"] + +products[ШО]["cost"] * +СКОКА, //и уменьшаем то, что покупается на количество
  75. };
  76. }
  77. return state; //если мы не поняли, что от нас просят в `action` - оставляем все как есть
  78. }
  79. function createStore(reducer) {
  80. let state = reducer(undefined, {}); //стартовая инициализация состояния, запуск редьюсера со state === undefined
  81. let cbs = []; //массив подписчиков
  82. const getState = () => state; //функция, возвращающая переменную из замыкания
  83. const subscribe = (cb) => (
  84. cbs.push(cb), //запоминаем подписчиков в массиве
  85. () => (cbs = cbs.filter((c) => c !== cb))
  86. ); //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
  87. const dispatch = (action) => {
  88. const newState = reducer(state, action); //пробуем запустить редьюсер
  89. if (newState !== state) {
  90. //проверяем, смог ли редьюсер обработать action
  91. state = newState; //если смог, то обновляем state
  92. for (let cb of cbs) cb(); //и запускаем подписчиков
  93. }
  94. };
  95. return {
  96. getState, //добавление функции getState в результирующий объект
  97. dispatch,
  98. subscribe, //добавление subscribe в объект
  99. };
  100. }
  101. </script>
  102. </body>
  103. </html>