Browse Source

HW add registration, login, logout, cart and order history (dashboard) pages

LenDoc 2 years ago
parent
commit
fc36f28264
2 changed files with 880 additions and 0 deletions
  1. 158 0
      js/17/index.html
  2. 722 0
      js/17/index.js

+ 158 - 0
js/17/index.html

@@ -0,0 +1,158 @@
+<!DOCTYPE HTML>
+<html>
+    <head>
+        <title> SHOP </title>
+        <meta charset='utf8' />
+        <style>
+            body{
+                font-size: medium;
+                font-family: serif;
+                margin: 10px;
+                padding: 10px; 
+                color: rgb(6, 58, 55);
+                background-color: rgb(204, 241, 255);
+            }
+            h1{
+                color: rgb(19, 98, 104)
+            }
+            span {
+      color:  rgb(19, 98, 104)
+            }
+            strong{
+                text-align: center;
+                font-size: bold;
+                background:#feffc4;
+                color: #051d05;
+                padding: 3px;
+                margin: 50px 0;
+                text-align: center; 
+            }
+            #mainContainer {
+                display: flex;
+                background-color: rgba(255, 255, 255, 0.76);
+            }
+            #aside {
+                width: 30%;
+            }
+            
+            #aside > a{
+                display: block;
+            }
+            .btn {
+                display: inline-block;
+                vertical-align: middle;
+                float: right;
+                background-color: rgb(236, 206, 245);
+                border-radius: 10px;
+                padding: 20px;
+                margin-left: 10px
+            }
+            img{
+                width: 40%;
+                height: 40%;
+            }
+            a{ 
+                font-weight: bold;
+                display: flex;
+                flex-direction: column;
+                flex-wrap: wrap;
+                color: rgb(53, 40, 40);
+                text-decoration: none;
+                  padding-bottom: 2px;
+    
+            }
+            a:hover{
+                border-bottom: 4px solid rgb(130, 30, 180);
+                text-decoration: underline;
+                color: rgb(95, 23, 131);
+            }
+            
+            input {
+                display: flex;
+                flex-direction: column;
+                border: 2px solid rgb(9, 52, 71);
+                border-radius: 4px;
+                margin: 10px;
+                padding: 10px;
+            }
+
+            input[type=text]:focus {
+                background-color: rgb(131, 187, 206);
+            }
+
+            button {
+                margin: 10px;
+                padding: 10px;
+               
+                cursor: pointer;
+                border-radius: 50px;
+                text-align: center;
+                background-color: rgb(156, 255, 153);
+             
+            }
+
+            button:hover {
+                box-shadow: 0 12px 16px 0 rgba(31, 240, 12, 0.452);
+            }
+            button.deleteBtn{
+               
+                background-color: rgb(185, 31, 25);
+                color:white;
+                
+            }
+            
+            .deleteBtn:hover {
+                box-shadow: 0 12px 16px 0 rgba(240, 12, 12, 0.452);
+            }
+            .cart{
+               /* display: flex;
+                flex-direction: row;
+               
+                justify-content: flex-start;
+                margin: 20px;
+                padding: 15px; */
+                margin-bottom: 20px;
+            }
+            .forCart{
+                width: 30%;
+                height: 30%;
+            }
+            .count{
+                display: inline-flex;
+                width:10%;
+                height: 10%;
+            }
+            .order{
+                width: 100%;
+            }
+
+            .clear{
+                background-color: rgb(66, 70, 73);
+                color:white;  
+            }
+            .clear:hover {
+                box-shadow: 0 12px 16px 0 rgba(63, 59, 59, 0.452);
+            }
+
+        </style>
+    </head>
+    <body>
+        <header>
+            <div id='cartIcon'></div>
+            <a id="signIn" class ="btn" href = "#/login/" > Sign In </a>
+            <a id = "register" class="btn" href = "#/register/" > Register</a>
+            <a id = "logOut" class="btn" href = "#/logout/" > Log Out</a>
+            <a id = "cart" class="btn" href = "#/cart/" > Cart </a>
+            <a id = "dashboard" class="btn" href = "#/dashboard/" > Dashboard </a>
+        </header>
+        <div id='mainContainer'>
+            <aside id='aside'>
+                Категории
+            </aside>
+            <main id='main'>
+                Контент
+            </main>
+        </div>
+        <script src="index.js"></script>
+    </body>
+</html>

+ 722 - 0
js/17/index.js

