|
@@ -1,276 +0,0 @@
|
|
|
-// функция createStore
|
|
|
-
|
|
|
-function createStore(reducer) {
|
|
|
- let state = reducer(undefined, {})
|
|
|
- let cbs = []
|
|
|
-
|
|
|
- function dispatch(action) {
|
|
|
- if (typeof action === 'function') {
|
|
|
- return action(dispatch)
|
|
|
- }
|
|
|
-
|
|
|
- const newState = reducer(state, action)
|
|
|
- if (newState !== state) {
|
|
|
- state = newState
|
|
|
- for (let cb of cbs)
|
|
|
- cb()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return {
|
|
|
- dispatch,
|
|
|
- getState() {
|
|
|
- return state
|
|
|
- },
|
|
|
- subscribe(cb) {
|
|
|
- cbs.push(cb)
|
|
|
- return () => cbs = cbs.filter(c => c !== cb)
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// функция promiseReducer
|
|
|
-
|
|
|
-function promiseReducer(state = {}, { type, status, payload, error, name }) {
|
|
|
-
|
|
|
- if (type === 'PROMISE') {
|
|
|
- return {
|
|
|
- ...state,
|
|
|
- [name]: { status, payload, error }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return state
|
|
|
-}
|
|
|
-
|
|
|
-const store = createStore(promiseReducer)
|
|
|
-
|
|
|
-// actions
|
|
|
-
|
|
|
-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))
|
|
|
- try{
|
|
|
- let payload = await promise
|
|
|
- dispatch(actionResolved(name, payload))
|
|
|
- return payload
|
|
|
- }
|
|
|
- catch(error){
|
|
|
- dispatch(actionRejected(name, error))
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-// функция cartReducer
|
|
|
-
|
|
|
-function cartReducer(state = {}, { type, count = 1, _id, name }) {
|
|
|
- if (type === "CART_ADD") {
|
|
|
- return {
|
|
|
- ...state,
|
|
|
- [_id]: {
|
|
|
- name: name,
|
|
|
- count: state[_id] ? state[_id].count + count : count
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (type === "CART_CHANGE") {
|
|
|
- return {
|
|
|
- ...state,
|
|
|
- [_id]: {
|
|
|
- name: name,
|
|
|
- count: count
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (type === 'CART_REMOVE') {
|
|
|
- let { [_id]: count, ...copyWithout } = state
|
|
|
- return copyWithout
|
|
|
- }
|
|
|
-
|
|
|
- if (type === 'CART_CLEAR') {
|
|
|
- return {}
|
|
|
- }
|
|
|
-
|
|
|
- return state
|
|
|
-}
|
|
|
-
|
|
|
-// reducers
|
|
|
-
|
|
|
-let reducers = {
|
|
|
- promise: promiseReducer,
|
|
|
- cart: cartReducer
|
|
|
-}
|
|
|
-
|
|
|
-// функция combineReducers
|
|
|
-
|
|
|
-function combineReducers(reducers) {
|
|
|
- function commonReducer(state = {}, action) {
|
|
|
- let newState = {}
|
|
|
-
|
|
|
- for (let key in reducers) {
|
|
|
- let innerState = reducers[key](state[key], action)
|
|
|
-
|
|
|
- innerState === state[key] ? newState[key] = state[key] : newState[key] = innerState
|
|
|
- }
|
|
|
-
|
|
|
- return newState
|
|
|
- }
|
|
|
-
|
|
|
- return commonReducer
|
|
|
-}
|
|
|
-
|
|
|
-// запросы
|
|
|
-
|
|
|
-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())
|
|
|
-
|
|
|
-let shopGQL = getGQL("http://shop-roles.asmer.fs.a-level.com.ua/graphql")
|
|
|
-
|
|
|
-const actionRootCategories = () =>
|
|
|
- actionPromise('rootCategories', shopGQL(`query cats($query:String) {
|
|
|
- CategoryFind(query:$query) {
|
|
|
- _id name
|
|
|
- }
|
|
|
- }`, {query: JSON.stringify([{parent:null}])}))
|
|
|
-
|
|
|
-store.dispatch(actionRootCategories())
|
|
|
-
|
|
|
-const actionCategoryById = (_id) =>
|
|
|
- actionPromise('catById', shopGQL(`query catById($query:String) {
|
|
|
- CategoryFindOne(query:$query) {
|
|
|
- _id name goods {
|
|
|
- _id name price description images {
|
|
|
- url
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }`, {query: JSON.stringify([{_id}])}))
|
|
|
-
|
|
|
-const actionGoodById = id =>
|
|
|
- actionPromise('goodById', shopGQL(`query GoodFind($id:String) {
|
|
|
- GoodFind(query: $id){
|
|
|
- name
|
|
|
- price
|
|
|
- description
|
|
|
- images {url}
|
|
|
- }
|
|
|
- }`, {id: JSON.stringify([{ "_id": id }])}))
|
|
|
-
|
|
|
-
|
|
|
-window.onhashchange = () => {
|
|
|
- let { 1: route, 2: id } = location.hash.split('/')
|
|
|
- if (route === 'categories') {
|
|
|
- store.dispatch(actionCategoryById(id))
|
|
|
- }
|
|
|
-
|
|
|
- if (route === 'good') {
|
|
|
- store.dispatch(actionGoodById(id))
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-function drawMainMenu() {
|
|
|
- let cats = store.getState().rootCategories.payload
|
|
|
- if (cats) {
|
|
|
- aside.innerText = ''
|
|
|
- for (let { _id, name } of cats.data.CategoryFind) {
|
|
|
- let catA = document.createElement('a')
|
|
|
- catA.href = `#/categories/${_id}`
|
|
|
- catA.innerText = name
|
|
|
- aside.append(catA)
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-store.subscribe(drawMainMenu)
|
|
|
-store.subscribe(() => console.log(store.getState()))
|
|
|
-
|
|
|
-store.subscribe(() => {
|
|
|
- const { 1: route, 2: id } = location.hash.split('/')
|
|
|
- if (route === 'categories') {
|
|
|
- const catById = store.getState().catById?.payload
|
|
|
- if (catById) {
|
|
|
- aside.innerText = ''
|
|
|
- let cats = document.createElement('p')
|
|
|
- cats.innerText = "Вы в категории ==>" + " " + catById.data.CategoryFindOne.name
|
|
|
- mainMenu = document.createElement('a')
|
|
|
- mainMenu.innerText = "Назад в главное меню"
|
|
|
- mainMenu.onclick = () => {
|
|
|
- main.innerText = ''
|
|
|
- drawMainMenu()
|
|
|
- }
|
|
|
- aside.append(mainMenu, cats)
|
|
|
-
|
|
|
- let goods = catById.data.CategoryFindOne.goods
|
|
|
- for (let {_id, name, price, description, images} of goods) {
|
|
|
- let div = document.createElement('div')
|
|
|
- div.className = 'goods'
|
|
|
- let btnCart = document.createElement('btn')
|
|
|
- let btn = document.createElement('button')
|
|
|
- btn.textContent = "Добавить в карзину"
|
|
|
- let img = document.createElement('img')
|
|
|
- img.style.width ='400px'
|
|
|
- img.src = `http://shop-roles.asmer.fs.a-level.com.ua/${images[0].url}`
|
|
|
- let prices = document.createElement('span')
|
|
|
- let descriptions = document.createElement('p')
|
|
|
- prices.innerText = `Цена: ${price} грн`
|
|
|
- descriptions.innerText = `Описание: ${description}`
|
|
|
- let goodA = document.createElement('a')
|
|
|
- goodA.href = `#/good/${_id}`
|
|
|
- goodA.innerText = name
|
|
|
- main.append(div)
|
|
|
- btnCart.append(btn)
|
|
|
- div.append(goodA, img, prices, descriptions, btnCart)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (route === 'good') {
|
|
|
- const goodById = store.getState().goodById?.payload
|
|
|
- const catById = store.getState().catById?.payload
|
|
|
- if (goodById) {
|
|
|
- aside.innerText = ''
|
|
|
- main.innerText = ''
|
|
|
- let cats = document.createElement('p')
|
|
|
- cats.innerText = "Вы в категории ==>" + " " + catById.data.CategoryFindOne.name
|
|
|
- menuGoods = document.createElement('a')
|
|
|
- menuGoods.innerText = catById.data.CategoryFindOne.name + " " + "<== Назад в список товаров"
|
|
|
- mainMenu = document.createElement('a')
|
|
|
- mainMenu.innerText = "Назад в главное меню"
|
|
|
- mainMenu.onclick = () => {
|
|
|
- main.innerText = ''
|
|
|
- drawMainMenu()
|
|
|
- }
|
|
|
- aside.append(mainMenu, cats)
|
|
|
-
|
|
|
- let good = goodById.data.GoodFind
|
|
|
- for (let {name, price, description, images} of good) {
|
|
|
- let div = document.createElement('div')
|
|
|
- div.className = 'good'
|
|
|
- let btn = document.createElement('button')
|
|
|
- btn.textContent = "Добавить в карзину"
|
|
|
- let img = document.createElement('img')
|
|
|
- img.style.width ='400px'
|
|
|
- img.src = `http://shop-roles.asmer.fs.a-level.com.ua/${images[0].url}`
|
|
|
- let prices = document.createElement('span')
|
|
|
- let descriptions = document.createElement('p')
|
|
|
- prices.innerText = `Цена: ${price} грн`
|
|
|
- descriptions.innerText = `Описание: ${description}`
|
|
|
- let goodA = document.createElement('a')
|
|
|
- goodA.innerText = name
|
|
|
- main.append(div)
|
|
|
- div.append(goodA, img, prices, descriptions, btn)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-})
|