import React, {useState} from 'react'; import {Header} from "./components/Header"; import {LoginForm} from "./components/LoginForm"; import {Main} from "./components/Main"; import {Input} from "./components/Input"; import CategoryMenu from "./components/CategoryMenu"; import Category from "./components/Category"; import Footer from "./components/Footer"; import thunk from "redux-thunk"; import { createStore, combineReducers, applyMiddleware } from "redux"; import { Provider, connect } from "react-redux"; import {mapStateToPropsFactory} from "react-redux/es/connect/mapStateToProps"; import Spoiler from "./components/Spoiler"; import RangeInput from "./components/RangeInput"; import PasswordConfirm from "./components/PasswordConfirm"; function jwtDecode(token){ try { return JSON.parse(atob(token.split('.')[1])) } catch(e){ } } function authReducer(state, {type, token}) { if (!state) { if (localStorage.authToken) { token = localStorage.authToken type = 'AUTH_LOGIN' } else { return {} } } if (type === 'AUTH_LOGIN') { let payload = jwtDecode(token) if (typeof payload === 'object') { localStorage.authToken = token return { ...state, token, payload } } else { return state } } if (type === 'AUTH_LOGOUT') { localStorage.removeItem("authToken"); return {} } return state } const actionAuthLogin = (token) => ({type: 'AUTH_LOGIN', token}) const actionAuthLogout = () => ({type: 'AUTH_LOGOUT'}) function cartReducer (state={}, {type, good={}, count=1}) { if (Object.keys(state).length === 0 && localStorage.cart) { let currCart = JSON.parse(localStorage.cart) if (currCart && Object.keys(currCart).length !== 0) { state = currCart } } const {_id} = good const types = { CART_ADD() { count = +count if (!count) { return state } let newState = { ...state, [_id]: {good, count: (count + (state[_id]?.count || 0)) < 1 ? 1 : count + (state[_id]?.count || 0)} } localStorage.cart = JSON.stringify(newState) return newState }, CART_CHANGE() { count = +count if (!count) { return state } let newState = { ...state, [_id]: {good, count: count < 0 ? 0 : count} } localStorage.cart = JSON.stringify(newState) return newState }, CART_REMOVE() { let { [_id]: removed, ...newState } = state localStorage.cart = JSON.stringify(newState) return newState }, CART_CLEAR() { localStorage.cart = JSON.stringify({}) return {} }, } if (type in types) { return types[type]() } return state } const actionCartAdd = (good, count) => ({type: 'CART_ADD', good, count}) const actionCartChange = (good, count) => ({type: 'CART_CHANGE', good, count}) const actionCartRemove = (good) => ({type: 'CART_REMOVE', good}) const actionCartClear = () => ({type: 'CART_CLEAR'}) function promiseReducer(state={}, {type, status, payload, error, name}) { if (!state) { return {} } if (type === 'PROMISE') { return { ...state, [name]: { status: status, payload : payload, error: 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 data = await promise dispatch(actionResolved(name, data)) return data } catch(error){ dispatch(actionRejected(name, error)) } } ) const getGQL = url => ( async (query, variables={}) => { let obj = await fetch(url, { method: 'POST', headers: { "Content-Type": "application/json", ...(localStorage.authToken ? {Authorization: "Bearer " + localStorage.authToken} : {}) }, body: JSON.stringify({ query, variables }) }) let a = await obj.json() if (!a.data && a.errors) { throw new Error(JSON.stringify(a.errors)) } else { return a.data[Object.keys(a.data)[0]] } } ) const backURL = 'http://shop-roles.node.ed.asmer.org.ua/' const gql = getGQL(backURL + 'graphql'); const actionOrder = () => ( async (dispatch, getState) => { let {cart} = getState() const orderGoods = Object.entries(cart) .map(([_id, {good, count}]) => ({good: {_id}, count})) let result = await dispatch(actionPromise('order', gql(` mutation newOrder($order:OrderInput){ OrderUpsert(order:$order) { _id total} } `, {order: {orderGoods}}))) if (result?._id) { dispatch(actionCartClear()) } }) const actionLogin = (login, password) => ( actionPromise('login', gql(`query log($login: String, $password: String) { login(login: $login, password: $password) }`, {login, password})) ) const actionFullLogin = (log, pass) => async (dispatch) => { let token = await dispatch( actionPromise( "login", gql( `query login($login: String, $password: String) { login(login: $login, password: $password) }`, { login: log, password: pass } ) ) ); if (token) { dispatch(actionAuthLogin(token)); } }; const actionRegister = (login, password) => ( actionPromise('register', gql(`mutation reg($user:UserInput) { UserUpsert(user:$user) { _id } } `, {user: {login, password}}) ) ) const actionFullRegister = (login, password) => ( async (dispatch) => { let registerId = await dispatch(actionRegister(login, password)) if (registerId) { dispatch(actionFullLogin(login, password)) } } ) 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 images { url } } subCategories { _id name } } }`, {q: JSON.stringify([{_id}])})) ) const actionGoodById = (_id) => ( actionPromise('goodById', gql(`query goodById($q: String) { GoodFindOne(query: $q) { _id name price description images { url } } }`, {q: JSON.stringify([{_id}])})) ) const actionGoodsByUser = (_id) => ( actionPromise('goodByUser', gql(`query oUser($query: String) { OrderFind(query:$query){ _id orderGoods{ price count total good{ _id name categories{ name } images { url } } } owner { _id login } } }`, {query: JSON.stringify([{___owner: _id}])})) ) const combinedReducer = combineReducers({promise: promiseReducer, auth: authReducer, cart: cartReducer}) const store = createStore(combinedReducer) const CLoginForm = connect(null, {onLogin: actionLogin})(LoginForm) function App() { return (
{/*
*/} {/**/} Заголовок!!!} open={false}> Контент 1

лорем ипсум траливали и тп.

Заголовок 2 !!!} open={false}>

Контент 2

лорем ипсум траливали и тп.

); } export default App;