123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- <!DOCTYPE html>
- <html>
- <head>
- <title>My</title>
- <meta charset='utf8' />
- <style>
- #mainContainer {
- display: flex;
- }
- #aside {
- width: 30%;
- }
- #aside > a {
- text-decoration: none;
- display: block;
- }
- img{
- width:250px;
- }
- #main a{
- text-decoration: none;
- border-bottom: 3px solid pink;
- padding-bottom: 1px
- }
- .link {
- display: block;
- }
- .good_item {
- text-align: center;
- }
- .description {
- text-align: right;
- }
- #i{
- margin-bottom: 30px;
- width: 50px;
- }
- </style>
- </head>
- <body>
- <header id="he">
- <a href="#/" id="cartIcon" ><img src="data:image/png;base64,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" id="i"></a>
- </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, 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))
- 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 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.innerText = name
- aside.append(link)
- }
- }
- })
- window.onhashchange = () => {
- const [, route, _id] = location.hash.split('/')
- const routes = {
- category() {
- store.dispatch(actionCatById(_id))
- },
- good() {
- 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>`
- for (const good of 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}" />
- <strong>${price}</strong>
- `
- main.append(card);
- }
- }
- })*/
- 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.className = 'link'
- 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>
- <strong>Стоимость: <i>${price} UAH</i></strong><br>
- <p><a href=#/good/${_id}>Страница товара</a>
- </p>
- </div>`
- let btn=document.createElement('input');
- btn.value='Купить';
- btn.type='submit';
- btn.style.marginLeft=230+'px';
- btn.style.marginTop=5+'px';
- btn.onclick=()=>console.log('hello')
- main.append(card,btn)
- }
- }
- })
- 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 goodItem = document.createElement('div')
- goodItem.className = 'good_item'
- goodItem.innerHTML = `
- <h2>${name}</h2>
- <img src="${backURL}/${images[0].url}"/>
- <div>
- <p><strong>Стоимость: <i>${price} UAH</i></strong></p>
- <p><strong>Описание:</strong> <i>${description}</i></p>
- </div>
- `
- main.append(goodItem)
- }
- })
- </script>
- </body>
- </html>
|