123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- 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 (state !== newState){
- state = newState
- cbs.forEach(cb => cb())
- }
- }
- return {
- dispatch,
- subscribe(cb){
- cbs.push(cb)
- return () => cbs = cbs.filter(c => c !== cb)
- },
- getState(){
- return state
- }
- }
- }
- function promiseReducer(state={}, {type, status, payload, error, name}){
- if (type === 'PROMISE'){
- return {
- ...state,
- [name]:{status, payload, error}
- }
- }
- return state
- }
- const store = createStore(promiseReducer)
- const unsubscribe1 = store.subscribe(() => console.log(store.getState()))
- 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 delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
- 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))
- }
- }
- const getGQL = url => {
- return function(query, variables={}) {
- return fetch(url,
- {
- method: "POST",
- headers:
- {"Content-Type": "application/json",
- ...(localStorage.authToken ? {Authorization: localStorage.authToken} : {})
- },
- body: JSON.stringify({query, variables})
- }).then(resp => resp.json())
- .then(data => {
- if ("errors" in data) {
- throw new Error('ашипка, угадывай што не так')
- }
- else {
- return data.data[Object.keys(variables)[0]]
- }
- })
- }
- }
- let shopGQL = getGQL('http://shop-roles.asmer.fs.a-level.com.ua/graphql')
- const goodById = goodId => {
- let id = `[{"_id":"${goodId}"}]`
- return shopGQL(`
- query good($id:String){
- GoodFindOne(query: $id) {
- name description price images {
- _id text url
- }
- categories {
- _id name
- }
- }
- }`, {GoodFindOne: '', id })
- }
- const actionGoodById = id =>
- actionPromise('goodById', goodById(id))
- const actionRootCategories = () =>
- actionPromise('rootCategories', shopGQL(`
- query cats($query:String){
- CategoryFind(query:$query){
- _id name
- }
- }
- `, {CategoryFind:'', query: JSON.stringify([{parent:null}])}))
- const actionCategoryById = (_id) =>
- actionPromise('catById', shopGQL(`query catById($query:String){
- CategoryFindOne(query:$query){
- _id name goods{
- _id name price description images{
- url
- }
- }
- }
- }`, {CategoryFindOne:'', query: JSON.stringify([{_id}])}))
- store.dispatch(actionRootCategories())
- 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){ //каждый раз дорисовываются в body
- aside.innerText = ''
- for (let {_id, name} of cats){
- let catA = document.createElement('a')
- catA.href = `#/categories/${_id}`
- catA.innerText = name
- aside.append(catA)
- }
- }
- }
- store.subscribe(drawMainMenu)
- store.subscribe(() => {
- const {1: route, 2:id} = location.hash.split('/')
- if (route === 'categories'){
- const catById = store.getState().catById?.payload
- if (catById){
- main.innerText = ''
- let categoryName = document.createElement('div')
- categoryName.innerText = catById.name
- categoryName.style.fontSize = '25px'
- categoryName.style.fontWeight = 'bold'
- main.append(categoryName)
- for (let {_id, name} of catById.goods){
- let good = document.createElement('a')
- good.href = `#/good/${_id}`
- good.innerText = name
- let btn = document.createElement('button')
- btn.style.cursor = 'pointer'
- btn.innerText = 'купыть'
- main.append(good, btn)
- }
- }
- }
- if (route === 'good'){
- const goodById = store.getState().goodById?.payload
- if (goodById){
- main.innerText = ''
- let {name, description, price} = goodById
- let goodName = document.createElement('div')
- goodName.innerText = name
- goodName.style.fontSize = '35px'
- goodName.style.fontWeight = 'bold'
- goodName.style.marginBottom = '25px'
- let goodDescription = document.createElement('div')
- goodDescription.innerText = description
- goodDescription.style.marginBottom = '25px'
- let goodPrice = document.createElement('div')
- goodPrice.innerText = 'Цена: ' + price
- goodPrice.style.marginBottom = '5px'
- let btn = document.createElement('button')
- btn.style.cursor = 'pointer'
- btn.innerText = 'купыть'
- main.append(goodName, goodDescription, goodPrice, btn)
- }
- }
- })
|