From d8b4d506fbd4fa32f0bc744966975fd06cddf511 Mon Sep 17 00:00:00 2001 From: veresku Date: Sat, 9 Dec 2017 21:10:15 +0100 Subject: [PATCH] done --- admin-panel/package.json | 1 + admin-panel/src/components/auth/SignInForm.js | 10 +++- admin-panel/src/components/routes/Admin.js | 17 +++++- .../src/components/routes/auth/index.js | 15 ++++- .../src/components/user/NewUserForm.js | 50 ++++++++++++++++ admin-panel/src/config.js | 16 +++--- admin-panel/src/ducks/auth.js | 11 ++++ admin-panel/src/ducks/user.js | 57 +++++++++++++++++++ admin-panel/src/redux/index.js | 35 ++++++++---- 9 files changed, 188 insertions(+), 24 deletions(-) create mode 100644 admin-panel/src/components/user/NewUserForm.js create mode 100644 admin-panel/src/ducks/user.js diff --git a/admin-panel/package.json b/admin-panel/package.json index 5fbeba9..d40efcb 100644 --- a/admin-panel/package.json +++ b/admin-panel/package.json @@ -8,6 +8,7 @@ "history": "^4.7.2", "immutable": "^3.8.2", "logger": "^0.0.1", + "prop-types": "^15.6.0", "react": "^16.2.0", "react-dom": "^16.2.0", "react-redux": "^5.0.6", diff --git a/admin-panel/src/components/auth/SignInForm.js b/admin-panel/src/components/auth/SignInForm.js index 3033ef6..0cd7b78 100644 --- a/admin-panel/src/components/auth/SignInForm.js +++ b/admin-panel/src/components/auth/SignInForm.js @@ -1,12 +1,16 @@ import React, { Component } from 'react' import {reduxForm, Field} from 'redux-form' +import PropTypes from "prop-types" class SignInForm extends Component { static propTypes = { - + authError: PropTypes.object, + authLoading: PropTypes.bool.isRequired }; render() { + const {authError, authLoading} = this.props; + return (

Sign In

@@ -17,6 +21,10 @@ class SignInForm extends Component {
password:
+ + {authLoading &&

Loading...

} + {authError &&

{authError.message}

} + diff --git a/admin-panel/src/components/routes/Admin.js b/admin-panel/src/components/routes/Admin.js index 952248e..2b19d74 100644 --- a/admin-panel/src/components/routes/Admin.js +++ b/admin-panel/src/components/routes/Admin.js @@ -1,4 +1,9 @@ -import React, { Component } from 'react' +import React, { Component } from 'react'; +import {Route, NavLink} from 'react-router-dom'; +import {connect} from 'react-redux'; + +import {addUser} from '../../ducks/user'; +import NewUserForm from '../../components/user/NewUserForm'; class Admin extends Component { static propTypes = { @@ -9,9 +14,17 @@ class Admin extends Component { return (

Admin Page

+
    +
  • Create user
  • +
+ } />
) } + + onAddNewUser = ({firstName, lastName, email}) => { + this.props.addUser(firstName, lastName, email); + } } -export default Admin \ No newline at end of file +export default connect(null, {addUser})(Admin); \ No newline at end of file diff --git a/admin-panel/src/components/routes/auth/index.js b/admin-panel/src/components/routes/auth/index.js index 91c9bab..f75ee3c 100644 --- a/admin-panel/src/components/routes/auth/index.js +++ b/admin-panel/src/components/routes/auth/index.js @@ -1,16 +1,22 @@ import React, { Component } from 'react' +import PropTypes from 'prop-types' import {Route, NavLink} from 'react-router-dom' import {connect} from 'react-redux' + import {signIn, signUp} from '../../../ducks/auth' +import {errorSelector, loadingSelector} from '../../../ducks/auth' import SignInForm from '../../auth/SignInForm' import SignUpForm from '../../auth/SignUpForm' class Auth extends Component { static propTypes = { - + authError: PropTypes.object, + authLoading: PropTypes.bool.isRequired }; render() { + const {authLoading, authError} = this.props; + return (

Auth page

@@ -18,7 +24,7 @@ class Auth extends Component {
  • Sign In
  • Sign Up
  • - } /> + } /> } />
    ) @@ -29,4 +35,7 @@ class Auth extends Component { } -export default connect(null, { signIn, signUp })(Auth) \ No newline at end of file +export default connect(state => ({ + authError: errorSelector(state), + authLoading: loadingSelector(state) +}), { signIn, signUp })(Auth) \ No newline at end of file diff --git a/admin-panel/src/components/user/NewUserForm.js b/admin-panel/src/components/user/NewUserForm.js new file mode 100644 index 0000000..605022d --- /dev/null +++ b/admin-panel/src/components/user/NewUserForm.js @@ -0,0 +1,50 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import {reduxForm, Field} from 'redux-form'; +import validator from 'email-validator'; + +import ErrorField from '../common/ErrorField'; + +class NewUserForm extends Component { + static propTypes = { + handleSubmit: PropTypes.func.isRequired + }; + + render() { + return ( +
    +

    Add user

    +
    +
    + First name: +
    +
    + Last name: +
    +
    + Email: +
    + +
    + +
    + ) + } +} + +const validate = ({ firstName, lastName, email }) => { + const errors = {}; + + if (!email) errors.email = 'Email is a required field'; + if (email && !validator.validate(email)) errors.email = 'Incorrect email format'; + + if (!firstName) errors.firstName = 'First name is a required field'; + if (!lastName) errors.lastName = 'Last name is a required field'; + + return errors; +} + +export default reduxForm({ + form: 'new-user', + validate +})(NewUserForm) \ No newline at end of file diff --git a/admin-panel/src/config.js b/admin-panel/src/config.js index 65bba00..202b263 100644 --- a/admin-panel/src/config.js +++ b/admin-panel/src/config.js @@ -1,14 +1,14 @@ -import firebase from 'firebase' +import firebase from 'firebase'; -export const appName = 'advreact-04-12' +export const appName = 'adv-react-8c4fb'; const config = { - apiKey: "AIzaSyCmDWlgYIhtEr1pWjgKYds3iXKWBl9wbjE", + apiKey: "AIzaSyCPlodrXJgpCXqDWklsFc_V5vHGiD6G2Uc", authDomain: `${appName}.firebaseapp.com`, databaseURL: `https://${appName}.firebaseio.com`, - projectId: appName, - storageBucket: "", - messagingSenderId: "95255462276" -} + projectId: {appName}, + storageBucket: "adv-react-8c4fb.appspot.com", + messagingSenderId: "47356959167" +}; -firebase.initializeApp(config) \ No newline at end of file +firebase.initializeApp(config); \ No newline at end of file diff --git a/admin-panel/src/ducks/auth.js b/admin-panel/src/ducks/auth.js index f031871..53346a6 100644 --- a/admin-panel/src/ducks/auth.js +++ b/admin-panel/src/ducks/auth.js @@ -10,6 +10,7 @@ const prefix = `${appName}/${moduleName}` export const SIGN_IN_START = `${prefix}/SIGN_IN_START` export const SIGN_IN_SUCCESS = `${prefix}/SIGN_IN_SUCCESS` +export const SIGN_IN_FAILURE = `${prefix}/SIGN_IN_FAILURE` export const SIGN_UP_START = `${prefix}/SIGN_UP_START` export const SIGN_UP_SUCCESS = `${prefix}/SIGN_UP_SUCCESS` @@ -35,6 +36,10 @@ export default function reducer(state = new ReducerRecord(), action) { return state .set('loading', false) .set('user', payload.user) + case SIGN_IN_FAILURE: + return state + .set('loading', false) + .set('error', payload.error) default: return state } @@ -45,6 +50,8 @@ export default function reducer(state = new ReducerRecord(), action) { * */ export const userSelector = state => state[moduleName].user +export const errorSelector = state => state[moduleName].error +export const loadingSelector = state => state[moduleName].loading /** * Action Creators @@ -61,6 +68,10 @@ export function signIn(email, password) { type: SIGN_IN_SUCCESS, payload: { user } })) + .catch(error => dispatch({ + type: SIGN_IN_FAILURE, + payload: { error } + })) } } diff --git a/admin-panel/src/ducks/user.js b/admin-panel/src/ducks/user.js new file mode 100644 index 0000000..966e694 --- /dev/null +++ b/admin-panel/src/ducks/user.js @@ -0,0 +1,57 @@ +import {appName} from '../config'; +import {Record} from 'immutable'; +import firebase from 'firebase'; + +/** + * Constants + * */ +export const moduleName = 'user'; +const prefix = `${appName}/${moduleName}`; + +export const ADD_USER_START = `${prefix}/ADD_USER_START`; +export const ADD_USER_SUCCESS = `${prefix}/ADD_USER_SUCCESS`; + +/** + * Reducer + * */ +export const ReducerRecord = Record({ + user: null, + loading: false, + error: null +}) + +export default function reducer(state = new ReducerRecord(), action) { + const {type, payload} = action + + switch (type) { + case ADD_USER_START: + return state.set('loading', true) + + case ADD_USER_SUCCESS: + return state + .set('loading', false) + .set('user', payload.user) + default: + return state + } +} + +/** + * Selectors + * */ + +export const userSelector = state => state[moduleName].user + +/** + * Action Creators + * */ + +export function addUser(firstName, lastName, email) { + return (dispatch) => { + dispatch({ + type: ADD_USER_START + }) + + console.log('addUser', firstName, lastName, email); + } +} \ No newline at end of file diff --git a/admin-panel/src/redux/index.js b/admin-panel/src/redux/index.js index 1a37261..768e08c 100644 --- a/admin-panel/src/redux/index.js +++ b/admin-panel/src/redux/index.js @@ -1,13 +1,28 @@ -import {createStore, applyMiddleware} from 'redux' -import logger from 'redux-logger' -import {routerMiddleware} from 'react-router-redux' -import thunk from 'redux-thunk' -import reducer from './reducer' -import history from '../history' +import {createStore, applyMiddleware, compose} from 'redux'; +import thunk from 'redux-thunk'; +import logger from 'redux-logger'; +import {routerMiddleware} from 'react-router-redux'; -const store = createStore(reducer, applyMiddleware(thunk, routerMiddleware(history), logger)) +import reducer from './reducer'; +import history from '../history'; -//dev only -window.store = store +// If Redux DevTools Extension is installed use it, otherwise use Redux compose +/* eslint-disable no-underscore-dangle */ +const composeEnhancers = + process.env.NODE_ENV !== 'production' && + typeof window === 'object' && + window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? + window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : compose; +/* eslint-enable */ -export default store \ No newline at end of file +const enhancer = composeEnhancers( + applyMiddleware(thunk, routerMiddleware(history), logger) +); + +const store = createStore(reducer, enhancer); + +if (process.env.NODE_ENV !== 'production') { + window.store = store; +} + +export default store;