- {label}
+
+ {label}
+
{errorText}
)
diff --git a/src/components/common/Submenu.js b/src/components/common/Submenu.js
new file mode 100644
index 0000000..466ed9b
--- /dev/null
+++ b/src/components/common/Submenu.js
@@ -0,0 +1,24 @@
+import React, { Component } from 'react'
+import { NavLink } from 'react-router-dom'
+
+class Submenu extends Component {
+ render() {
+ return (
+
+ {this.props.links.map(this.renderSubmenuItem.bind(this))}
+
+ )
+ }
+
+ renderSubmenuItem(item, index) {
+ const { to, title } = item
+
+ return (
+
+ {title}
+
+ )
+ }
+}
+
+export default Submenu
diff --git a/src/components/routes/Admin.js b/src/components/routes/Admin.js
index 952248e..7a5ed7c 100644
--- a/src/components/routes/Admin.js
+++ b/src/components/routes/Admin.js
@@ -1,4 +1,7 @@
import React, { Component } from 'react'
+import Submenu from '../common/Submenu'
+import { Route } from 'react-router-dom'
+import People from './People'
class Admin extends Component {
static propTypes = {
@@ -6,9 +9,22 @@ class Admin extends Component {
};
render() {
+ const links = [{
+ to: '/admin/people',
+ title: 'People',
+ }, {
+ to: '/admin/stats',
+ title: 'Stats',
+ }, {
+ to: '/admin/whatever',
+ title: 'Whatever',
+ }]
+
return (
Admin Page
+
+
)
}
diff --git a/src/components/routes/Auth.js b/src/components/routes/Auth.js
index a183ff9..ec4898e 100644
--- a/src/components/routes/Auth.js
+++ b/src/components/routes/Auth.js
@@ -1,7 +1,7 @@
import React, { Component } from 'react'
import {Route, NavLink} from 'react-router-dom'
import {connect} from 'react-redux'
-import {signUp} from '../../ducks/auth'
+import {signUp, signIn} from '../../ducks/auth'
import SignIn from '../auth/SignIn'
import SignUp from '../auth/SignUp'
@@ -22,8 +22,8 @@ class AuthPage extends Component {
)
}
- handleSignIn = (values) => console.log('---', 'sign in', values)
+ handleSignIn = ({email, password}) => this.props.signIn(email, password)
handleSignUp = ({email, password}) => this.props.signUp(email, password)
}
-export default connect(null, { signUp })(AuthPage)
\ No newline at end of file
+export default connect(null, { signUp, signIn })(AuthPage)
\ No newline at end of file
diff --git a/src/components/routes/People.js b/src/components/routes/People.js
new file mode 100644
index 0000000..0e523ed
--- /dev/null
+++ b/src/components/routes/People.js
@@ -0,0 +1,68 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import MemberForm from '../admin/MemberForm'
+import { addMember, membersSelector } from '../../ducks/people'
+
+class People extends Component {
+ get members() {
+ return this.props.members
+ }
+
+ get hasMembers() {
+ return this.members.length > 0
+ }
+
+ curryAddMember() {
+ return values => {
+ const { firstName, lastName, email } = values
+
+ this.props.addMember(firstName, lastName, email)
+ }
+ }
+
+ render() {
+ return (
+
+
People
+
+ {this.renderMembers()}
+ {this.renderAddForm()}
+
+
+ )
+ }
+
+ renderMembers() {
+ if (!this.hasMembers) {
+ return
There is no members yet.
+ }
+
+ return (
+
+ {this.members.map(this.renderMember.bind(this))}
+
+ )
+ }
+
+ renderMember(item) {
+ const { firstName, lastName, email } = item
+
+ return (
+
+ {firstName} {lastName} {email}
+
+ )
+ }
+
+ renderAddForm() {
+ return
+ }
+}
+
+export default connect(state => {
+ return {
+ members: membersSelector(state)
+ }
+}, {
+ addMember,
+})(People)
diff --git a/src/config.js b/src/config.js
index 2782a0b..6ce5a80 100644
--- a/src/config.js
+++ b/src/config.js
@@ -1,12 +1,12 @@
import firebase from 'firebase'
-export const appName = 'advreact-1610'
+export const appName = 'advreact-1610-9cb0c'
firebase.initializeApp({
- apiKey: "AIzaSyB31xpTtp4Jln_hb2kAbE4PGf6Mi8EgLyA",
+ apiKey: "AIzaSyBNaOQkLL75ZGoeaNtqbe63wEjjWLzLOPY",
authDomain: `${appName}.firebaseapp.com`,
databaseURL: `https://${appName}.firebaseio.com`,
projectId: appName,
storageBucket: "",
- messagingSenderId: "397157634637"
+ messagingSenderId: "266748171955"
})
\ No newline at end of file
diff --git a/src/ducks/auth.js b/src/ducks/auth.js
index 1ab7d1b..5ca5265 100644
--- a/src/ducks/auth.js
+++ b/src/ducks/auth.js
@@ -13,7 +13,10 @@ export const SIGN_UP_START = `${prefix}/SIGN_UP_START`
export const SIGN_UP_SUCCESS = `${prefix}/SIGN_UP_SUCCESS`
export const SIGN_UP_ERROR = `${prefix}/SIGN_UP_ERROR`
+export const SIGN_IN_START = `${prefix}/SIGN_IN_START`
export const SIGN_IN_SUCCESS = `${prefix}/SIGN_IN_SUCCESS`
+export const SIGN_IN_ERROR = `${prefix}/SIGN_IN_ERROR`
+
/**
* Reducer
@@ -29,6 +32,7 @@ export default function reducer(state = new ReducerRecord(), action) {
switch (type) {
case SIGN_UP_START:
+ case SIGN_IN_START:
return state.set('loading', true)
case SIGN_UP_SUCCESS:
@@ -37,6 +41,12 @@ export default function reducer(state = new ReducerRecord(), action) {
.set('user', payload.user)
.set('loading', false)
+ case SIGN_UP_ERROR:
+ case SIGN_IN_ERROR:
+ return state
+ .set('error', payload.error)
+ .set('loading', false)
+
default:
return state
}
@@ -70,6 +80,24 @@ export function signUp(email, password) {
}
}
+export function signIn(email, password) {
+ return (dispatch) => {
+ dispatch({
+ type: SIGN_IN_START
+ })
+
+ firebase.auth().signInWithEmailAndPassword(email, password)
+ .then(user => dispatch({
+ type: SIGN_IN_SUCCESS,
+ payload: { user }
+ }))
+ .catch(error => dispatch({
+ type: SIGN_IN_ERROR,
+ payload: { error }
+ }))
+ }
+}
+
firebase.auth().onAuthStateChanged(user => {
if (!user) return
diff --git a/src/ducks/people.js b/src/ducks/people.js
new file mode 100644
index 0000000..d36813a
--- /dev/null
+++ b/src/ducks/people.js
@@ -0,0 +1,47 @@
+import {Record} from 'immutable'
+import {reset} from 'redux-form';
+import {appName} from '../config'
+import {createSelector} from 'reselect'
+
+export const moduleName = 'people'
+
+const prefix = `${appName}/${moduleName}`
+
+/* constants */
+export const ADD_MEMBER = `${prefix}/ADD_MEMBER`
+
+/* reducer */
+const ReducerRecord = Record({
+ items: [],
+})
+
+export default function reducer(state = new ReducerRecord(), action) {
+ const { type, payload } = action
+
+ switch (type) {
+ case ADD_MEMBER:
+ return state
+ .set('items', state.get('items').concat(payload.user))
+
+ default:
+ return state
+ }
+}
+
+/* action creators */
+export function addMember(firstName, lastName, email) {
+ const user = {firstName, lastName, email}
+
+ return dispatch => {
+ dispatch({
+ type: ADD_MEMBER,
+ payload: {user},
+ })
+
+ dispatch(reset('member'))
+ }
+}
+
+/* selectors */
+export const stateSelector = state => state[moduleName]
+export const membersSelector = createSelector(stateSelector, state => state.items)
diff --git a/src/redux/reducer.js b/src/redux/reducer.js
index 34143fe..6f671f0 100644
--- a/src/redux/reducer.js
+++ b/src/redux/reducer.js
@@ -2,8 +2,10 @@ import {combineReducers} from 'redux'
import {routerReducer as router} from 'react-router-redux'
import {reducer as form} from 'redux-form'
import authReducer, {moduleName as authModule} from '../ducks/auth'
+import peopleReducer, {moduleName as peopleModule} from '../ducks/people'
export default combineReducers({
router, form,
- [authModule]: authReducer
-})
\ No newline at end of file
+ [authModule]: authReducer,
+ [peopleModule]: peopleReducer,
+})