123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>thunk 2</title>
- <style>
- #mainContainer{
- display:flex;
- }
- #aside{
- width: 30%;
- }
- #aside > a{
- display: block;
- }
- img{
- width:300px;
- }
- </style>
- </head>
- <body>
- <header>Куда я попал?</header>
- <div id="mainContainer">
- <aside id="aside">
- Категории
- </aside>
- <main id="main">
- Контент
- </main>
- </div>
- <script>
- 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
- }
- }
- function promiseReducer(state={},{type,status,payload,error,name}){
- //{login:{status,payload,error}
- //catById: {status,payload,error}
- //}
- if(type==="PROMISE"){
- //вернуть новый state, в котором один ключ поменян/добавлен на name
- //значение этого ключа - обьект вида {status,payload,error}
- 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 delay=ms=>new Promise(ok=>setTimeout(()=>ok(ms),ms))
- const store=createStore(promiseReducer);
- store.subscribe(()=>console.log(store.getState()))
- /*store.dispatch(actionPending('delay1000'))
- delay(1000).then(data=>store.dispatch(actionResolved('delay1000',data)),
- err=>dispatch(actionRejected('delay1000',error)))
- store.dispatch(actionPending('delay2000'))
- delay(2000).then(data=>store.dispatch(actionResolved('delay2000',data)),
- err=>dispatch(actionRejected('delay2000',error)))*/
- const actionPromise=(name,promise)=>
- async dispatch=>{
- dispatch(actionPending(name))
- /*let data= await promise.then(data=>dispatch(actionResolved(name,data)),
- error=>dispatch(actionRejected(name,error)))*/
- try{
- let data= await promise
- dispatch(actionResolved(name,data))
- return data
- }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.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')
- 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())
- store.subscribe(()=>{
- const {rootCats}=store.getState()
- if(rootCats?.payload){
- aside.innerHTML=''
- for(const {_id,name} of rootCats?.payload){
- const link=document.createElement('a')
- link.href=`#/category/${_id}`
- link.innerHTML=name
- aside.append(link)
- }
- }
- })
- window.onhashchange=()=>{
- const [,route,_id]=location.hash.split('/')
- const routes={
- category(){
- store.dispatch(actionCatById(_id))
- },
- good(){
- //задиспатчить actionGoodById
- store.dispatch(actionGoodById(_id))
- console.log('ТОВАРОСТРАНИЦА')
- }
- }
- if(route in routes){
- routes[route]()
- }
- }
- window.onhashchange()
- store.subscribe(() => {
- const {catById} = store.getState()
- const [, route, _id] = location.hash.split('/')
- if (catById?.payload && route === 'category'){
- const { name } = catById.payload
- main.innerHTML = `<h1>${name}</h1>`
- //Тут должны быть подкатегории
- if (catById.payload.subCategories) {
- for (let { _id, name } of catById.payload.subCategories) {
- const link = document.createElement('a')
- link.href = `#/category/${_id}`
- link.textContent = name
- main.append(link)
- }
- }
- for (const { _id, name, price, images } of catById.payload.goods) {
- 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>`
- //Тут должны быть ссылка на страницу товара вида #/good/айди
- main.append(card)
- }
- }
- })
- store.subscribe(() => {
- const { goodById } = store.getState()
- const [, route, _id] = location.hash.split('/')
- if(goodById?.payload && route === 'good' && location.href.includes(`#/good/${_id}`)){
- main.innerHTML = ''
- let { _id, name, price, images, description } = goodById.payload
- let item = document.createElement('div')
- console.log(description);
- item.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(item)
- }
- })
- /*store.dispatch(actionPromise('delay1000',delay(1000)))
- store.dispatch(actionPromise('delay2000',delay(2000)))
- store.dispatch(actionPromise('luke',fetch('https://swapi.dev/api/people/1/').then(data=>data.json())))*/
- </script>
- </body>
- </html>
|