Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"redux": "^4.0.1",
"redux-form": "^8.1.0",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0"
"redux-thunk": "^2.3.0",
"reselect": "^4.0.0"
},
"scripts": {
"start": "react-scripts start",
Expand Down
21 changes: 17 additions & 4 deletions admin/src/App.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React, { Component } from 'react'
import { Route, NavLink } from 'react-router-dom'
import { Route, NavLink, Redirect, Switch } from 'react-router-dom'
import AuthPage from './components/routes/auth'
import AdminPage from './components/routes/admin'
import PeoplePage from './components/routes/people'
import {connect} from 'react-redux'
import {userSelector} from './ducks/auth'

class App extends Component {
static propTypes = {
Expand All @@ -19,15 +22,25 @@ class App extends Component {
<li>
<NavLink to="/admin" activeStyle={{ color: 'red'}}>admin</NavLink>
</li>
<li>
<NavLink to="/people" activeStyle={{ color: 'red'}}>people</NavLink>
</li>
</ul>
</nav>
<section>
<Route path="/auth" component={AuthPage}/>
<Route path="/admin" component={AdminPage}/>
<Switch>
<Route path="/auth" component={AuthPage}/>
{!this.props.user && <Redirect from="/admin" to={'/auth'} />}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я б делал эту проверку в защищенном роуте, чтоб не разносить логику по разным частям

<Route path="/admin" component={AdminPage}/>
<Route path="/people" component={PeoplePage}/>
</Switch>
</section>
</div>
)
}
}
const mapStateToProps = (state) => ({
user: userSelector(state)
})

export default App
export default connect(mapStateToProps)(App)
38 changes: 38 additions & 0 deletions admin/src/components/people/add-person-form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, {Component} from 'react'
import {reduxForm, Field} from 'redux-form'
import validator from 'email-validator'
import ErrorField from "../common/error-field";

class AddPersonForm extends Component {
static propTypes = {}

render() {
return (
<div>
<h3>Add Person</h3>
<form onSubmit={this.props.handleSubmit}>
<Field name="firstName" component={ErrorField} label="First Name"/>
<Field name="lastName" component={ErrorField} label="Last Name"/>
<Field name="email" component={ErrorField} label="Email"/>
<button type="submit">Add Person</button>
</form>
</div>
)
}
}

const validate = ({firstName, lastName, email}) => {
const errors = {}
if (!email) errors.email = 'email is a required field'
else if (!validator.validate(email)) errors.email = 'invalid email'

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: 'add-person',
validate
})(AddPersonForm)
20 changes: 20 additions & 0 deletions admin/src/components/people/people-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react'
import Person from './person'

const PeopleList = ({ people }) => {
if(people.length === 0) return null
return (
<div>
<h2>People</h2>
<ul>
{people.map(({firstName, lastName, email, id}) => (
<li key={id}>
<Person firstName={firstName} lastName={lastName} email={email}/>
</li>))}
</ul>
</div>
)
}


export default PeopleList
10 changes: 10 additions & 0 deletions admin/src/components/people/person.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react'

const Person = ({firstName, lastName, email}) => (
<div>
<div>{`${firstName} ${lastName}`}</div>
<div>{email}</div>
</div>
)

export default Person
25 changes: 25 additions & 0 deletions admin/src/components/routes/people/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import AddForm from '../../people/add-person-form'
import People from '../../../components/people/people-list'
import { addPerson, peopleListSelector } from '../../../ducks/people'

class PeoplePage extends Component {
render() {
return (
<div>
<h1>People Page</h1>
<AddForm onSubmit={this.handleAddPerson} />
<People people={this.props.people} />
</div>
)
}

handleAddPerson = (person) => this.props.addPerson(person)
}

export default connect((state) => {
return {
people: peopleListSelector(state)
}
}, { addPerson })(PeoplePage)
38 changes: 26 additions & 12 deletions admin/src/ducks/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export const SIGN_IN_SUCCESS = `${prefix}/SIGN_IN_SUCCESS`
export const SIGN_UP_START = `${prefix}/SIGN_UP_START`
export const SIGN_UP_SUCCESS = `${prefix}/SIGN_UP_SUCCESS`

