diff --git a/README.md b/README.md index e63d3b7..ef1fcad 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,4 @@ ##HT2.1 Реализовать логику signIn ##HT2.2 покрыть тестами auth логику -##HT2.3 при успешной записи человека в стор - чистить форму в /people \ No newline at end of file +##HT2.3 при успешной записи человека в стор - чистить форму в /people diff --git a/src/components/admin/RegisteredUserForm.js b/src/components/admin/RegisteredUserForm.js new file mode 100644 index 0000000..a3c893c --- /dev/null +++ b/src/components/admin/RegisteredUserForm.js @@ -0,0 +1,55 @@ +import React, { Component } from 'react' +import {reduxForm, Field,reset} from 'redux-form' +import emailValidator from 'email-validator' +import ErrorField from '../common/ErrorField' + +class RegisteredUserForm extends Component { + render() { + const {handleSubmit} = this.props + return ( +
+

Add user form

+
+ + + + +
+ +
+ +
+ ) + } +} +const validateName = (param,label,errors)=>{ + + if (!param) errors[label] = `${label} is required` + else if (/^[a-zA-Zа-яА-ЯёЁ]$/.test(param)) errors[label] = `invalid ${label}` +} + +const validate = ({firstName,lastName, email}) => { + //debugger + let errors = {} + + if (!email) errors.email = 'email is required' + else if (!emailValidator.validate(email)) errors.email = 'invalid email' + + validateName(lastName,'lastName',errors) + validateName(firstName,'firstName',errors) + return errors +} + + +const afterSubmit = (result, dispatch) =>{ + console.log('afterSubmit') + return dispatch(reset('RegisteredUserForm')); +} + + +export default reduxForm({ + form: 'RegisteredUserForm', + onSubmitSuccess: afterSubmit, + validate +})(RegisteredUserForm) + diff --git a/src/components/admin/UserList.js b/src/components/admin/UserList.js new file mode 100644 index 0000000..d320ee6 --- /dev/null +++ b/src/components/admin/UserList.js @@ -0,0 +1,19 @@ +import React from 'react' +import {connect} from 'react-redux' +import {moduleName} from '../../ducks/people' + + +const UserList = (props)=>{ + const _list = props.people.map( + user=>
  • {user.firstName} /{user.lastName}/ {user.email}
  • ) + return ( +
    +

    User list

    + {_list} +
    + ) +} + +export default connect(store=>({ + people:store[moduleName].entities +}))(UserList) \ No newline at end of file diff --git a/src/components/auth/SignInForm.js b/src/components/auth/SignInForm.js index a88d77a..a4b40e0 100644 --- a/src/components/auth/SignInForm.js +++ b/src/components/auth/SignInForm.js @@ -1,5 +1,6 @@ import React, { Component } from 'react' import {reduxForm, Field} from 'redux-form' +import validate from './validate' class SignInForm extends Component { static propTypes = { @@ -30,5 +31,6 @@ class SignInForm extends Component { } export default reduxForm({ - form: 'auth' + form: 'auth', + validate })(SignInForm) \ No newline at end of file diff --git a/src/components/auth/SignUpForm.js b/src/components/auth/SignUpForm.js index af7a699..b46ece5 100644 --- a/src/components/auth/SignUpForm.js +++ b/src/components/auth/SignUpForm.js @@ -1,7 +1,9 @@ import React, { Component } from 'react' import {reduxForm, Field} from 'redux-form' -import emailValidator from 'email-validator' + import ErrorField from '../common/ErrorField' +import validate from './validate' + class SignUpForm extends Component { static propTypes = { @@ -25,19 +27,6 @@ class SignUpForm extends Component { } } -const validate = ({email, password}) => { - const errors = {} - - if (!email) errors.email = 'email is required' - else if (!emailValidator.validate(email)) errors.email = 'invalid email' - - if (!password) errors.password = 'password is required' - else if (password.length < 8) errors.password = 'to short' - - return errors -} - - export default reduxForm({ form: 'auth', validate diff --git a/src/components/auth/validate.js b/src/components/auth/validate.js new file mode 100644 index 0000000..4545ebc --- /dev/null +++ b/src/components/auth/validate.js @@ -0,0 +1,12 @@ +import emailValidator from 'email-validator' +export default function({email, password}){ + const errors = {} + + if (!email) errors.email = 'email is required' + else if (!emailValidator.validate(email)) errors.email = 'invalid email' + + if (!password) errors.password = 'password is required' + else if (password.length < 8) errors.password = 'to short' + + return errors +} \ No newline at end of file diff --git a/src/components/common/ErrorField.js b/src/components/common/ErrorField.js index a4879c1..925999d 100644 --- a/src/components/common/ErrorField.js +++ b/src/components/common/ErrorField.js @@ -12,7 +12,4 @@ function ErrorField(props) { ) } -ErrorField.propTypes = { -} - export default ErrorField \ No newline at end of file diff --git a/src/components/routes/AdminPage.js b/src/components/routes/AdminPage.js index 1c4cb84..ddebe01 100644 --- a/src/components/routes/AdminPage.js +++ b/src/components/routes/AdminPage.js @@ -1,17 +1,24 @@ import React, { Component } from 'react' +import {Route, NavLink} from 'react-router-dom' +import {connect} from 'react-redux' +import {addPerson} from '../../ducks/people' +import RegisteredUserForm from '../admin/RegisteredUserForm' +import UserList from '../admin/UserList' class AdminPage extends Component { - static propTypes = { - - }; render() { return (

    Admin Page

    + Registered user + User list + }/> + }/>
    ) } + handleAddUser=({email, lastName,firstName}) => this.props.addPerson({email, lastName,firstName}) } -export default AdminPage \ No newline at end of file +export default connect(null, {addPerson})(AdminPage) \ No newline at end of file diff --git a/src/components/routes/AuthPage.js b/src/components/routes/AuthPage.js index cc9a55f..2b9de1d 100644 --- a/src/components/routes/AuthPage.js +++ b/src/components/routes/AuthPage.js @@ -3,7 +3,7 @@ import SignInForm from '../auth/SignInForm' import SignUpForm from '../auth/SignUpForm' import {Route, NavLink} from 'react-router-dom' import {connect} from 'react-redux' -import {signUp, moduleName} from '../../ducks/auth' +import {signUp,signIn, moduleName} from '../../ducks/auth' import Loader from '../common/Loader' class AuthPage extends Component { @@ -25,10 +25,10 @@ class AuthPage extends Component { ) } - handleSignIn = (values) => console.log('---', values) + handleSignIn = ({email, password}) => this.props.signIn(email, password) handleSignUp = ({email, password}) => this.props.signUp(email, password) } export default connect(state => ({ loading: state[moduleName].loading -}), {signUp})(AuthPage) \ No newline at end of file +}), {signUp,signIn})(AuthPage) \ No newline at end of file diff --git a/src/config.js b/src/config.js index e8d8d78..6a042e8 100644 --- a/src/config.js +++ b/src/config.js @@ -1,13 +1,15 @@ import firebase from 'firebase' -export const appName = "advreact-21-08" +export const appName = 'advreact-277e8'//"advreact-21-08" export const firebaseConfig = { - apiKey: "AIzaSyDjA6CeIHuni5lNm4ML1b-TSxJltsYUO8g", + //apiKey: "AIzaSyDjA6CeIHuni5lNm4ML1b-TSxJltsYUO8g", + apiKey: "AIzaSyCw2LF9saF-AiDhbN464gWERWR35m5qm0Q", authDomain: `${appName}.firebaseapp.com`, databaseURL: `https://${appName}.firebaseio.com`, projectId: appName, storageBucket: `${appName}.appspot.com`, - messagingSenderId: "789814589283" + //messagingSenderId: "789814589283" + messagingSenderId: "313050002315" } firebase.initializeApp(firebaseConfig) \ No newline at end of file diff --git a/src/ducks/auth.js b/src/ducks/auth.js index 6bae0d9..69dcaf5 100644 --- a/src/ducks/auth.js +++ b/src/ducks/auth.js @@ -15,9 +15,14 @@ export const moduleName = 'auth' export const SIGN_UP_REQUEST = `${appName}/${moduleName}/SIGN_UP_REQUEST` export const SIGN_UP_SUCCESS = `${appName}/${moduleName}/SIGN_UP_SUCCESS` export const SIGN_UP_ERROR = `${appName}/${moduleName}/SIGN_UP_ERROR` + export const SIGN_IN_SUCCESS = `${appName}/${moduleName}/SIGN_IN_SUCCESS` +export const SIGN_IN_REQUEST = `${appName}/${moduleName}/SIGN_IN_REQUEST` +export const SIGN_IN_ERROR = `${appName}/${moduleName}/SIGN_IN_ERROR` + export const SIGN_OUT_REQUEST = `${appName}/${moduleName}/SIGN_OUT_REQUEST` export const SIGN_OUT_SUCCESS = `${appName}/${moduleName}/SIGN_OUT_SUCCESS` +export const AUTH = firebase.auth() //console.log('---', ReducerRecord) export default function reducer(state = new ReducerRecord(), action) { @@ -53,6 +58,13 @@ export function signUp(email, password) { } } +export function signIn(email, password) { + return { + type: SIGN_IN_REQUEST, + payload: {email, password} + } +} + export function signOut() { return { type: SIGN_OUT_REQUEST @@ -60,14 +72,14 @@ export function signOut() { } export const signUpSaga = function * () { - const auth = firebase.auth() + while (true) { const action = yield take(SIGN_UP_REQUEST) try { const user = yield call( - [auth, auth.createUserWithEmailAndPassword], + [AUTH, AUTH.createUserWithEmailAndPassword], action.payload.email, action.payload.password ) yield put({ @@ -83,30 +95,35 @@ export const signUpSaga = function * () { } } -/* -export function signUp(email, password) { - return (dispatch) => { - dispatch({ - type: SIGN_UP_REQUEST - }) +export const signInSaga = function * () { - firebase.auth().createUserWithEmailAndPassword(email, password) - .then(user => dispatch({ - type: SIGN_UP_SUCCESS, + while (true) { + const action = yield take(SIGN_IN_REQUEST) + try { + const user = yield call( + [AUTH, AUTH.signInWithEmailAndPassword], + action.payload.email, action.payload.password + ) + + yield put({ + type: SIGN_IN_SUCCESS, payload: {user} - })) - .catch(error => dispatch({ - type: SIGN_UP_ERROR, + }) + yield put(push('/admin/people')) + + } catch (error) { + yield put({ + type: SIGN_IN_ERROR, error - })) + }) + } } } -*/ export const watchStatusChange = function * () { - const auth = firebase.auth() + try { - yield cps([auth, auth.onAuthStateChanged]) + yield cps([AUTH, AUTH.onAuthStateChanged]) } catch (user) { yield put({ type: SIGN_IN_SUCCESS, @@ -115,22 +132,11 @@ export const watchStatusChange = function * () { } } -/* -firebase.auth().onAuthStateChanged(user => { - const store = require('../redux').default - store.dispatch({ - type: SIGN_IN_SUCCESS, - payload: {user} - }) -}) - -*/ - export const signOutSaga = function * () { - const auth = firebase.auth() + try { - yield call([auth, auth.signOut]) + yield call([AUTH, AUTH.signOut]) yield put({ type: SIGN_OUT_SUCCESS }) @@ -143,7 +149,8 @@ export const signOutSaga = function * () { export const saga = function * () { yield all([ signUpSaga(), + signInSaga(), watchStatusChange(), - takeEvery(SIGN_OUT_REQUEST, signOutSaga) + takeEvery(SIGN_OUT_REQUEST, signOutSaga), ]) } \ No newline at end of file diff --git a/src/ducks/auth.test.js b/src/ducks/auth.test.js new file mode 100644 index 0000000..75f7630 --- /dev/null +++ b/src/ducks/auth.test.js @@ -0,0 +1,47 @@ +import {signInSaga, + signUpSaga, + SIGN_IN_REQUEST, + SIGN_UP_SUCCESS, + SIGN_IN_SUCCESS, + SIGN_IN_ERROR, + AUTH +} from './auth' +import {call,take, put} from 'redux-saga/effects' +import {push} from 'react-router-redux' + +//signIn + +const user = { + email: 'uu@uu.com', + password: '11111111' +} + +const action ={ + type:SIGN_IN_REQUEST, + payload:user +} + + +it('sign In user', () => { + + const saga = signInSaga() + + expect(saga.next().value).toEqual(take(SIGN_IN_REQUEST)) + + expect(saga.next(action).value).toEqual(call( + [AUTH, AUTH.signInWithEmailAndPassword], + user.email, user.password + )) + + expect(saga.next(user).value).toEqual(put({ + type:SIGN_IN_SUCCESS, + payload:{user} + })) + + expect(saga.next().value).toEqual(put(push('/admin/people'))) + + //const error = 'some error'; + expect(saga.throw()).toEqual({ + type: SIGN_IN_ERROR + }) +}) diff --git a/src/ducks/registeredUser.js b/src/ducks/registeredUser.js new file mode 100644 index 0000000..7cfbd7e --- /dev/null +++ b/src/ducks/registeredUser.js @@ -0,0 +1,35 @@ +import {appName} from '../config' +import {Record} from 'immutable' + +const ReducerRecord = Record({ + users: [], + loading: false +}) + +export const moduleName = 'registeredUser' +export const CHANGE_USERS_LIST = `${appName}/${moduleName}/CHANGE_USERS_LIST` + +//console.log('---', ReducerRecord) +export default function reducer(state = new ReducerRecord(), action) { + const {type, payload} = action + + switch (type) { + case CHANGE_USERS_LIST: + return state + .set('users', payload) + default: + return state + } +} + +export function addUser(email, lastName,firstName) { + + return (dispatch,getState) => { + let _users=[...getState()[moduleName].users] + _users.push({email,lastName,firstName}) + dispatch({ + type: CHANGE_USERS_LIST, + payload:_users + }) + } +}