|
@@ -0,0 +1,240 @@
|
|
|
|
+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
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const getGQL = url =>
|
|
|
|
+ (query, variables) => fetch(url, {
|
|
|
|
+ method: 'POST',
|
|
|
|
+ headers: {
|
|
|
|
+ "Content-Type": "application/json",
|
|
|
|
+ // 'Accept' : 'application/json',
|
|
|
|
+ ...(localStorage.authToken ? {"Authorization": "Bearer " + localStorage.authToken} : {})
|
|
|
|
+ },
|
|
|
|
+ body: JSON.stringify({query, variables})
|
|
|
|
+ }).then(res => res.json())
|
|
|
|
+ .then(data => {
|
|
|
|
+ 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');
|
|
|
|
+
|
|
|
|
+const jwtDecode = token => {
|
|
|
|
+ try{
|
|
|
|
+ return JSON.parse(atob(token.split('.')[1]));
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ catch(e){
|
|
|
|
+ console.log(e.name, e.message);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function authReducer(state, {type, token}){
|
|
|
|
+ if (state === undefined){
|
|
|
|
+ if(localStorage.authToken){
|
|
|
|
+ type = 'AUTH_LOGIN';
|
|
|
|
+ token = localStorage.authToken
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(type === 'AUTH_LOGIN'){
|
|
|
|
+ let payload = jwtDecode(token);
|
|
|
|
+ if (payload){
|
|
|
|
+ localStorage.authToken = token
|
|
|
|
+ return {token, payload}
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(type === 'AUTH_LOGOUT'){
|
|
|
|
+ localStorage.removeItem("authToken")
|
|
|
|
+ return {}
|
|
|
|
+ }
|
|
|
|
+ return state || {}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function promiseReducer(state={}, {type, name, status, payload, error}){
|
|
|
|
+ if (type === 'PROMISE'){
|
|
|
|
+ return {
|
|
|
|
+ ...state,
|
|
|
|
+ [name]:{status, payload, error}
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return state
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const combineReducers = (reducers) => (state={}, action) => {
|
|
|
|
+ let newState = {}
|
|
|
|
+ for (const [reducerName, reducer] of Object.entries(reducers)){
|
|
|
|
+ let subNewState = reducer(state[reducerName],action)
|
|
|
|
+ if(subNewState !== state[reducerName]){
|
|
|
|
+ newState = {
|
|
|
|
+ ...newState, [reducerName] : subNewState
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(Object.keys(newState).length > 0){
|
|
|
|
+ return {
|
|
|
|
+ ...state,...newState
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return state
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const actionAuthLogin = (token) => ({type: 'AUTH_LOGIN', token});
|
|
|
|
+const actionAuthLogout = () => ({type: 'AUTH_LOGOUT'});
|
|
|
|
+
|
|
|
|
+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 delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
|
|
|
|
+
|
|
|
|
+const store = createStore(combineReducers({promise: promiseReducer, auth: authReducer}));
|
|
|
|
+store.subscribe(() => console.log(store.getState()))
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+const actionPromise = (name, promise) =>
|
|
|
|
+async dispatch => {
|
|
|
|
+ dispatch(actionPending(name))
|
|
|
|
+ try {
|
|
|
|
+ let payload = await promise
|
|
|
|
+ dispatch(actionFulfilled(name, payload))
|
|
|
|
+ return payload
|
|
|
|
+ }
|
|
|
|
+ catch(error){
|
|
|
|
+ dispatch(actionRejected(name, error))
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const actionFullRegister = (log, pass) =>
|
|
|
|
+ async dispatch => {
|
|
|
|
+ let user = await dispatch(
|
|
|
|
+ actionPromise('register', gql( `mutation register($login: String, $password: String) {
|
|
|
|
+ UserUpsert(user: {login: $login, password: $password}) {
|
|
|
|
+ _id
|
|
|
|
+ login
|
|
|
|
+ }
|
|
|
|
+ }`, {login : log, password : pass}))
|
|
|
|
+ )
|
|
|
|
+ if(user){
|
|
|
|
+ dispatch(actionFullLogin(log, pass));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+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))
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+store.dispatch(actionFullRegister('bd2404', '2404'))
|
|
|
|
+// store.dispatch(actionAuthLogout());
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+const actionLuke = () => actionPromise('luke',
|
|
|
|
+ fetch('https://swapi.dev/api/people/1')
|
|
|
|
+ .then(res => res.json()))
|
|
|
|
+store.dispatch(actionLuke())
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+const actionCategoryById = (_id) =>
|
|
|
|
+ actionPromise('catById', gql(`query catById($q: String){
|
|
|
|
+ CategoryFindOne(query: $q){
|
|
|
|
+ _id name goods {
|
|
|
|
+ _id name price images {
|
|
|
|
+ url
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }`, {q: JSON.stringify([{_id}])}));
|
|
|
|
+
|
|
|
|
+store.dispatch(actionCategoryById("5dc458985df9d670df48cc47"));
|
|
|
|
+
|
|
|
|
+const actionGoodById = (_id) =>
|
|
|
|
+ actionPromise('goodById', gql(`query goodByid($goodId: String) {
|
|
|
|
+ GoodFindOne(query: $goodId) {
|
|
|
|
+ name
|
|
|
|
+ price
|
|
|
|
+ description
|
|
|
|
+ images {
|
|
|
|
+ url
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }`, {goodId: JSON.stringify([{_id}])}))
|
|
|
|
+
|
|
|
|
+store.dispatch(actionGoodById("5dc4a3e15df9d670df48cc6b"));
|
|
|
|
+
|
|
|
|
+const actionRootCategories = () =>
|
|
|
|
+ actionPromise('rootCats', gql(`query {
|
|
|
|
+ CategoryFind(query: "[{\\"parent\\":null}]"){
|
|
|
|
+ _id name
|
|
|
|
+ }
|
|
|
|
+ }`))
|
|
|
|
+
|
|
|
|
+store.dispatch(actionRootCategories());
|
|
|
|
+
|
|
|
|
+const actionNewOrder = (order) =>
|
|
|
|
+ actionPromise('newOrder', gql( `mutation newOrder($order: OrderInput) {
|
|
|
|
+ OrderUpsert(order: $order) {
|
|
|
|
+ _id
|
|
|
|
+ total
|
|
|
|
+ }
|
|
|
|
+ }`, {order : order}
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ )
|
|
|
|
+let order = {
|
|
|
|
+ orderGoods: [
|
|
|
|
+ {count: 2, good: {_id: "5dcac57d6d09c45440d14cfc"}},
|
|
|
|
+ {count: 2, good: {_id: "5dcac9ba6d09c45440d14d02"}},
|
|
|
|
+ {count: 1, good: {_id: "5dc8844e0e36db246e3049bd"}},
|
|
|
|
+ ]
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// store.dispatch(actionNewOrder(order));
|
|
|
|
+
|
|
|
|
+const actionOrders = () =>
|
|
|
|
+ actionPromise('allOrders', gql(`query findOrder($q: String) {
|
|
|
|
+ OrderFind(query: $q) {
|
|
|
|
+ _id
|
|
|
|
+ total
|
|
|
|
+ orderGoods {
|
|
|
|
+ count
|
|
|
|
+ good {
|
|
|
|
+ name
|
|
|
|
+ price
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }`, {q: JSON.stringify([{}])}))
|
|
|
|
+
|
|
|
|
+// store.dispatch(actionOrders())
|