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 (
)
}
+
+ 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 (
+
+ )
+ }
+}
+
+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;