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
20 changes: 20 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<style>
nav.submenu {
background: #eee;
padding: .5rem;
}
nav.submenu a {
margin-right: 1rem;
color: #333;
text-decoration: none;
}
nav.submenu a.active {
font-weight: bold;
}
.error-field {
margin-bottom: 1rem;
}
.error {
color: #c00;
}
</style>
</head>
<body>
<noscript>
Expand Down
50 changes: 45 additions & 5 deletions src/components/App.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,69 @@
import React, { Component } from 'react'
import {Route, NavLink} from 'react-router-dom'
import {connect} from 'react-redux'
import firebase from 'firebase'
import ProtectedRoute from './common/ProtectedRoute'
import AdminPage from './routes/Admin'
import AuthPage from './routes/Auth'
import PersonPage from './routes/PersonPage'
import Submenu from './common/Submenu'
import {userAuthorized} from '../ducks/auth'
import history from '../history'

class App extends Component {
static propTypes = {

};

componentDidMount() {
history.push(this.props.authorized ? '/people' : '/auth/signin')
Copy link
Owner

Choose a reason for hiding this comment

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

а если статус может(и будет) позже меняться. Стоило делать в утке

}

render() {
return (
<div>
<h1>Hello world</h1>
<ul>
<li><NavLink to='/admin' activeStyle = {{color: 'red'}}>admin</NavLink></li>
<li><NavLink to='/people' activeStyle = {{color: 'red'}}>people</NavLink></li>
</ul>
{this.renderSubmenu()}
<ProtectedRoute path = '/admin' component = {AdminPage}/>
<ProtectedRoute path = '/people' component={PersonPage}/>
<Route path = '/auth' component = {AuthPage}/>
</div>
)
}

renderSubmenu() {
const links = []

if (this.props.authorized) {
links.push({
to: '/admin',
title: 'Admin',
}, {
to: '/people',
title: 'People',
}, {
to: '/logout',
title: 'Logout',
})
}
else {
links.push({
to: '/auth/signin',
title: 'Sign in',
}, {
to: '/auth/signup',
title: 'Sign up',
})
}

const props = {
links,
}

return <Submenu {...props} />
}
}

export default App
export default connect(state => ({
authorized: userAuthorized(state)
}), null, null, { pure: false })(App)
Copy link
Owner

Choose a reason for hiding this comment

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

Здесь pure: false не нужен

22 changes: 21 additions & 1 deletion src/components/auth/SignIn.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ class SignIn extends Component {

};

shouldComponentUpdate(nextProps) {
Copy link
Owner

Choose a reason for hiding this comment

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

вот этого совсем не понял

if (nextProps.shouldReset) {
this.props.reset()
return false
}

return true
}

render() {
return (
<div>
Expand All @@ -20,12 +29,23 @@ class SignIn extends Component {
<div>
<input type = 'submit'/>
</div>
{this.renderError()}
</form>
</div>
)
}

renderError() {
const { signInError } = this.props

if (!signInError) {
return null
}

return <p className="error">{signInError}</p>
}
}