export const AUTH_USER = `${prefix}/AUTH_USER`

/**
* Reducer
* */
Expand All @@ -25,8 +27,7 @@ export default function reducer(state = new ReducerRecord(), action) {
const {type, payload} = action

switch (type) {
case SIGN_IN_SUCCESS:
case SIGN_UP_SUCCESS:
case AUTH_USER:
return state.set('user', payload.user)
default:
return state
Expand All @@ -37,6 +38,8 @@ export default function reducer(state = new ReducerRecord(), action) {
* Selectors
* */

export const userSelector = (state) => state.auth.user

/**
* Action Creators
* */
Expand All @@ -50,9 +53,9 @@ export function signIn(email, password) {
const user = await firebase.auth().signInWithEmailAndPassword(email, password)

dispatch({
type: SIGN_IN_SUCCESS,
payload: { user }
type: SIGN_IN_SUCCESS
})
dispatch(authUser(user))
}
}

Expand All @@ -65,16 +68,27 @@ export function signUp(email, password) {
const user = await firebase.auth().createUserWithEmailAndPassword(email, password)

dispatch({
type: SIGN_UP_SUCCESS,
payload: { user }
type: SIGN_UP_SUCCESS
})
dispatch(authUser(user))
}
}

/**
* Init
**/
export function authUser(user) {
return (dispatch) => {
dispatch({
type: AUTH_USER,
payload: { user }
})
}
}

firebase.auth().onAuthStateChanged((user) => {
console.log('--- user', user)
})
export function verifyAuth() {
return (dispatch) => {
firebase.auth().onAuthStateChanged(user => {
if (user) {
dispatch(authUser(user))
}
})
}
}
71 changes: 71 additions & 0 deletions admin/src/ducks/people.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Record, OrderedMap } from 'immutable'
import { appName } from '../config'
import { createSelector } from 'reselect'
import {reset} from 'redux-form'

/**
* Constants
* */
export const moduleName = 'auth'
const prefix = `${appName}/${moduleName}`

export const ADD_PERSON = `${prefix}/ADD_PERSON`

/**
* Reducer
* */
export const PersonRecord = Record({
id: null,
firstName: null,
lastName: null,
email: null
})


const ReducerRecord = Record({
entities: new OrderedMap({}),
})

export default function reducer(state = new ReducerRecord(), action) {
const { type, payload } = action

switch (type) {
case ADD_PERSON:
return state.setIn(
['entities', randomId],
new PersonRecord({
...payload.person,
id: randomId
})
)
default:
return state
}
}

/**
* Selectors
* */

const peopleMapSelector = (state) => state.people.entities

export const peopleListSelector = createSelector(
peopleMapSelector,
(peopleMap) => peopleMap.valueSeq().toArray()
);

/**
* Action Creators
* */

export const addPerson = (person) => (dispatch) => {
dispatch({
type: ADD_PERSON,
payload: { person }
})
dispatch(reset('add-person'))
}

function randomId() {
return (Date.now() + Math.random()).toString()
}
5 changes: 4 additions & 1 deletion admin/src/redux/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import logger from 'redux-logger'
import thunk from 'redux-thunk'
import reducer from './reducer'
import history from '../history'
import { verifyAuth } from "../ducks/auth";

const enhancer = applyMiddleware(thunk, routerMiddleware(history), logger)
const store = createStore(reducer, enhancer)

export default createStore(reducer, enhancer)
store.dispatch(verifyAuth())
export default store
4 changes: 3 additions & 1 deletion admin/src/redux/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { combineReducers } from 'redux'
import {connectRouter} from 'connected-react-router'
import {reducer as form} from 'redux-form'
import authReducer from '../ducks/auth'
import peopleReducer from '../ducks/people'
import history from '../history'

export default combineReducers({
auth: authReducer,
router: connectRouter(history),
form
form,
people: peopleReducer
})
Loading