|
@@ -0,0 +1,99 @@
|
|
|
+<header>KIOSK</header>
|
|
|
+
|
|
|
+<body>
|
|
|
+ <script>
|
|
|
+ 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 в объект
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const seller = (state, { type, item, amount, cash, price }) => {
|
|
|
+ if (state === undefined) {
|
|
|
+ state = {
|
|
|
+ beer: { amount: 20, price: 10 },
|
|
|
+ vodka: { amount: 10, price: 30 },
|
|
|
+ cigars: { amount: 100, price: 20 },
|
|
|
+ cashbox: 0,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (type === 'BUY' &&
|
|
|
+ item in state &&
|
|
|
+ typeof amount == "number" &&
|
|
|
+ typeof cash == "number" &&
|
|
|
+ state[item].amount >= amount &&
|
|
|
+ amount > 0 &&
|
|
|
+ cash > 0 &&
|
|
|
+ state[item].price <= cash / amount) { //если тип action - КУПИТЬ, то:
|
|
|
+ /*let newState = {...state};
|
|
|
+ newState[item] = state[item].amount - amount;
|
|
|
+ newState.cashbox = state.cashbox + amount * price;
|
|
|
+ return newState;*/
|
|
|
+ return {
|
|
|
+ ...state, //берем все что было из ассортимента
|
|
|
+ [item]: { amount: state[item].amount - amount, price: state[item].price }, //и уменьшаем то, что покупается на количество
|
|
|
+ cashbox: state.cashbox + amount * state[item].price,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (type === 'SUPPLY' &&
|
|
|
+ typeof amount == "number" && amount > 0) {
|
|
|
+ let newState = { ...state };
|
|
|
+ let currItem = newState[item];
|
|
|
+ if (!currItem) {
|
|
|
+ if (typeof price != "number" || price <= 0)
|
|
|
+ return state;
|
|
|
+ newState[item] = { amount: 0, price: price };
|
|
|
+ }
|
|
|
+ else if (!(price === undefined))
|
|
|
+ return state;
|
|
|
+ newState[item] = { amount: newState[item].amount + amount, price: newState[item].price }; //и уменьшаем то, что покупается на количество
|
|
|
+ return newState;
|
|
|
+ }
|
|
|
+ return state;
|
|
|
+ }
|
|
|
+ let store = createStore(seller);
|
|
|
+ const unsubscribe = store.subscribe(() => console.log(store.getState()))
|
|
|
+
|
|
|
+ store.dispatch({ type: 'BUY', item: 'cigars', amount: 3, cash: 58 })
|
|
|
+ store.dispatch({ type: 'BUY', item: 'vodka', amount: 3, cash: 92 })
|
|
|
+ store.dispatch({ type: 'SUPPLY', item: 'vodka', amount: 5 })
|
|
|
+ store.dispatch({ type: 'SUPPLY', item: 'cukerky', amount: 5, price: 3 })
|
|
|
+
|
|
|
+
|
|
|
+ </script>
|
|
|
+</body>
|
|
|
+
|
|
|
+const store = createStore(reducer)
|
|
|
+
|
|
|
+//запомнит функцию во внутреннем массиве cbs.
|
|
|
+//она будет запущена при любом успешном dispatch
|
|
|
+const unsubscribe = store.subscribe(() => console.log(store.getState()))
|
|
|
+
|
|
|
+setTimeout(unsubscribe, 10000) //отпишемся через 10 секунд, например
|
|
|
+
|
|
|
+//происходит запуск редьюсера, который создает новый state.
|
|
|
+//dispatch запускает всех подписчиков из массива cbs
|
|
|
+store.dispatch({type: 'КУПИТЬ', ШО: 'пиво', СКОКА: 3})
|
|
|
+
|
|
|
+const купиПиваса = СКОКА => ({type: 'КУПИТЬ', ШО: 'пиво', СКОКА})
|
|
|
+const купиЧипсики = СКОКА => ({type: 'КУПИТЬ', ШО: 'чипсы', СКОКА})
|
|
|
+
|
|
|
+store.dispatch(купиПиваса(3))
|
|
|
+store.dispatch(купиЧипсики(6))
|
|
|
+store.dispatch(купиПиваса(30))
|