|
@@ -0,0 +1,731 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html>
|
|
|
+<head>
|
|
|
+ <meta charset="utf-8">
|
|
|
+ <title>Korzinap!!!!!!!!!!!!!!!</title>
|
|
|
+ <style>
|
|
|
+ .Jorik{
|
|
|
+ border-bottom: 1px dotted green;
|
|
|
+ }
|
|
|
+ #content {
|
|
|
+ display: flex;
|
|
|
+ }
|
|
|
+ #aside {
|
|
|
+ width: 30%;
|
|
|
+ }
|
|
|
+
|
|
|
+ #aside > a {
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+
|
|
|
+ .wrapper{
|
|
|
+ border: 1px dotted green;
|
|
|
+ }
|
|
|
+
|
|
|
+ img{
|
|
|
+ width:300px;
|
|
|
+ }
|
|
|
+ main{
|
|
|
+ padding-left: 20px;
|
|
|
+ }
|
|
|
+ table{
|
|
|
+ border:1px solid black;
|
|
|
+ }
|
|
|
+ td{
|
|
|
+ text-align: center;
|
|
|
+ border:1px solid black;
|
|
|
+ }
|
|
|
+
|
|
|
+ header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ }
|
|
|
+ #ownCab, .wrapper{
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ }
|
|
|
+ #ownCab{
|
|
|
+ margin-left: 1em;
|
|
|
+ }
|
|
|
+ #ownCab a, button{
|
|
|
+ margin-left: 1em;
|
|
|
+ }
|
|
|
+ .cart img{
|
|
|
+ width: 1.5em;
|
|
|
+ height: 1.5em;
|
|
|
+ }
|
|
|
+ a {
|
|
|
+ text-decoration: none;
|
|
|
+ color:blue;
|
|
|
+ }
|
|
|
+ a:hover{
|
|
|
+ color: green;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+<body>
|
|
|
+
|
|
|
+ <header>
|
|
|
+ <div id="formId"></div>
|
|
|
+ <div class="wrapper">
|
|
|
+ <div class="cart">
|
|
|
+ <a href="#/cart">
|
|
|
+ <span id="cartQuantity"></span>
|
|
|
+ <img src="xz.png" />
|
|
|
+ </a>
|
|
|
+ </div>
|
|
|
+ <div id="ownCab"></div>
|
|
|
+ </div>
|
|
|
+ </header>
|
|
|
+ <div id='content'>
|
|
|
+ <aside id='aside'>
|
|
|
+ Категории
|
|
|
+ </aside>
|
|
|
+ <main id='main'>
|
|
|
+ Контент
|
|
|
+ </main>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <script>
|
|
|
+//----------------------Store---------------------------------------
|
|
|
+ function createStore(reducer){
|
|
|
+ let state = reducer(undefined, {})
|
|
|
+ let cbs = []
|
|
|
+ const getState = () => state
|
|
|
+ const subscribe = cb => (cbs.push(cb),
|
|
|
+ () => cbs = cbs.filter(c => c !== cb))
|
|
|
+ const dispatch = action => {
|
|
|
+ if (typeof action === 'function'){
|
|
|
+ return action(dispatch, getState)
|
|
|
+ }
|
|
|
+ const newState = reducer(state, action)
|
|
|
+ if (newState !== state){
|
|
|
+ state = newState
|
|
|
+ for (let cb of cbs) cb()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ getState,
|
|
|
+ dispatch,
|
|
|
+ subscribe
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+ //написать jwtDecode = token =>({})
|
|
|
+ const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOnsiaWQiOiI2MWE0ZTA1MmM3NTBjMTJiYTZiYTQwMjkiLCJsb2dpbiI6InZsYWRCcmF1bjQiLCJhY2wiOlsiNjFhNGUwNTJjNzUwYzEyYmE2YmE0MDI5IiwidXNlciJdfSwiaWF0IjoxNjM4NTM5NTUzfQ.oPRus9nGS1rg69eKu8rK-tMi4V-hN5HXE0NOzAc5K4k";
|
|
|
+
|
|
|
+ //выкусить из токена серединку
|
|
|
+ //сделать base64 декод (atob)
|
|
|
+ //с результатом сделать JSON.parse
|
|
|
+ const jwtDecode = token =>{
|
|
|
+ try{
|
|
|
+ let mid=token.split('.');
|
|
|
+ let tok=mid[1];
|
|
|
+ let tokenDecode=atob(tok);
|
|
|
+ let finalTok=JSON.parse(tokenDecode);
|
|
|
+ return finalTok;
|
|
|
+ }catch(e){
|
|
|
+ console.log(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log(jwtDecode(token));
|
|
|
+
|
|
|
+//-------------------------------------------------------------------------------
|
|
|
+ function authReducer(state, {type, token}) {
|
|
|
+ if(!state) {
|
|
|
+ if (localStorage.authToken) {
|
|
|
+ type = 'AUTH_LOGIN'
|
|
|
+ token = localStorage.authToken
|
|
|
+ } else {
|
|
|
+ return {}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (type === 'AUTH_LOGIN') {
|
|
|
+ localStorage.authToken = token
|
|
|
+ let payload = jwtDecode(token)
|
|
|
+ if (typeof payload !== 'object') {
|
|
|
+ return {}
|
|
|
+ }
|
|
|
+ return {token, payload}
|
|
|
+ }
|
|
|
+ if (type === 'AUTH_LOGOUT') {
|
|
|
+ // debugger
|
|
|
+ localStorage.removeItem('authToken')
|
|
|
+ return {}
|
|
|
+ }
|
|
|
+ return state
|
|
|
+ }
|
|
|
+
|
|
|
+// const store = createStore(authReducer)
|
|
|
+const actionAuthLogin = token => ({type: 'AUTH_LOGIN', token})
|
|
|
+const actionAuthLogout = () => ({type: 'AUTH_LOGOUT'})
|
|
|
+
|
|
|
+// login.onclick = () => store.dispatch(actionAuthLogin(token))
|
|
|
+// logout.onclick = () => store.dispatch(actionAuthLogout())
|
|
|
+
|
|
|
+//------------------------------------------------------------------------------
|
|
|
+ function combineReducers(reducers) {
|
|
|
+ return (state = {}, action) => {
|
|
|
+ const newState = {}
|
|
|
+ for (const [reducerName, reducer] of Object.entries(reducers)) {
|
|
|
+ let newSubstate = reducer(state[reducerName], action)
|
|
|
+ if (newSubstate !== state[reducerName]) {
|
|
|
+ newState[reducerName] = newSubstate
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (Object.entries(newState).length !== 0) {
|
|
|
+ return {...state, ...newState}
|
|
|
+ } else return state
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+//-------------------------------------------------------------------------------
|
|
|
+function promiseReducer(state = {}, { type, name, status, payload, error }) {
|
|
|
+ //{
|
|
|
+ // login: {status, payload, error}
|
|
|
+ // catById: {status, payload, error}
|
|
|
+ //}
|
|
|
+ if (type === 'PROMISE') {
|
|
|
+ return {
|
|
|
+ ...state,
|
|
|
+ [name]: { status, payload, error }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return state
|
|
|
+}
|
|
|
+
|
|
|
+const actionPending = name => ({ type: 'PROMISE', status: 'PENDING', name })
|
|
|
+const actionResolved = (name, payload) => ({ type: 'PROMISE', status: 'RESOLVED', name, payload })
|
|
|
+const actionRejected = (name, error) => ({ type: 'PROMISE', status: 'REJECTED', name, error })
|
|
|
+const actionPromise = (name, promise) =>
|
|
|
+ async dispatch => {
|
|
|
+ dispatch(actionPending(name)) // 1. {delay1000: {status: 'PENDING'}}
|
|
|
+ try {
|
|
|
+ let payload = await promise
|
|
|
+ dispatch(actionResolved(name, payload))
|
|
|
+ return payload
|
|
|
+ }
|
|
|
+ catch (error) {
|
|
|
+ dispatch(actionRejected(name, error))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+// const store = createStore(promiseReducer)
|
|
|
+// store.subscribe(() => console.log(store.getState()))
|
|
|
+
|
|
|
+// const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
|
|
|
+// store.dispatch(actionPromise('delay1000', delay(1000)))
|
|
|
+// store.dispatch(actionPromise('delay2000', delay(2000)))
|
|
|
+// store.dispatch(actionPromise('failedfetch', fetch('https://swapi.dev/api/people/1/')
|
|
|
+// .then(res => res.json())))
|
|
|
+
|
|
|
+//--------------------------------------------------------------
|
|
|
+ function cartReducer(state = {}, {type, good = {}, count = 1}) {
|
|
|
+ const {_id} = good
|
|
|
+
|
|
|
+ if(!count) {
|
|
|
+ return state
|
|
|
+ }
|
|
|
+ const types = {
|
|
|
+ CART_ADD(){
|
|
|
+ //берет старую позицию, и добавляет count к текущему количеству.
|
|
|
+ //если позиции нет - то добавляет к 0 (т. е. в первый раз будет count)
|
|
|
+ count = +count
|
|
|
+ return {
|
|
|
+ ...state,
|
|
|
+ [_id]: {good, count:(state[_id] ? state[_id].count : 0) + count}
|
|
|
+ }
|
|
|
+ },
|
|
|
+ CART_CHANGE(){
|
|
|
+ //тупо меняет позицию
|
|
|
+ return {
|
|
|
+ ...state,
|
|
|
+ [_id]: {good, count}
|
|
|
+ }
|
|
|
+ },
|
|
|
+ CART_REMOVE(){
|
|
|
+ //надо как-то создать объект без ключа
|
|
|
+ let {[_id]: remove, ...rest} = state
|
|
|
+ return rest
|
|
|
+ },
|
|
|
+ CART_CLEAR(){
|
|
|
+ //самое простое
|
|
|
+ return {}
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(type in types) {
|
|
|
+ return types[type]()
|
|
|
+ }
|
|
|
+ return state
|
|
|
+ }
|
|
|
+
|
|
|
+ const actionCartAdd = (good, count) => ({type: 'CART_ADD', good, count})
|
|
|
+ const actionCartChange = (good, count) => ({type: 'CART_CHANGE', good, count})
|
|
|
+ const actionCartRemove = (good) => ({type: 'CART_REMOVE', good})
|
|
|
+ const actionCartClear = () => ({type: 'CART_CLEAR'})
|
|
|
+//-------------------------------------------------------------------------
|
|
|
+const combinedReducer = combineReducers({promise: promiseReducer, auth: authReducer, cart: cartReducer}) //тут еще
|
|
|
+const store = createStore(combinedReducer)
|
|
|
+console.log(store.getState())
|
|
|
+
|
|
|
+// store.dispatch(actionPromise('delay1000', delay('1000')))
|
|
|
+// store.dispatch(actionAuthLogin(token))
|
|
|
+
|
|
|
+//--------------------------------------------------------------------------------
|
|
|
+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.errors && !data.data)
|
|
|
+ throw new Error(JSON.stringify(data.errors))
|
|
|
+ return data.data[Object.keys(data.data)[0]]
|
|
|
+ })
|
|
|
+
|
|
|
+ const backURL = 'http://shop-roles.asmer.fs.a-level.com.ua'
|
|
|
+
|
|
|
+ const gql = getGQL(backURL + '/graphql')
|
|
|
+
|
|
|
+//-------------------------Actions----------------------------------------
|
|
|
+ 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 description images {
|
|
|
+ url
|
|
|
+ }
|
|
|
+ }
|
|
|
+ subCategories {
|
|
|
+ name _id goods {
|
|
|
+ _id name description
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }`, { q: JSON.stringify([{ _id }]) }))
|
|
|
+
|
|
|
+ const actionGoodById = (_id) =>
|
|
|
+ actionPromise('goodById', gql(`query goodById($q: String){
|
|
|
+ GoodFindOne(query: $q){
|
|
|
+ _id name description price images{
|
|
|
+ url
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }`, { q: JSON.stringify([{ _id }]) }))
|
|
|
+
|
|
|
+ store.dispatch(actionRootCats())
|
|
|
+
|
|
|
+ const actionOrder = () =>
|
|
|
+ async (dispatch, getState) => {
|
|
|
+ let {cart} = store.getState()
|
|
|
+ const orderGoods = Object.entries(cart)
|
|
|
+ .map(([_id, {good, count}]) => ({good: {_id}, count}))
|
|
|
+ let result = await dispatch(actionPromise('order', gql(`
|
|
|
+ mutation newOrder($order:OrderInput){
|
|
|
+ OrderUpsert(order:$order)
|
|
|
+ { _id total }
|
|
|
+ }`, {order: {orderGoods}})))
|
|
|
+ if(result?._id) {
|
|
|
+ store.dispatch(actionCartClear())
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const actionMyOrders = () =>
|
|
|
+ actionPromise('orderfind', gql(`query orderfind{
|
|
|
+ OrderFind(query: "[{}]"){
|
|
|
+ _id createdAt total orderGoods{
|
|
|
+ _id createdAt price count
|
|
|
+ good{
|
|
|
+ _id description name images{
|
|
|
+ _id url
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }`))
|
|
|
+
|
|
|
+ const actionLogin = (login, password) =>
|
|
|
+ actionPromise('login', gql(`query login($login: String, $password: String){
|
|
|
+ login(login: $login, password: $password)
|
|
|
+ }`, {login: login, password: password})
|
|
|
+ )
|
|
|
+
|
|
|
+ const actionFullLogin = (login, password) =>
|
|
|
+ async dispatch => {
|
|
|
+ let token = await dispatch(actionLogin(login, password))
|
|
|
+ if(token) {
|
|
|
+ dispatch(actionAuthLogin(token))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const actionRegister = (login, password) =>
|
|
|
+ actionPromise('register', gql(`mutation registration($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 log = await dispatch(actionRegister(login, password))
|
|
|
+ if (log) {
|
|
|
+ let token = await dispatch(actionLogin(login, password))
|
|
|
+ if (token){
|
|
|
+ dispatch(actionAuthLogin(token))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+//--------------------------main Page--------------------------------------------
|
|
|
+ store.subscribe(() => {
|
|
|
+ const { promise } = store.getState()
|
|
|
+ console.log('------------')
|
|
|
+ console.log(promise)
|
|
|
+ if (promise?.rootCats?.payload) {
|
|
|
+ aside.innerHTML = ''
|
|
|
+ for (const { _id, name } of promise?.rootCats?.payload) {
|
|
|
+ const link = document.createElement('a')
|
|
|
+ link.href = `#/category/${_id}`
|
|
|
+ link.innerText = name
|
|
|
+ aside.append(link)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ store.subscribe(() => {
|
|
|
+ const { promise } = store.getState()
|
|
|
+ const [, route, _id] = location.hash.split('/')
|
|
|
+ if (promise?.catById?.payload && route === 'category') {
|
|
|
+ const { name } = promise.catById.payload
|
|
|
+ main.innerHTML = `<h1 class="Jorik">${name}</h1>`
|
|
|
+ if (promise.catById.payload?.subCategories) {
|
|
|
+ for (let { _id, name } of promise.catById.payload.subCategories) {
|
|
|
+ const podCat = document.createElement('a')
|
|
|
+ podCat.href = `#/category/${_id}`
|
|
|
+ podCat.innerText = name
|
|
|
+ main.append(podCat)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (const good of promise.catById.payload.goods) {
|
|
|
+ const {_id, name, price, images} = good
|
|
|
+ const card = document.createElement('div')
|
|
|
+ card.innerHTML = `<h2>${name}</h2>
|
|
|
+ <img src="${backURL}/${images[0].url}"/>
|
|
|
+ <div>
|
|
|
+ <b>Стоимость:</b> <b><sub>${price}UAH</sub></b>
|
|
|
+ <br><a href=#/good/${_id}>Страница товара</a>
|
|
|
+ </div>`
|
|
|
+ main.append(card)
|
|
|
+ let btn = document.createElement('button')
|
|
|
+ btn.innerText = 'Добавить в корзину'
|
|
|
+ btn.style.marginLeft=50+'%'
|
|
|
+ btn.onclick = () => store.dispatch(actionCartAdd(good, 1))
|
|
|
+ card.append(btn)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+//-----------------------Korzina---------------------------
|
|
|
+ store.subscribe(() => {
|
|
|
+ const {cart} = store.getState()
|
|
|
+ console.log(cart)
|
|
|
+ if (cart){
|
|
|
+ let num = 0
|
|
|
+ cartQuantity.innerText = ''
|
|
|
+ for (let key in cart) {
|
|
|
+ num+=cart[key].count
|
|
|
+ }
|
|
|
+ cartQuantity.innerText = num
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ function showCart() {
|
|
|
+ const { cart } = store.getState()
|
|
|
+ console.log(cart)
|
|
|
+ main.innerHTML = ``
|
|
|
+ let num = 1
|
|
|
+ let count = 0
|
|
|
+ let total = 0
|
|
|
+ let h = document.createElement('h2')
|
|
|
+ h.innerText = 'Корзина';
|
|
|
+ h.style.borderBottom = 1+'px solid black'
|
|
|
+ main.append(h)
|
|
|
+ const table = document.createElement('table')
|
|
|
+ for (let key in cart) {
|
|
|
+ let { good, count } = cart[key]
|
|
|
+ console.log(good, count)
|
|
|
+ let cartKey = document.createElement('tr')
|
|
|
+ cartKey.innerHTML = `<td>${num++}</td><td><img src="${backURL}/${good.images[0].url}"/></td><td>${good.name}</td>
|
|
|
+ <td>${good.price} UAH</td>`
|
|
|
+ let addBtnTd = document.createElement('td')
|
|
|
+ let addBtn = document.createElement('button')
|
|
|
+ addBtn.innerText = '+'
|
|
|
+ addBtnTd.append(addBtn)
|
|
|
+ let chngTd = document.createElement('td')
|
|
|
+ let chng = document.createElement('input')
|
|
|
+ chng.type = 'number'
|
|
|
+ chng.min = 0
|
|
|
+ chng.max = 50
|
|
|
+ chng.value = count
|
|
|
+ chngTd.append(chng)
|
|
|
+ let subBtnTd = document.createElement('td')
|
|
|
+ let subBtn = document.createElement('button')
|
|
|
+ subBtn.innerText = '-'
|
|
|
+ subBtnTd.append(subBtn)
|
|
|
+ let deleteBtnTd = document.createElement('td')
|
|
|
+ let deleteBtn = document.createElement('button')
|
|
|
+ deleteBtn.innerText = 'Удалить'
|
|
|
+ deleteBtnTd.append(deleteBtn)
|
|
|
+ chng.oninput = () => store.dispatch(actionCartChange(good, chng.value))
|
|
|
+ deleteBtn.onclick = () => {
|
|
|
+ cartKey.remove()
|
|
|
+ store.dispatch(actionCartRemove(good))
|
|
|
+ }
|
|
|
+ addBtn.onclick = () => {
|
|
|
+ store.dispatch(actionCartAdd(good, 1))
|
|
|
+ chng.value++
|
|
|
+ }
|
|
|
+ subBtn.onclick = () => {
|
|
|
+ store.dispatch(actionCartAdd(good, -1))
|
|
|
+ chng.value--
|
|
|
+ }
|
|
|
+ cartKey.append(addBtnTd, chngTd, subBtnTd, deleteBtnTd)
|
|
|
+ table.append(cartKey)
|
|
|
+ main.append(table)
|
|
|
+ count += parseInt(chng.value)
|
|
|
+ total += good.price * chng.value
|
|
|
+ }
|
|
|
+ let clearBtn = document.createElement('button')
|
|
|
+ clearBtn.innerText = "Очистить корзину";
|
|
|
+ Object.entries(cart).length > 0 ? main.append(clearBtn) : null
|
|
|
+ clearBtn.onclick = () => {
|
|
|
+ store.dispatch(actionCartClear())
|
|
|
+ table.remove()
|
|
|
+ clearBtn.style.display = 'none';
|
|
|
+ canOrder.style.display = 'none';
|
|
|
+ }
|
|
|
+ let canOrder = document.createElement('button')
|
|
|
+ canOrder.innerText = "Оформить заказ"
|
|
|
+ Object.entries(cart).length > 0 ? main.append(canOrder) : null
|
|
|
+ if (localStorage.authToken) {
|
|
|
+ canOrder.disabled = false
|
|
|
+ } else {
|
|
|
+ canOrder.disabled = true
|
|
|
+ }
|
|
|
+ canOrder.onclick = () => {
|
|
|
+ store.dispatch(actionOrder())
|
|
|
+ table.remove()
|
|
|
+ clearBtn.style.display = 'none';
|
|
|
+ canOrder.style.display = 'none';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+//-----------------opis tovara--------------------------
|
|
|
+ store.subscribe(() => {
|
|
|
+ const { promise } = store.getState()
|
|
|
+ const [, route, _id] = location.hash.split('/')
|
|
|
+ if (promise?.goodById?.payload && route === 'good' && location.href.includes(`#/good/${_id}`)) {
|
|
|
+ main.innerHTML = ``
|
|
|
+ let { _id, name, price, images, description } = promise.goodById.payload
|
|
|
+ let goodItem = document.createElement('div')
|
|
|
+ goodItem.className = 'good_item'
|
|
|
+ goodItem.innerHTML = `<h2>${name}</h2>
|
|
|
+ <img src="${backURL}/${images[0].url}"/>
|
|
|
+ <div>
|
|
|
+ <p><b>Стоимость:</b> <b><sub>${price} UAH</sub></b></strong></p>
|
|
|
+ <p><b>Описание:</b> <sub>${description}</sub></p>
|
|
|
+ </div>`
|
|
|
+ main.append(goodItem)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+//--------------------------Orders-----------------------------
|
|
|
+ store.subscribe(() => {
|
|
|
+ const {promise} = store.getState()
|
|
|
+ const [,route, _id] = location.hash.split('/')
|
|
|
+ if (promise?.orderfind?.payload && route === 'dashboard'){
|
|
|
+ main.innerHTML = ''
|
|
|
+ let title = document.createElement('h2')
|
|
|
+ title.innerText = 'Ваши заказы';
|
|
|
+ title.style.textAlign='left'
|
|
|
+ title.style.borderBottom=1+'px solid black'
|
|
|
+ main.append(title)
|
|
|
+ for (let order of promise.orderfind.payload) {
|
|
|
+ let quantity = 0
|
|
|
+ const {total, orderGoods} = order
|
|
|
+ let table = document.createElement('table')
|
|
|
+ let thead = document.createElement('thead')
|
|
|
+ thead.innerHTML = `<th class="user-order">Дата заказа</th>
|
|
|
+ <th>Наименование</th>
|
|
|
+ <th>Количество</th>
|
|
|
+ <th>Цена</th>`
|
|
|
+ table.append(thead)
|
|
|
+ for (let {createdAt, count, good, price} of orderGoods){
|
|
|
+ quantity += count;
|
|
|
+ let date = new Date(+createdAt).toLocaleDateString();
|
|
|
+ let tr = document.createElement('tr')
|
|
|
+ tr.innerHTML = `<td>${date}</td>
|
|
|
+ <td><figure class='good-img'>
|
|
|
+ <img src="${backURL}/${good.images[0].url}">
|
|
|
+ <figcaption>${good.name}</figcaption>
|
|
|
+ </figure></td>
|
|
|
+ <td>${count}</td>
|
|
|
+ <td>${price}</td>`
|
|
|
+ table.append(tr)
|
|
|
+ }
|
|
|
+ let totalOrderAmount = document.createElement('tr')
|
|
|
+ totalOrderAmount.innerHTML = `<th class="user-order">Всего товаров в заказе: ${quantity}</th>
|
|
|
+ <th>Общая сумма заказа: ${total}</th>`
|
|
|
+ table.append(totalOrderAmount)
|
|
|
+ main.append(table)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (!promise?.orderfind?.payload && route === 'dashboard'){
|
|
|
+ main.innerHTML = ''
|
|
|
+ let title = document.createElement('h2')
|
|
|
+ title.textContent = 'Вы еще не сделали заказ';
|
|
|
+ main.append(title)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+//----------------------Login-------------------------------
|
|
|
+ store.subscribe(() => {
|
|
|
+ const {auth} = store.getState()
|
|
|
+ const {payload} = auth
|
|
|
+ if (payload?.sub ) {
|
|
|
+ ownCab.innerHTML = ''
|
|
|
+ //ownCab.style.marginTop=10+'px'
|
|
|
+ //ownCab.style.border=5+'px solid blue'
|
|
|
+ //ownCab.style.width=17+'%'
|
|
|
+ const {id, login} = payload.sub
|
|
|
+ const userName = document.createElement('div')
|
|
|
+ userName.innerHTML = `Hello, ${login}`
|
|
|
+ const userOrders = document.createElement('a')
|
|
|
+ //userOrders.style.marginRight=10+'px'
|
|
|
+ userOrders.innerText = 'Your Orders'
|
|
|
+ userOrders.href = `#/dashboard/`
|
|
|
+ let logout = document.createElement('button')
|
|
|
+ logout.textContent = 'Exit'
|
|
|
+ logout.onclick = () => {
|
|
|
+ formId.innerHTML = ''
|
|
|
+ store.dispatch(actionAuthLogout());
|
|
|
+ }
|
|
|
+ ownCab.append(userName, userOrders, logout)
|
|
|
+ } else {
|
|
|
+ ownCab.innerHTML = ''
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ store.subscribe(() => {
|
|
|
+ const {auth} = store.getState()
|
|
|
+ if (!auth?.payload){
|
|
|
+ formId.innerHTML = '';
|
|
|
+ let twoBtns=document.createElement('span')
|
|
|
+ let loginBtn = document.createElement('a');
|
|
|
+ let regBtn = document.createElement('a');
|
|
|
+ twoBtns.append(loginBtn, regBtn)
|
|
|
+ twoBtns.style.border=1+'px dotted green'
|
|
|
+ formId.append(twoBtns)
|
|
|
+ loginBtn.innerText = 'LogIn'
|
|
|
+ regBtn.innerText = 'Registration'
|
|
|
+ loginBtn.onclick = () => {
|
|
|
+ loginBtn.style.display = 'none'
|
|
|
+ regBtn.style.display= 'none'
|
|
|
+ let form = document.createElement('form')
|
|
|
+ let login = document.createElement('input')
|
|
|
+ login.type = 'text'
|
|
|
+ login.placeholder = 'Login'
|
|
|
+ let password = document.createElement('input')
|
|
|
+ password.placeholder = 'Password'
|
|
|
+ password.type = 'password'
|
|
|
+ let btn = document.createElement('a')
|
|
|
+ btn.innerText = 'Enter'
|
|
|
+ btn.onclick = () => {
|
|
|
+ if (login.value !== '' && password.value !== '') {
|
|
|
+ btn.href = `#/login/${login.value}*${password.value}`
|
|
|
+ }
|
|
|
+ formId.innerHTML = ''
|
|
|
+ }
|
|
|
+ form.append(login, password, btn)
|
|
|
+ formId.append(form)
|
|
|
+ }
|
|
|
+ regBtn.onclick = () => {
|
|
|
+ loginBtn.style.display = 'none'
|
|
|
+ regBtn.style.display= 'none'
|
|
|
+ let form = document.createElement('form')
|
|
|
+ let login = document.createElement('input')
|
|
|
+ login.type = 'text'
|
|
|
+ login.placeholder = 'Login'
|
|
|
+ let pass = document.createElement('input')
|
|
|
+ pass.placeholder = 'Password'
|
|
|
+ pass.type = 'password'
|
|
|
+ let btn = document.createElement('a')
|
|
|
+ btn.innerText = 'Registration'
|
|
|
+ btn.onclick = () => {
|
|
|
+ if (login.value !== '' && pass.value !== '') {
|
|
|
+ btn.href = `#/register/${login.value}*${pass.value}`
|
|
|
+ }
|
|
|
+ formId.innerHTML = ''
|
|
|
+ }
|
|
|
+ form.append(login, password, button)
|
|
|
+ formId.append(form)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+//-------------------------------------------------------------
|
|
|
+ window.onhashchange = () => {
|
|
|
+ const [, route, _id] = location.hash.split('/')
|
|
|
+
|
|
|
+ const routes = {
|
|
|
+ category() {
|
|
|
+ store.dispatch(actionCatById(_id))
|
|
|
+ },
|
|
|
+ good() {
|
|
|
+ //задиспатчить actionGoodById
|
|
|
+ store.dispatch(actionGoodById(_id))
|
|
|
+ console.log('ТОВАРОСТРАНИЦА')
|
|
|
+ },
|
|
|
+ login(){
|
|
|
+ let data = _id.split('*')
|
|
|
+ store.dispatch(actionFullLogin(data[0], data[1]))
|
|
|
+ console.log('ЛОГИН')
|
|
|
+ },
|
|
|
+ register(){
|
|
|
+ let data = _id.split('*')
|
|
|
+ store.dispatch(actionFullRegister(data[0], data[1]))
|
|
|
+ console.log('РЕГА')
|
|
|
+ },
|
|
|
+ cart(){
|
|
|
+ showCart()
|
|
|
+ console.log('Сделать страницу с позициями, полями ввода колличества, картинками и кнопкой')
|
|
|
+ },
|
|
|
+ dashboard(){
|
|
|
+ store.dispatch(actionMyOrders())
|
|
|
+ console.log('Прочитать бывшие заказы')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (route in routes)
|
|
|
+ routes[route]()
|
|
|
+ }
|
|
|
+ window.onhashchange()
|
|
|
+ </script>
|
|
|
+</body>
|
|
|
+</html>
|