import "./App.scss"; import {createStore, combineReducers, applyMiddleware} from "redux"; import {Provider, connect} from "react-redux"; import thunk from "redux-thunk"; import React, {useState, useEffect} from "react"; import {Router, Route, Link, Redirect, Switch} from 'react-router-dom'; import createHistory from "history/createBrowserHistory"; const promiseReducer = function(state={}, {type, name, status, payload, error}) { if (type == 'PROMISE'){ return { ...state, [name]:{status, payload, error} } } return state; }; const actionPending = name => ({type: "PROMISE", name, status: 'PENDING'}); const actionFulfilled = (name,payload) => ({type: "PROMISE", name, status: 'FULFILLED', payload}); const actionRejected = (name,error) => ({type: "PROMISE", name, status: 'REJECTED', error}); const actionPromise = function(name, promise) { return async dispatch => { dispatch(actionPending(name)); try { let payload = await promise dispatch(actionFulfilled(name, payload)) return payload } catch(error){ dispatch(actionRejected(name, error)) }; }; }; let jwtDecode = function(token) { let payloadInBase64; let payloadInJson; let payload; try { payloadInBase64 = token.split(".")[1]; payloadInJson = atob(payloadInBase64); payload = JSON.parse(payloadInJson); return payload; } catch(err) { } }; const authReducer = function(state, {type, token}) { let payload; if (state == undefined) { if(localStorage.authToken) { type = "AUTH_LOGIN"; token = localStorage.authToken; } else { type = "AUTH_LOGOUT"; }; }; if (type == "AUTH_LOGIN") { payload = jwtDecode(token); if(payload) { localStorage.authToken = token; return { token: token, payload: payload } } }; if (type == "AUTH_LOGOUT") { localStorage.removeItem("authToken"); return {}; }; return state || {}; }; const actionAuthLogin = token => ({type: "AUTH_LOGIN", token}); const actionAuthLogout = () => ({type: "AUTH_LOGOUT"}); const actionFullLogin = function(login, password) { return async dispatch => { let token = await gql("query userLogin($login: String, $password: String) {login(login: $login, password: $password)}", {"login": login, "password": password}); dispatch(actionAuthLogin(token)); }; }; let actionFullRegister = function(login, password, nick) { return async dispatch => { dispatch(actionPromise("userRegister", gql(`mutation userRegister($login:String, $password:String, $nick:String) { UserUpsert(user: {login:$login, password:$password, nick:$nick}) { _id login nick } }`, { "login": login, "password": password, "nick": nick }))); dispatch(actionFullLogin(login, password)); }; }; let cartReducer = function(state={}, {type, good, count=1}) { if(type == "CART_ADD") { let newState = {...state}; if(good["_id"] in state) { newState[good._id] = {count: newState[good._id].count + count, good} } else { newState = { ...state, [good._id]: {count, good} }; }; return newState; }; if(type == "CART_CHANGE") { let newState = {...state, [good._id]: {count, good} }; return newState; }; if(type == "CART_DELETE") { let newState = {...state}; delete newState[good._id]; return newState; }; if(type == "CART_CLEAR") { return {}; }; return state; }; const actionCartAdd = (good, count=1) => ({type: 'CART_ADD', good, count: +count}) const actionCartChange = (good, count=1) => ({type: 'CART_CHANGE', good, count: +count}) const actionCartDelete = (good) => ({type: 'CART_DELETE', good}) const actionCartClear = () => ({type: 'CART_CLEAR'}) const getGQL = function(url) { return async function(query, variables) { const res = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", ...(localStorage.authToken ? { "Authorization": "Bearer " + localStorage.authToken } : {}) }, body: JSON.stringify({ query, variables }) }); const data = await res.json(); if (data.data) { return Object.values(data.data)[0]; } else { throw new Error(JSON.stringify(data.errors)); }; }; }; const backendURL = 'http://shop-roles.asmer.fs.a-level.com.ua'; const gql = getGQL(backendURL + '/graphql'); let actionRootCats = function() { return actionPromise("rootCats", gql(`query { CategoryFind(query: "[{\\"parent\\":null}]"){ _id name } }`)); }; let actionCatById = function(_id) { return actionPromise("catById", gql(`query catById($q: String){ CategoryFindOne(query: $q){ _id name goods { _id name price images { url } } } }`, {q: JSON.stringify([{_id}])} )); }; let actionGoodById = function(_id) { return actionPromise("goodById", gql(`query findGood($goodQuery: String) { GoodFindOne(query:$goodQuery) { _id name price images { url } } }`, {goodQuery: JSON.stringify([{"_id": _id}])} )); }; let actionOrders = async function() { let order = await gql(`mutation makeOrder($order:OrderInput){ OrderUpsert(order: $order){ _id } }`, { "order": { orderGoods: Object.entries(store.getState().cart).map(([_id, count]) =>({"count": count.count, "good": {_id}})) } }); store.dispatch(actionCartClear()); } let actionOrdersFind = function() { return actionPromise("ordersFind", gql(`query ordersFind($query:String) { OrderFind(query: $query) { createdAt orderGoods { count good { name price images { url } } } } }`, { "query": JSON.stringify([{}]) })); } const store = createStore(combineReducers({promise: promiseReducer, auth: authReducer, cart: cartReducer}), applyMiddleware(thunk)); store.subscribe(() => console.log(store.getState())); store.dispatch(actionRootCats()); let Nav = function({auth}) { return ( ); }; const CNav = connect(state => ({auth: state.auth}))(Nav); let Header = function() { return (
Типо логотип
); }; let RootCategories = function({rootCats}) { return ( ); }; const CRootCategories = connect(state => ({rootCats: state.promise?.rootCats?.payload || []}))(RootCategories); let MainPage = function() { return (

Главная страничка

); }; let GoodCard = function({good}) { return (
  • {good.name}
    Цена: {good.price}
    Перейти на страничку товара
  • ); }; let Goods = function({goods}) { return (
    ); }; const CGoods = connect(state => ({goods: state.promise?.catById?.payload?.goods || []}))(Goods); let Categories = function({match: {params: {_id}}, catById}) { catById(_id); return ( ); }; const CCategories = connect(null, {catById: actionCatById})(Categories); let GoodPageCard = function({good, cartAdd}) { return (
    {good?.name}
    Цена: {good?.price}
    ); }; const CGoodPageCard = connect(state => ({good: state.promise?.goodById?.payload}), {cartAdd: actionCartAdd})(GoodPageCard) let GoodPage = function({match: {params: {_id}}, goodById}) { goodById(_id); return ( ); }; const CGoodPage = connect(null, {goodById: actionGoodById})(GoodPage); let Login = function({fullLogin}) { const [login, setLogin] = useState(""); const [password, setPassword] = useState(""); return (

    Логин

    setLogin(evt.target.value)} />
    setPassword(evt.target.value)} />
    ); }; const CLogin = connect(null, {fullLogin: actionFullLogin})(Login); let Registration = function({fullRegister}) { const [login, setLogin] = useState(""); const [nick, setNick] = useState(""); const [password, setPassword] = useState(""); return (

    Регистрация

    setLogin(evt.target.value)} />
    setNick(evt.target.value)} />
    setPassword(evt.target.value)} />
    ); }; const CRegistration = connect(null, {fullRegister: actionFullRegister})(Registration) let CardGood = function({good: {count, good}, cartChange, cartDelete}) { const [value, setValue] = useState(count); return ( {good?.name} Цена: {good?.price} Количество: { setValue(evt.target.value); cartChange(good, evt.target.value); }}/> ); }; const CCardGood = connect(null, {cartChange: actionCartChange, cartDelete: actionCartDelete})(CardGood); let Cart = function({cart, makeOrder}) { return (

    Корзина

    {cart.map(good => )}
    ); }; const CCart = connect(state => ({cart: Object.values(state.cart) || []}), {makeOrder: actionOrders})(Cart); let OrderGood = function({good: {count, good}}) { return (
    • {good?.name}
    • Цена: {good?.price}
    • Количество: {count}
  • ); }; let Order = function({order: {createdAt, orderGoods}}) { return ( {(new Date(+createdAt)).toLocaleString()} ); } let Dashboard = function({orders}) { return ( {orders.map(order => )}
    ); }; const CDashboardTable = connect(state => ({orders: state.promise?.ordersFind?.payload || []}))(Dashboard) let PreDashboard = function({orderFind}) { orderFind(); return (

    История заказов

    ); }; const CDashboard = connect(null, {orderFind: actionOrdersFind})(PreDashboard); let Content = function() { return ( ); }; let Main = function() { return (
    ); }; const history = createHistory() function App() { return (
    ); } export default App;