Browse Source

HW_13 (redux) done

Graf15 2 years ago
parent
commit
8dc03bc8fe
3 changed files with 213 additions and 0 deletions
  1. 16 0
      js/js_13_redux/index.html
  2. 140 0
      js/js_13_redux/index.js
  3. 57 0
      js/js_13_redux/style.css

+ 16 - 0
js/js_13_redux/index.html

@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="stylesheet" href="style.css">
+    <title>Document</title>
+    
+</head>
+<body>
+    <script src="index.js"></script>
+</body>
+
+</body>
+</html>

+ 140 - 0
js/js_13_redux/index.js

@@ -0,0 +1,140 @@
+
+function reducer(state, {type, productName, productQuantity, summ}){ //объект action деструктуризируется на три переменных
+    if (!state){ //начальная уборка в ларьке:
+        return {
+            пиво: {
+                quantity: 100,
+                price: 30,
+            },
+            чипсы: {
+                quantity: 100,
+                price: 52,
+            },
+            сиги: {
+                quantity: 100,
+                price: 89,
+            },
+            касса: 0
+        }
+    }
+    if (type === 'КУПИТЬ' && productQuantity <= state[productName].quantity && summ >= state[productName].price * productQuantity){ //если тип action - КУПИТЬ, то:
+        return {
+            ...state, //берем все что было из ассортимента
+            [productName]: {
+                quantity: state[productName].quantity - productQuantity,
+                price: state[productName].price
+            },
+            касса: state.касса + state[productName].price * productQuantity
+              //и уменьшаем то, что покупается на количество
+        }
+    }
+
+    return state //если мы не поняли, что от нас просят в `action` - оставляем все как есть
+}
+
+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 actionCreator (type, productName, productQuantity, summ){
+    return {
+        type,
+        productName,
+        productQuantity,
+        summ
+    }
+}
+
+const store = createStore(reducer)
+myState = store.getState()
+
+const showcase = document.createElement('section')
+document.body.append(showcase)
+showcase.classList.add('showcase')
+
+const orderSection = document.createElement('section')
+document.body.append(orderSection)
+orderSection.classList.add('orderSection')
+
+const orderSelectProd = document.createElement('select')
+orderSection.append(orderSelectProd)
+
+const orderInputQuantity = document.createElement('input')
+orderInputQuantity.type = 'number'
+orderInputQuantity.min = '0'
+orderSection.append(orderInputQuantity)
+
+const orderInputQuantityName  = document.createElement('div')
+orderInputQuantity.before(orderInputQuantityName)
+orderInputQuantityName.innerText = 'количество товара:'
+
+const orderSendMoney = document.createElement('input')
+orderSendMoney.type = 'number'
+orderSendMoney.min = '0'
+orderSection.append(orderSendMoney)
+
+const orderSendMoneyName  = document.createElement('div')
+orderSendMoney.before(orderSendMoneyName)
+orderSendMoneyName.innerText = 'сумма:'
+
+const orderBuyButton = document.createElement('input')
+orderBuyButton.type = 'button'
+orderBuyButton.value = 'КУПИТЬ'
+orderSection.append(orderBuyButton)
+orderBuyButton.onclick = () => { store.dispatch( actionCreator(orderBuyButton.value, orderSelectProd.value, +orderInputQuantity.value, +orderSendMoney.value ) ) }
+
+
+for (const elemProduct in store.getState()){
+    if (elemProduct === 'касса') continue
+
+    const productCard = document.createElement('div')
+    const productName = document.createElement('h2')
+    const productPrice = document.createElement('div')
+    const productQuantity = document.createElement('div')
+    
+    productCard.append(productName)
+    productCard.append(productQuantity)
+    productCard.append(productPrice)
+    showcase.append(productCard)
+
+    productCard.classList.add('productCard')
+    productName.classList.add('productName')
+    productPrice.classList.add('productPrice')
+    productQuantity.classList.add('productQuantity')
+
+    productName.innerText = elemProduct
+    productPrice.innerText = store.getState()[elemProduct].price + ' грн'
+    productQuantity.innerText = store.getState()[elemProduct].quantity + ' шт\nв наличии'
+
+    const selectProdOption = document.createElement('option')
+    selectProdOption.value = selectProdOption.innerText = elemProduct
+    orderSelectProd.append(selectProdOption)
+    const productPriceUnsubscribe = store.subscribe( () => {
+        productPrice.innerText = store.getState()[elemProduct].price + ' грн'    
+    } )
+    const productQuantityUnsubscribe = store.subscribe( () => {
+        productQuantity.innerText = store.getState()[elemProduct].quantity + ' шт\nв наличии'
+    } )
+
+}
+
+

+ 57 - 0
js/js_13_redux/style.css

@@ -0,0 +1,57 @@
+*,
+*:before,
+*:after {
+  box-sizing: border-box;
+}
+
+body {
+    margin: 0;
+    height: 100vh;
+    background-color: darkgrey;
+
+}
+
+.productCard{
+  padding: 10px;
+  margin: 20px;
+  width: 200px;
+  background-color: azure;
+  border-radius: 10px;
+}
+
+.productName{
+  text-align: center;
+  background-color: rgb(231, 30, 8);
+  padding: 5px;
+  color: white;
+  border-radius: 5px;
+  margin-top: 0px;
+}
+
+.productPrice{
+  text-align: center;
+  padding: 8px;
+  background-color: green;
+  color: white;
+  border-radius: 5px;
+}
+
+.showcase{
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.productQuantity{
+  padding: 10px 0px 50px;
+  text-align: center;
+}
+
+.orderSection{
+  display: flex;
+  justify-content: center;
+}
+
+.orderSection * {
+margin: 10px
+}