export default reduxForm({
form: 'auth'
})(SignIn)
})(SignIn)
4 changes: 2 additions & 2 deletions src/components/common/ErrorField.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ function ErrorField(props) {
const {input, type, meta: {error, touched}} = props
const errorText = touched && error && <div style={{color: 'red'}}>{error}</div>
return (
<div>
<label>{input.name}</label>
<div className="error-field">
<label>{input.name}<br/></label>
<input {...input} type={type}/>
{errorText}
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/components/common/ProtectedRoute.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Component } from 'react'
import {Route} from 'react-router-dom'
import {connect} from 'react-redux'
import {userSelector} from '../../ducks/auth'
import {userAuthorized} from '../../ducks/auth'

class ProtectedRoute extends Component {
static propTypes = {
Expand All @@ -21,5 +21,5 @@ class ProtectedRoute extends Component {
}

export default connect(state => ({
authorized: !!userSelector(state)
authorized: userAuthorized(state)
}), null, null, { pure: false })(ProtectedRoute)
30 changes: 30 additions & 0 deletions src/components/common/Submenu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { Component } from 'react'
import { NavLink } from 'react-router-dom'

class Submenu extends Component {
render() {
return (
<nav className="submenu">
{this.props.links.map(this.renderSubmenuItem.bind(this))}
</nav>
)
}

renderSubmenuItem(item, index) {
const { to, title } = item

const props = {
key: index,
activeClassName: 'active',
to,
}

return (
<NavLink {...props}>
{title}
</NavLink>
)
}
}

export default Submenu
23 changes: 17 additions & 6 deletions src/components/routes/Auth.js
Original file line number Diff line number Diff line change
@@ -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, errorMessage, userAuthorized} from '../../ducks/auth'
import SignIn from '../auth/SignIn'
import SignUp from '../auth/SignUp'

Expand All @@ -14,16 +14,27 @@ class AuthPage extends Component {
return (
<div>
<h2>Auth page</h2>
<NavLink to = '/auth/signin' activeStyle = {{color: 'red'}}>sign in</NavLink>
<NavLink to = '/auth/signup' activeStyle = {{color: 'red'}}>sign up</NavLink>
<Route path = '/auth/signin' render = {() => <SignIn onSubmit = {this.handleSignIn}/>}/>
<Route path = '/auth/signin' render = {this.renderSignIn.bind(this)}/>
<Route path = '/auth/signup' render = {() => <SignUp onSubmit = {this.handleSignUp}/>}/>
</div>
)
}

handleSignIn = (values) => console.log('---', 'sign in', values)
renderSignIn() {
const props = {
onSubmit: this.handleSignIn,
signInError: this.props.error,
shouldReset: this.props.authorized,
}

return <SignIn {...props} />
}

handleSignIn = ({email, password}) => this.props.signIn(email, password)
handleSignUp = ({email, password}) => this.props.signUp(email, password)
}

export default connect(null, { signUp })(AuthPage)
export default connect(state => ({
error: errorMessage(state),
authorized: userAuthorized(state),
}), { signIn, signUp, errorMessage })(AuthPage)
6 changes: 3 additions & 3 deletions src/config.js
Original file line number Diff line number Diff line change
@@ -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"
})
55 changes: 52 additions & 3 deletions src/ducks/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {Record} from 'immutable'
import firebase from 'firebase'
import {createSelector} from 'reselect'
import {call, put, all, take} from 'redux-saga/effects'
import history from '../history'

/**
* Constants
Expand All @@ -14,7 +15,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
Expand All @@ -30,14 +34,23 @@ export default function reducer(state = new ReducerRecord(), action) {

switch (type) {
case SIGN_UP_START:
return state.set('loading', true)
case SIGN_IN_START:
return state
.set('loading', true)
.set('error', null)

case SIGN_UP_SUCCESS:
case SIGN_IN_SUCCESS:
return state
.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
}
Expand All @@ -49,6 +62,8 @@ export default function reducer(state = new ReducerRecord(), action) {

export const stateSelector = state => state[moduleName]
export const userSelector = createSelector(stateSelector, state => state.user)
export const userAuthorized = createSelector(stateSelector, state => !!state.user)
export const errorMessage = createSelector(stateSelector, state => state.error && state.error.message || '')

/**
* Action Creators
Expand All @@ -60,6 +75,13 @@ export function signUp(email, password) {
}
}

export function signIn(email, password) {
return {
type: SIGN_IN_START,
payload: { email, password }
}
}

firebase.auth().onAuthStateChanged(user => {
if (!user) return

Expand Down Expand Up @@ -96,8 +118,35 @@ export function * signUpSaga() {
}
}

export function * signInSaga() {
const auth = firebase.auth()

while (true) {
const action = yield take(SIGN_IN_START)
const { email, password } = action.payload

try {
const user = yield call([auth, auth.signInWithEmailAndPassword], email, password)

yield put({
type: SIGN_IN_SUCCESS,
payload: {user},
})

yield call([history, history.push], '/people')
Copy link
Owner

Choose a reason for hiding this comment

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

возьми push как AC из react-router-redux, сделай put

}
catch (error) {
yield put({
type: SIGN_IN_ERROR,
payload: {error},
})
}
}
}

export function * saga() {
yield all([
signUpSaga()
signUpSaga(),
signInSaga(),
])
}
}
Loading