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
'Content-Type': 'application/json',
...(localStorage.authToken ? {'Authorization': 'Bearer ' + localStorage.authToken} :
{})
},
//body с ключами query и variables
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;
}
}
//скопировать
//3 редьюсера
//экшоны к ним
//
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;
}
// Actions =============================
// Логин и логаут
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 = () =>
;
const Header = () =>