Browse Source

added reworked sign in

Maxim 5 years ago
parent
commit
ba885f86b9

+ 16 - 21
package-lock.json

@@ -1803,6 +1803,15 @@
       "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
       "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
     },
+    "axios": {
+      "version": "0.18.0",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
+      "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
+      "requires": {
+        "follow-redirects": "^1.3.0",
+        "is-buffer": "^1.1.5"
+      }
+    },
     "axobject-query": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
@@ -5740,13 +5749,11 @@
         },
         "balanced-match": {
           "version": "1.0.0",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "brace-expansion": {
           "version": "1.1.11",
           "bundled": true,
-          "optional": true,
           "requires": {
             "balanced-match": "^1.0.0",
             "concat-map": "0.0.1"
@@ -5759,18 +5766,15 @@
         },
         "code-point-at": {
           "version": "1.1.0",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "concat-map": {
           "version": "0.0.1",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "console-control-strings": {
           "version": "1.1.0",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "core-util-is": {
           "version": "1.0.2",
@@ -5873,8 +5877,7 @@
         },
         "inherits": {
           "version": "2.0.3",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "ini": {
           "version": "1.3.5",
@@ -5884,7 +5887,6 @@
         "is-fullwidth-code-point": {
           "version": "1.0.0",
           "bundled": true,
-          "optional": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
@@ -5897,20 +5899,17 @@
         "minimatch": {
           "version": "3.0.4",
           "bundled": true,
-          "optional": true,
           "requires": {
             "brace-expansion": "^1.1.7"
           }
         },
         "minimist": {
           "version": "0.0.8",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "minipass": {
           "version": "2.2.4",
           "bundled": true,
-          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.1",
             "yallist": "^3.0.0"
@@ -5927,7 +5926,6 @@
         "mkdirp": {
           "version": "0.5.1",
           "bundled": true,
-          "optional": true,
           "requires": {
             "minimist": "0.0.8"
           }
@@ -6000,8 +5998,7 @@
         },
         "number-is-nan": {
           "version": "1.0.1",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "object-assign": {
           "version": "4.1.1",
@@ -6011,7 +6008,6 @@
         "once": {
           "version": "1.4.0",
           "bundled": true,
-          "optional": true,
           "requires": {
             "wrappy": "1"
           }
@@ -6117,7 +6113,6 @@
         "string-width": {
           "version": "1.0.2",
           "bundled": true,
-          "optional": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",

+ 1 - 0
package.json

@@ -3,6 +3,7 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
+    "axios": "^0.18.0",
     "bootstrap": "^4.2.1",
     "jquery": "^3.3.1",
     "node-sass": "^4.11.0",

+ 17 - 0
src/actions/auth/signIn.js

@@ -0,0 +1,17 @@
+import * as actionTypes from './../../constants/auth';
+
+export const signIn = payload => {
+    console.log('Inside the signIn action', payload);
+    return {
+        type: actionTypes.SIGN_IN_REQUEST,
+        payload
+    };
+}
+export const signInSuccess = payload => ({
+    type: actionTypes.SIGN_IN_REQUEST_SUCCESS,
+    payload
+});
+export const signInFailure = error => ({
+    type: actionTypes.SIGN_IN_REQUEST_FAILURE,
+    error
+});

+ 14 - 0
src/actions/auth/signUp.js

@@ -0,0 +1,14 @@
+import * as actionTypes from './../../constants/auth';
+
+export const signUp = payload => ({
+    type: actionTypes.SIGN_UP_REQUEST,
+    payload
+});
+export const signUpSuccess = payload => ({
+    type: actionTypes.SIGN_UP_REQUEST_SUCCESS,
+    payload
+});
+export const signUpFailure = error => ({
+    type: actionTypes.SIGN_UP_REQUEST_FAILURE,
+    error
+});

+ 1 - 1
src/components/common/formInput.js

@@ -3,6 +3,6 @@ import React, { Fragment } from 'react';
 export default ({ input, className, placeholder, type, meta: { touched, error } }) => (
     <Fragment>
         <input className={className} placeholder={placeholder} type={type} {...input} />
-        {touched && (error && <p style={{"color": "red", "textTransform": "uppercase"}}>⚠ {error}</p>)}
+        {touched && (error && <p className="text-af pt-2 text-uppercase">⚠ {error}</p>)}
     </Fragment>
 )

+ 3 - 2
src/components/common/protectedRoute.js

@@ -2,7 +2,7 @@ import React from 'react';
 import { Route, Redirect } from 'react-router-dom';
 import * as routes from './../../constants/routes';
 
-export default ({ component: Component, user: { data : checkedData }, tokenAuth, access, ...rest }) => (
+export default ({ component: Component, user, tokenAuth, access, ...rest }) => (
     <Route
         {...rest}
         render={props => {
@@ -21,10 +21,11 @@ export default ({ component: Component, user: { data : checkedData }, tokenAuth,
                     checkedData = null;
                 }
             } */}
+            const checkedData = user && user.data ? user.data : null;
 
             console.log('Component', Component);
             console.log('Access', access);
-            console.log('CheckedData', checkedData);
+            console.log('User Data', checkedData);
 
             if (access === 'public') {
                 return <Component {...props} />

+ 6 - 3
src/components/common/spinner.js

@@ -1,6 +1,9 @@
 import React from 'react';
 
-export default props => (
-    // add props optionally
-    null
+export default () => (
+    <div class="d-flex justify-content-center">
+        <div class="spinner-border" role="status">
+            <span class="sr-only">Loading...</span>
+        </div>
+    </div>
 )

+ 4 - 0
src/components/public/Header.js

@@ -39,6 +39,10 @@ export default class Header extends React.Component {
                                 <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" />
                                 <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
                             </form>
+                            <div className="btn-group ml-2" role="group">
+                                <button className="btn btn-secondary">Sign In</button>
+                                <button className="btn btn-secondary">Sign Up</button>
+                            </div>
                         </div>
                     </nav>
                 </div>

+ 23 - 15
src/components/public/SignIn/Form/index.js

@@ -1,29 +1,41 @@
 import React from 'react';
 import { reduxForm, Field } from 'redux-form';
-import { connect } from 'react-redux'
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux';
+
 import validate from './validate';
 import formInput from './../../../common/formInput';
 
 class Form extends React.Component {
 
-    submit(values) {
-        const { } = this.props;
-        console.log('Submit', values);
-        // TODO: request
+    submit = ({ email, password }) => {
+        const { signIn } = this.props;
+        signIn({
+            email,
+            password
+        })
     }
 
     render() {
-        const { handleSubmit } = this.props;
+        const { handleSubmit, error } = this.props;
 
         return (
-            <form className="text-center">
+            <form className="text-center" onSubmit={handleSubmit(this.submit)}>
+                {
+                    error
+                        ?
+                        <p className="text-af text-uppercase">{error}</p>
+                        :
+                        null
+                }
+
                 <div className="form-group">
-                    <label>Email address</label>
+                    <label className="text-uppercase">Email address</label>
                     <Field type="email" name='email' className="form-control" placeholder="name@example.com" component={formInput} />
                 </div>
 
                 <div className="form-group">
-                    <label>Password</label>
+                    <label className="text-uppercase">Password</label>
                     <Field type="password" name='password' className="form-control" placeholder="example123" component={formInput} />
                 </div>
 
@@ -33,11 +45,7 @@ class Form extends React.Component {
     }
 }
 
-const mapStateToProps = state => ({
-    user: state.user
-})
-
-export default connect(mapStateToProps, null)(reduxForm({
+export default reduxForm({
     form: "SignIn",
     validate
-})(Form))
+})(Form)

+ 29 - 3
src/components/public/SignIn/index.js

@@ -1,14 +1,40 @@
 import React from 'react';
 import Form from './Form';
+import { bindActionCreators } from 'redux';
+import { connect } from 'react-redux';
+import { Redirect } from 'react-router-dom'
 
-const SignIn = props => (
+import Spinner from './../../common/spinner';
+import { signIn } from './../../../actions/auth/signIn';
+
+const SignIn = ({ signIn, user }) => (
     <div className="row">
         <div className="container">
             <div className="col-4 m-auto p-4 border rounded">
-                <Form />
+                {
+                    user.isFetching
+                        ?
+                        <Spinner />
+                        : user.data
+                            ?
+                            <Redirect to='/' />
+                            : user.error
+                                ?
+                                <Form error={user.error} signIn={signIn} />
+                                :
+                                <Form signIn={signIn} />
+                }
             </div>
         </div>
     </div>
 )
 
-export default SignIn;
+const mapStateToProps = state => ({
+    user: state.signIn
+});
+const mapDispatchToProps = dispatch => bindActionCreators({
+    signIn
+}, dispatch);
+
+
+export default connect(mapStateToProps, mapDispatchToProps)(SignIn);

+ 2 - 2
src/constants/auth.js

@@ -1,9 +1,9 @@
-export const SIGN_IN_URL = 'https://quiz.maxcrc.de/api/v1/user?';
+export const SIGN_IN_URL = 'https://test-app-a-level.herokuapp.com/auth/login'; 
 export const SIGN_IN_REQUEST = 'SIGN_IN_REQUEST';
 export const SIGN_IN_REQUEST_SUCCESS = 'SIGN_IN_REQUEST_SUCCESS';
 export const SIGN_IN_REQUEST_FAILURE = 'SIGN_IN_REQUEST_FAILURE';
 
-export const SIGN_UP_URL = 'https://quiz.maxcrc.de/api/v1/user';
+export const SIGN_UP_URL = '';
 export const SIGN_UP_REQUEST = 'SIGN_UP_REQUEST';
 export const SIGN_UP_REQUEST_SUCCESS = 'SIGN_UP_REQUEST_SUCCESS';
 export const SIGN_UP_REQUEST_FAILURE = 'SIGN_UP_REQUEST_FAILURE';

+ 18 - 5
src/reducers/auth/signIn.js

@@ -1,13 +1,26 @@
-// import * as types from '';
-import intialState from './../initialState'
+import * as actionTypes from './../../constants/auth';
 import initialState from './../initialState';
 
-export default function signInReducer(state = initialState.signIn, {type, payload, error}) {
+export default function signInReducer(state = initialState.signIn, {type, payload: data, error}) {
     switch(type) {
-        case 1: {
+        case actionTypes.SIGN_IN_REQUEST: {
             return {
                 ...state,
-                test: 'test'
+                isFetching: true
+            }
+        }
+        case actionTypes.SIGN_IN_REQUEST_SUCCESS: {
+            return {
+                ...state,
+                isFetching: false,
+                data
+            }
+        }
+        case actionTypes.SIGN_IN_REQUEST_FAILURE: {
+            return {
+                ...state,
+                isFetching: false,
+                error
             }
         }
         default: {

+ 30 - 0
src/reducers/auth/signUp.js

@@ -0,0 +1,30 @@
+import * as actionTypes from './../../constants/auth';
+import initialState from './../initialState';
+
+export default function signInReducer(state = initialState.signUp, {type, payload, error}) {
+    switch(type) {
+        case actionTypes.SIGN_IN_REQUEST: {
+            return {
+                ...state,
+                isFetching: true
+            }
+        }
+        case actionTypes.SIGN_IN_REQUEST_SUCCESS: {
+            return {
+                ...state,
+                isFetching: false,
+                payload
+            }
+        }
+        case actionTypes.SIGN_IN_REQUEST_FAILURE: {
+            return {
+                ...state,
+                isFetching: false,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 10 - 1
src/reducers/initialState.js

@@ -1,3 +1,12 @@
 export default {
-    signIn: {}
+    signIn: {
+        isFetching: false,
+        data: null,
+        error: null
+    },
+    signUp: {
+        isFetching: false,
+        data: null,
+        error: null
+    }
 }

+ 6 - 11
src/router.js

@@ -2,9 +2,6 @@ import React, { Suspense, lazy } from "react";
 import { Switch, Route, withRouter } from "react-router-dom";
 import { connect } from 'react-redux';
 
-// import Header from "./containers/header";
-// import Footer from './components/public-components/footer';
-
 import ProtectedRoute from './components/common/protectedRoute';
 import config from './configs/routerConfig';
 
@@ -16,7 +13,7 @@ class Router extends React.Component {
     render() {
         const { user, tokenAuth } = this.props;
 
-        // TODO: add spinner, user
+        // TODO: add footer
         return (
             <div className="app">
                 <Header />
@@ -33,7 +30,7 @@ class Router extends React.Component {
                                 path={route.path}
                                 component={route.component}
                                 access={route.access}
-                                user={{data: {role: 1}}}
+                                user={user}
                                 key={route}
                                 exact
                             />
@@ -45,11 +42,9 @@ class Router extends React.Component {
     }
 }
 
-// const mapStateToProps = state => ({
-//     user: state.user
-// })
+const mapStateToProps = state => ({
+    user: state.user
+})
 // const mapDispatchToProps = dispatch => bindActionCreators({ tokenAuth }, dispatch);
 
-// export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Router));
-
-export default Router;
+export default withRouter(connect(mapStateToProps, null)(Router));

+ 3 - 2
src/sagas/auth/index.js

@@ -5,6 +5,7 @@ import * as actionTypes from './../../constants/auth'
 import { takeEvery } from 'redux-saga/effects';
 
 export default function* () {
-    takeEvery(actionTypes.SIGN_IN_REQUEST, signIn)
-    takeEvery(actionTypes.SIGN_UP_REQUEST, signUp)
+    console.log('takeEvery');
+    yield takeEvery(actionTypes.SIGN_IN_REQUEST, signIn)
+    yield takeEvery(actionTypes.SIGN_UP_REQUEST, signUp)
 }

+ 26 - 2
src/sagas/auth/signIn.js

@@ -1,3 +1,27 @@
-export default function* () {
-    
+import { put, call } from 'redux-saga/effects';
+import axios from 'axios';
+
+import { SIGN_IN_URL } from './../../constants/auth';
+import { signInSuccess, signInFailure } from './../../actions/auth/signIn'
+
+export default function* ({payload}) {
+    console.log('User inside the worker-saga', payload);
+    try {
+        const config = {
+            headers: {
+                "Content-Type": "application/json"
+            }
+        }
+
+        const user = yield call(() =>
+            axios.post(SIGN_IN_URL, payload, config)
+                .then(({ data }) => data)
+        )
+
+
+        yield put(signInSuccess(user));
+    }
+    catch ({ message }) {
+        yield put(signInFailure(message));
+    }
 }

+ 1 - 3
src/sagas/index.js

@@ -2,7 +2,5 @@ import { fork } from "redux-saga/effects";
 import auth from './auth'
 
 export default function*() {
-    yield [
-        fork(auth)
-    ]
+    yield fork(auth)
 }

+ 3 - 2
src/state/index.js

@@ -16,6 +16,7 @@ const store = createStore(
     initialState,
     applyMiddleware(sagaMiddleware, logger)
 );
-export default store;
 
-sagaMiddleware.run(sagas);
+sagaMiddleware.run(sagas);
+
+export default store;

+ 2 - 2
src/styles/base/_theme.scss

@@ -8,7 +8,7 @@
     &-mist {
         background: $color-mist !important;
     }
-    &-autumn-foliage {
+    &-af {
         background: $color-autumn-foliage !important;
     }
 }
@@ -22,7 +22,7 @@
     &-mist {
         color: $color-mist !important;
     }
-    &-autumn-foliage {
+    &-af {
         color: $color-autumn-foliage !important;
     }
 }

+ 0 - 2
src/styles/base/_typography.scss

@@ -1,7 +1,5 @@
 @import url('https://fonts.googleapis.com/css?family=Cormorant+Infant:400,700|Open+Sans+Condensed:300,700|Poiret+One');
 
-
-
 .font {
     &-ci {
         font-family: 'Cormorant Infant', serif !important;