import logo from './logo.svg'; import './App.scss'; import thunk from 'redux-thunk'; import {createStore, combineReducers, applyMiddleware} from 'redux'; import {Provider, connect} from 'react-redux'; 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 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 backendURL = "http://shop-roles.asmer.fs.a-level.com.ua" const gql = getGQL(backendURL + '/graphql') function jwtDecode(token) { try { let decoded = token.split('.') decoded = decoded[1] decoded = atob(decoded) decoded = JSON.parse(decoded) return decoded } catch (e) { return; } } const actionRootCats = () => actionPromise('rootCats', gql(`query { CategoryFind(query: "[{\\"parent\\":null}]"){ _id name } }`)) const actionCartAdd = (good, count = 1) => ({ type: 'CART_ADD', good, count }) const actionCartRemove = (good, count = 1) => ({ type: 'CART_REMOVE', good, count }) const actionCartChange = (good, count = 1) => ({ type: 'CART_CHANGE', good, count }) const actionCartClear = (good, count = 1) => ({ type: 'CART_CLEAR', good, count }) function cartReducer(state = {}, { type, good={}, count=1}){ const {_id } = good const types = { CART_ADD() { return { ...state, [_id]: { good, count: count + (state[_id]?.count || 0)} } }, CART_REMOVE(){ let newState = { ...state } delete newState[_id] return { ...newState } }, CART_CHANGE(){ return { ...state, [_id]:{good, count} } }, CART_CLEAR(){ return {} }, } if (type in types) return types[type]() return state } function authReducer(state, {type, token}){ if (!state) { if (localStorage.authToken) { type = 'AUTH_LOGIN' token = localStorage.authToken } else { return {} } } if (type === 'AUTH_LOGIN') { let auth = jwtDecode(token) if (auth) { localStorage.authToken = token return { token, payload: auth } } } if (type === 'AUTH_LOGOUT') { localStorage.authToken = '' return {} } return state } function promiseReducer(state={}, {type, name, status, payload, error}){ if (type === 'PROMISE'){ return { ...state, [name]:{status, payload, error} } } return state } const actionAuthLogin = (token) => ({ type: 'AUTH_LOGIN', token }) const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' }) const actionLogin = (login = 'tst', password = '123') => actionPromise('login', gql(`query ($login:String, $password:String){ login(login:$login, password:$password)}`, { 'login': login, 'password': password })) const actionFullLogin = (login = 'tst', password = '123') => async dispatch => { let token = await dispatch(actionLogin(login, password)) if (token) { dispatch(actionAuthLogin(token)) } } const actionRegister = (login = 'tst', password = '123') => actionPromise('login', gql(`mutation reg($login:String, $password:String) { UserUpsert(user:{login:$login, password:$password, nick:$login}){ _id login } }`, { 'login': login, 'password': password })) const actionFullRegister = (login = 'tst', password = '123') => async dispatch => { await dispatch(actionRegister(login, password)) await dispatch(actionFullLogin(login, password)) } const actionCatById = (_id) => actionPromise('catById', gql(`query ($q: String){ CategoryFindOne(query: $q){ _id name goods { _id name price images { url } } subCategories { _id name } } }`, { q: JSON.stringify([{ _id }]) })) const actionGoodById = (_id) => actionPromise('goodById', gql(`query ($good:String) { GoodFindOne(query:$good) { _id name price images { url } } }`, { good: JSON.stringify([{ _id }]) })) const store = createStore(combineReducers({promise: promiseReducer, auth: authReducer, cart: cartReducer}), applyMiddleware(thunk)) store.subscribe(() => console.log(store.getState())) store.dispatch(actionRootCats()) store.dispatch(actionCatById('5dc458985df9d670df48cc47')) const Logo = () => logo const Header = () =>
const Navbar = () => const CategoryListItem = ({_id, name}) =>
  • {name}
  • const CategoryList = ({cats}) => const CCategoryList = connect(state => ({cats:state.promise.rootCats?.payload || []}))(CategoryList) const Aside = () => const GoodCard = ({good:{_id, name, price, images}, onAdd}) =>
  • {name}

    {images && images[0] && images[0].url && }
    Цена: {price}
  • const CGoodCard = connect(null, {onAdd: actionCartAdd})(GoodCard) const Category = ({cat:{name, goods=[]}={}}) =>

    {name}

    const CCategory = connect(state => ({cat:state.promise.catById?.payload || {}}))(Category) const Koshik = ({cart}) => { let goodsInCart = cart let allGoodsInCart = 0 for (let key in goodsInCart) { allGoodsInCart += goodsInCart[key].count } return (

    Корзина: {allGoodsInCart}

    ) } const CKoshik = connect(({cart}) => ({cart}))(Koshik) const CartItem = ({cart:{_id, name, price, images}, count: {count}, onChange, onRemove}) => { console.log('good', _id) return(
  • {name}

    {images && images[0] && images[0].url && }
    Цена: {price * count}  
  • ) } const CCartItem = connect(null, {onChange: actionCartChange, onRemove: actionCartRemove})(CartItem) const Cart = ({cart}) => { let cartArr = [] for(let item in cart) { cartArr.push(cart[item]) } console.log('cartarr',cartArr) return(

    Корзина

    ) } const CCart = connect(state => ({cart:state.cart}))(Cart) //const CCart = connect(забрать из редакса корзину положить в пропс cart, //дать компоненту onCartChange и onCartRemove с соответствующими actionCreator)(Cart) const Main = () =>
    const Content = ({children}) =>
    {children}
    const Footer = () => function App() { return (
    ); } export default App;