@@ -0,0 +1,722 @@
+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) => {
+    if (typeof action === "function") {
+      //если action - не объект, а функция
+      return action(dispatch, getState); //запускаем эту функцию и даем ей dispatch и getState для работы
+    }
+    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 promiseReducer(state = {}, { type, name, status, payload, error }) {
+  if (type === "PROMISE") {
+    return {
+      ...state,
+      [name]: { status, payload, error },
+    };
+  }
+  return state;
+}
+
+const actionPending = (name) => ({ type: "PROMISE", name, status: "PENDING" });
+const actionFulfilled = (name, payload) => ({
+  type: "PROMISE",
+  name,
+  status: "FULFILLED",
+  payload,
+});
+const actionRejected = (name, error) => ({
+  type: "PROMISE",
+  name,
+  status: "REJECTED",
+  error,
+});
+const actionPromise = (name, promise) => async (dispatch) => {
+  dispatch(actionPending(name));
+  try {
+    let payload = await promise;
+    dispatch(actionFulfilled(name, payload));
+    return payload;
+  } catch (error) {
+    dispatch(actionRejected(name, error));
+  }
+};
+
+const getGQL = (url) => (query, variables) =>
+  fetch(url, {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+      ...(localStorage.authToken
+        ? { Authorization: "Bearer " + localStorage.authToken }
+        : {}),
+    },
+    body: JSON.stringify({ query, variables }),
+  })
+    .then((res) => res.json())
+    .then((data) => {
+      if (data.data) {
+        return Object.values(data.data)[0];
+      } else throw new Error(JSON.stringify(data.errors));
+    });
+
+const backendURL = "http://shop-roles.asmer.fs.a-level.com.ua";
+
+const gql = getGQL(backendURL + "/graphql");
+const actionRootCats = () =>
+  actionPromise(
+    "rootCats",
+    gql(`query {
+        CategoryFind(query: "[{\\"parent\\":null}]"){
+            _id name
+        }
+    }`)
+  );
+
+const actionCatById = (_id) =>
+  actionPromise(
+    "catById",
+    gql(
+      `query catById($q: String){
+        CategoryFindOne(query: $q){
+            _id name goods {
+                _id name price images {
+                    url
+                }
+
+            }
+            subCategories {
+                _id name
+                }
+                parent {
+                 _id name
+                }
+        }
+    }`,
+      { q: JSON.stringify([{ _id }]) }
+    )
+  );
+const actionGoodById = (_id) =>
+  actionPromise(
+    "goodById",
+    gql(
+      `query goodById($good: String){
+          GoodFindOne(query: $good){
+              _id name description price categories{_id name owner{_id login nick}}images{url}
+    }
+  }`,
+      { good: JSON.stringify([{ _id }]) }
+    )
+  );
+
+const actionOrders = () =>
+  actionPromise(
+    "orders",
+    gql(`
+  query orders {
+    OrderFind(query: "[{}]") {
+      _id
+      total
+      createdAt
+      orderGoods {
+        price
+        count
+        total
+        good {
+          name
+          categories {
+            name
+          }
+        }
+      }
+    }
+  }`)
+  );
+
+const jwtDecode = (token) => {
+  try {
+    const payload = JSON.parse(atob(token.split(".")[1]));
+    //  серединка, atob, JSON.parse
+    return payload;
+  } catch (e) {
+    console.log(e);
+  }
+};
+function authReducer(state, { type, token }) {
+  if (state === undefined && localStorage.authToken) {
+    token = localStorage.authToken;
+    type = "AUTH_LOGIN";
+  }
+  if (type === "AUTH_LOGIN") {
+    let decodeToken = jwtDecode(token);
+    if (decodeToken) {
+      localStorage.authToken = token;
+      return {
+        token,
+        payload: decodeToken,
+      };
+    }
+  }
+  if (type === "AUTH_LOGOUT") {
+    localStorage.authToken = "";
+    //чистим localStorage.authToken
+    return {};
+  }
+  return state || {};
+}
+//написать к этому пару экшонов
+const actionAuthLogin = (token) => ({ type: "AUTH_LOGIN", token });
+const actionAuthLogout = () => ({ type: "AUTH_LOGOUT" });
+
+function cartReducer(state = {}, { type, good = {}, count = 1 }) {
+  //каков state:
+  //{
+  //  _id1: {count:1, good: {_id1, name, price, images}}
+  //  _id2: {count:1, good: {_id2, name, price, images}}
+  //}
+  //каковы действия по изменению state
+  if (type === "CART_ADD") {
+    count = +count;
+    if (!count) return state;
+    else
+      return {
+        ...state,
+        [good._id]: { good, count: count + (state[good._id]?.count || 0) },
+      };
+  }
+  if (type === "CART_CHANGE") {
+    count = +count;
+    if (!count) return state;
+
+    return {
+      ...state,
+      [good._id]: { good, count },
+    };
+  }
+  if (type === "CART_DELETE") {
+    const { [good._id]: removedProperty, ...someGoods } = state;
+    return someGoods;
+  }
+
+  if (type === "CART_CLEAR") {
+    return {};
+  }
+  return state;
+}
+const actionCartAdd = (good, count = 1) => ({ type: "CART_ADD", good, count });
+const actionCartChange = (good, count = 1) => ({
+  type: "CART_CHANGE",
+  good,
+  count,
+});
+const actionCartDelete = (good) => ({ type: "CART_DELETE", good });
+const actionCartClear = () => ({ type: "CART_CLEAR" });
+
+const actionOrder = () => async (dispatch, getState) => {
+  let { cart } = getState();
+  const orderGoods = Object.entries(cart).map(([_id, { count }]) => ({
+    good: { _id },
+    count,
+  }));
+  let result = await dispatch(
+    actionPromise(
+      "order",
+      gql(
+        `
+                    mutation newOrder($order:OrderInput){
+                      OrderUpsert(order:$order)
+                        { _id total }
+                    }
+            `,
+        { order: { orderGoods: orderGoods } }
+      )
+    )
+  );
+  if (result?._id) {
+    dispatch(actionCartClear());
+  }
+};
+
+const combineReducers =
+  (reducers) =>
+  (state = {}, action) => {
+    const newState = {};
+    for (const [reducerName, reducer] of Object.entries(reducers)) {
+      let newSubState = reducer(state[reducerName], action);
+      // console.log(newSubState)
+      if (newSubState !== state[reducerName]) {
+        newState[reducerName] = newSubState;
+        // console.log(newState[reducerName])
+      }
+    }
+    if (Object.keys(newState).length !== 0) return { ...state, ...newState };
+    else return state;
+  };
+const store = createStore(
+  combineReducers({
+    promise: promiseReducer,
+    auth: authReducer,
+    cart: cartReducer,
+  })
+);
+
+// для корневых категорий
+store.dispatch(actionRootCats());
+store.subscribe(() => console.log(store.getState()));
+const actionFullLogin = (login, password) => async (dispatch) => {
+  let token = await dispatch(
+    actionPromise(
+      "auth",
+      gql(
+        ` query login($login:String, $password:String){
+    login(login:$login, password:$password)} `,
+        { login, password }
+      )
+    )
+  );
+  if (token) {
+    dispatch(actionAuthLogin(token));
+  }
+};
+const actionRegister = (login, password) =>
+  actionPromise(
+    "register",
+    gql(
+      `mutation register($login: String, $password: String) {
+        UserUpsert(user: {login: $login, password: $password, nick: $login}) {
+          _id login
+        }
+      }`,
+      { login: login, password: password }
+    )
+  );
+
+const actionFullRegister = (login, password) => async (dispatch) => {
+  let tokenCheck = await dispatch(actionRegister(login, password));
+
+  if (tokenCheck?.login === login) {
+    dispatch(actionFullLogin(login, password));
+  }
+};
+
+store.subscribe(() => {
+  const { rootCats } = store.getState().promise;
+  if (rootCats?.payload) {
+    aside.innerHTML = "";
+    for (const { _id, name } of rootCats.payload) {
+      const link = document.createElement("a");
+      link.href = `#/category/${_id}`;
+      link.innerText = name;
+      aside.append(link);
+    }
+  }
+});
+
+store.subscribe(() => {
+  const { catById } = store.getState().promise;
+  const { cart } = store.getState();
+
+  const [, route, _id] = location.hash.split("/");
+  //проверка на наличие 'category' в адресной строке
+  if (catById?.payload && route === "category") {
+    //достаем имя
+    const { name } = catById.payload;
+    main.innerHTML = `<h1>${name}</h1>`;
+    if (catById?.payload?.subCategories) {
+      for (const { _id, name } of catById.payload?.subCategories) {
+        const link = document.createElement("a");
+        link.href = `#/category/${_id}`;
+        link.innerText = name;
+        main.append(link);
+      }
+    }
+
+    for (const myGood of catById.payload.goods) {
+      const { _id, name, price, images } = myGood;
+      const card = document.createElement("div");
+      card.innerHTML = `<h2>${name}</h2>
+                   <img src="${backendURL}/${images[0].url}" />
+                   <br>
+                   <strong> Цена ${price} грн</strong>
+                   <br>
+                    <a href ="#/good/${_id}">Перейти на товар ${name} </a>`;
+      let btnAdd = document.createElement("button");
+      btnAdd.innerText = "Добавить в корзину";
+      card.append(btnAdd);
+
+      let btnDelete = document.createElement("button");
+      btnDelete.innerText = "Удалить из корзины";
+      btnDelete.classList.add("deleteBtn");
+      card.append(btnDelete);
+
+      let p = document.createElement("p");
+      if (cart[myGood._id]?.count != undefined)
+        p.innerHTML = `Выбранное количество: ${cart[myGood._id]?.count}`;
+      else p.innerHTML = `Выбранное количество: 0`;
+      card.append(p);
+
+      // console.log(cart[myGood._id]?.count)
+      //console.log(count)
+      btnAdd.onclick = () => {
+        store.dispatch(actionCartAdd(myGood));
+      };
+
+      btnDelete.onclick = () => {
+        store.dispatch(actionCartDelete(myGood));
+      };
+
+      main.append(card);
+    }
+
+    if (catById.payload?.parent && catById.payload?.parent != null) {
+      const { _id, name } = catById.payload.parent;
+      const linkParent = document.createElement("a");
+      linkParent.href = `#/category/${_id}`;
+      //console.log(_id, name);
+      linkParent.innerText = ` Вернуться к категории ` + name;
+      main.append(linkParent);
+    }
+  }
+});
+
+store.subscribe(() => {
+  const { goodById } = store.getState().promise;
+  const { cart } = store.getState();
+  const [, route, _id] = location.hash.split("/");
+
+  //проверка на наличие 'good' в адресной строке
+  if (goodById?.payload && route === "good") {
+    main.innerHTML = "";
+    //достаем имя
+    const { _id, name, description, price, images } = goodById.payload;
+    main.innerHTML = `<h1>${name}</h1>
+       <img src="${backendURL}/${images[0].url}" />
+       <h3>${description} </h3>
+       <br>
+       <strong> Цена ${price} грн </strong>`;
+
+    let btnAdd = document.createElement("button");
+    btnAdd.innerText = "Добавить в корзину";
+
+    btnAdd.onclick = () => store.dispatch(actionCartAdd(goodById.payload));
+    main.append(btnAdd);
+    let p = document.createElement("p");
+    //console.log(goodById.payload._id);
+    if (cart[goodById.payload._id]?.count != undefined)
+      p.innerHTML = `Выбранное количество: ${
+        cart[goodById.payload._id]?.count
+      }`;
+    else p.innerHTML = `Выбранное количество: 0`;
+    main.append(p);
+
+    if (goodById.payload?.categories) {
+      for (const { _id, name } of goodById.payload.categories) {
+        const link = document.createElement("a");
+        link.href = `#/category/${_id}`;
+        link.innerText = `Вернуться к категории ${name}`;
+        main.append(link);
+      }
+    }
+  }
+});
+let pMess = document.createElement("p");
+store.subscribe(() => {
+  const { auth } = store.getState();
+  if (Object.keys(auth).length !== 0) {
+    btnSignIn.innerHTML = `${auth.payload.sub.login}`;
+  }
+  const [, route, _id] = location.hash.split("/");
+  if (route === "login") {
+    pMess.innerHTML = "";
+
+    if (Object.keys(auth).length !== 0) {
+      if (
+        actionFulfilled(auth, auth.payload != null) &&
+        actionAuthLogin(auth)
+      ) {
+        pMess.innerHTML =
+          "Вы авторизировались! Добро пожаловать, " +
+          `${auth.payload.sub.login}, в наш магазин!`;
+        pMess.style.backgroundColor = "#98FB98";
+        pMess.style.color = "#006400";
+        main.prepend(pMess);
+      }
+    } else {
+      btnSignIn.innerHTML = "Sign In";
+      pMess.innerHTML = "Имя пользователя или пароль неверны.";
+      pMess.style.backgroundColor = "#FA8072";
+      pMess.style.color = "#8B0000";
+      main.prepend(pMess);
+    }
+  }
+});
+
+store.subscribe(() => {
+  const { auth } = store.getState();
+  const [, route, _id] = location.hash.split("/");
+  if (route === "register") {
+    pMess.innerHTML = "";
+    if (Object.keys(auth).length !== 0) {
+      if (
+        actionFulfilled(auth, auth.payload != null) &&
+        actionAuthLogin(auth)
+      ) {
+        pMess.innerHTML = `Вы успешно зарегистрированы!Добро пожаловать, ${auth.payload.sub.login}, в наш магазин!`;
+        pMess.style.backgroundColor = "#98FB98";
+        pMess.style.color = "#006400";
+        btnSignIn.innerHTML = `${auth.payload.sub.login}`;
+        main.prepend(pMess);
+      }
+    } else {
+      btnSignIn.innerHTML = "Sign In";
+      pMess.innerHTML =
+        "Такое имя пользователя уже существует, придумайте другое!";
+      pMess.style.backgroundColor = "#FA8072";
+      pMess.style.color = "#8B0000";
+      main.prepend(pMess);
+    }
+  }
+});
+
+store.subscribe(() => {
+  const { orders } = store.getState().promise;
+  const [, route, _id] = location.hash.split("/");
+  if (route === "dashboard") {
+    main.innerHTML = "";
+    let h2 = document.createElement("h2");
+    if (orders != undefined && orders?.payload?.length != 0) {
+      //console.log(orders);
+
+      h2.innerHTML = "Ваши заказы: ";
+      main.append(h2);
+      for (let elem in orders?.payload) {
+        const card = document.createElement("div");
+        card.classList.add("cart");
+        let num = document.createElement("p");
+        num.innerHTML = `<h1>№${elem} заказа
+                        <br>
+                        Ваши товары:
+                        </h1>`;
+        card.append(num);
+        //console.log(orders?.payload[elem].total)
+        for (let elem2 in orders?.payload[elem]?.orderGoods) {
+          card.innerHTML += `<h2> * ${orders?.payload[elem]?.orderGoods[elem2].good?.name}</h2>  
+                              <h3> Цена: ${orders?.payload[elem]?.orderGoods[elem2]?.price} </h3>  
+                              <h3> Количество: ${orders?.payload[elem]?.orderGoods[elem2]?.count} </h3>
+                               `;
+
+         // console.log(orders?.payload[elem]?.orderGoods[elem2].good?.name);
+        }
+        main.append(card);
+        let num2 = document.createElement("p");
+        num2.innerHTML = `<span> Общая сумма заказа: ${orders?.payload[elem].total} </span>`;
+        card.append(num2);
+      }
+    } else {
+      h2.innerHTML = "У вас нету еще оформленных заказов! :( ";
+      main.append(h2);
+    }
+  }
+});
+
+let btnSignIn = document.getElementById("signIn");
+let btnlogOut = document.getElementById("logOut");
+window.onhashchange = () => {
+  const [, route, _id] = location.hash.split("/");
+
+  const routes = {
+    category() {
+      store.dispatch(actionCatById(_id));
+    },
+    good() {
+      store.dispatch(actionGoodById(_id));
+    },
+    login() {
+      main.innerHTML = "";
+      let labelLog = document.createElement("label");
+      labelLog.innerHTML = "Login";
+      let inputLogin = document.createElement("input");
+      let labelPass = document.createElement("label");
+      labelPass.innerHTML = "Password";
+      let inputPassword = document.createElement("input");
+      let sign = document.createElement("button");
+      sign.innerHTML = "SIGN";
+      sign.setAttribute("id", "sign");
+      pMess.innerHTML = "";
+      main.append(labelLog);
+      main.append(inputLogin);
+      main.append(labelPass);
+      main.append(inputPassword);
+      main.append(sign);
+
+      sign.addEventListener("click", () => {
+        try {
+          if (inputLogin.value != "" && inputPassword.value != "") {
+            store.dispatch(
+              actionFullLogin(inputLogin.value, inputPassword.value)
+            );
+          } else {
+            pMess.innerHTML = "Введите значение!";
+            pMess.style.backgroundColor = "#FA8072";
+            pMess.style.color = "#8B0000";
+            main.prepend(pMess);
+          }
+        } catch (e) {
+          console.log("myError", e);
+        }
+      });
+    },
+    register() {
+      main.innerHTML = "";
+      let labelLog = document.createElement("label");
+      labelLog.innerHTML = "Login";
+      let inputLogin = document.createElement("input");
+      let labelPass = document.createElement("label");
+      labelPass.innerHTML = "Password";
+      let inputPassword = document.createElement("input");
+      let register = document.createElement("button");
+      register.innerHTML = "REGISTER";
+      pMess.innerHTML = "";
+      main.append(pMess);
+      main.append(labelLog);
+      main.append(inputLogin);
+      main.append(labelPass);
+      main.append(inputPassword);
+
+      register.addEventListener("click", () => {
+        try {
+          if (inputLogin.value != "" && inputPassword.value != "") {
+            store.dispatch(
+              actionFullRegister(inputLogin.value, inputPassword.value)
+            );
+          } else {
+            pMess.innerHTML = "Введите значение!";
+            pMess.style.backgroundColor = "#FA8072";
+            pMess.style.color = "#8B0000";
+          }
+        } catch (e) {
+          console.log("myError", e);
+        }
+      });
+
+      main.append(register);
+    },
+    logout() {
+      main.innerHTML = "";
+      store.dispatch(actionAuthLogout());
+      btnSignIn.innerHTML = "Sign In";
+    },
+    cart() {
+      const { cart } = store.getState();
+      main.innerHTML = "";
+      let label = document.createElement("h2");
+      label.innerHTML = "";
+      main.append(label);
+
+      if (Object.keys(cart).length !== 0) {
+        label.innerHTML = "Ваши товары: ";
+        for (let good in cart) {
+          let {
+            good: {
+              _id: _id,
+              name: name,
+              price: price,
+              images: [{ url }],
+            },
+            count,
+          } = cart[good];
+          const card = document.createElement("div");
+          card.classList.add("cart");
+          card.innerHTML = `         
+                <img src="${backendURL}/${url}" class="forCart" />
+                <h2>${name}</h2> 
+                <a href ="#/good/${_id}">Перейти на товар ${name} </a>
+                `;
+
+          let inputCount = document.createElement("input");
+          inputCount.setAttribute("type", "number");
+          inputCount.value = `${count}`;
+          inputCount.min = 1;
+          let strongPrice = document.createElement("strong");
+          strongPrice.innerHTML = ` Цена ${price * inputCount.value} грн `;
+
+          inputCount.oninput = function () {
+            store.dispatch(actionCartChange(cart[good].good, inputCount.value));
+            strongPrice.innerHTML = ` Цена ${price * inputCount.value} грн `;
+          };
+          inputCount.classList.add("count");
+
+          let btnDelete = document.createElement("button");
+          btnDelete.innerHTML = "Удалить товар";
+          btnDelete.classList.add("deleteBtn");
+          btnDelete.addEventListener("click", () => {
+            store.dispatch(actionCartDelete(cart[good].good));
+            card.innerHTML = "";
+          });
+
+          inputCount.oninput = function () {
+            store.dispatch(actionCartChange(cart[good].good, inputCount.value));
+            strongPrice.innerHTML = ` Цена ${price * inputCount.value} грн `;
+          };
+          card.append(strongPrice);
+          card.append(inputCount);
+          card.append(btnDelete);
+
+          main.append(card);
+        }
+        let btnClear = document.createElement("button");
+        btnClear.innerHTML = "Очистить все товары";
+        btnClear.classList.add("clear");
+        let btnOrder = document.createElement("button");
+        btnOrder.innerHTML = "Оформить заказ";
+        btnOrder.classList.add("order");
+        btnOrder.addEventListener("click", () => {
+          alert("Ваш заказ оформлен! Спасибо что выбираете наш магазин!");
+          main.innerHTML = "";
+          label.innerHTML = "Ваша корзина пустая!";
+          main.append(label);
+          store.dispatch(actionOrder());
+        });
+
+        btnClear.addEventListener("click", () => {
+          store.dispatch(actionCartClear());
+          main.innerHTML = "";
+
+          label.innerHTML = "Ваша корзина пустая!";
+          main.append(label);
+        });
+
+        main.append(btnClear);
+        main.append(btnOrder);
+      } else {
+        label.innerHTML = "Ваша корзина пустая!";
+      }
+    },
+
+    dashboard() {
+      store.dispatch(actionOrders());
+    },
+  };
+  if (route in routes) routes[route]();
+};
+window.onhashchange();