app/modules/auth/reducers/auth.reducer.js
'use strict';
// Libs
import Rx from 'rxjs';
const Observable = Rx.Observable;
const { ajax } = Observable;
// Constants
/**
* constant
* @type {string}
*/
export const LOGIN_REQUEST = 'LOGIN_REQUEST';
/**
* constant
* @type {string}
*/
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
/**
* constant
* @type {string}
*/
export const LOGIN_FAILURE = 'LOGIN_FAILURE';
/**
* constant
* @type {string}
*/
export const LOGGED_OUT = 'LOGGED_OUT';
// Actions
/**
* action to log user in
* @param {!string} login
* user login
* @param {!string} password
* user password
* @return {Object}
* @property {string} type
* action type
* @property {string} login
* user login
* @property {string} password
* user password
*/
export const logIn = ( login, password ) => ({ type : LOGIN_REQUEST, login, password });
/**
* action to notify user log in success
* @param {!Object} user
* data to associate to the current user
* @return {Object}
* @property {string} type
* action type
* @property {string} user
* user data
*/
export const logInSuccess = user => ({ type : LOGIN_SUCCESS, user });
/**
* action to notify user log in failure
* @param {!Object} error
* error object related to the failure
* @return {Object}
* @property {string} type
* action type
* @property {string} error
* error data
*/
export const logInFailure = error => ({ type : LOGIN_FAILURE, error });
/**
* action to log user out
* @return {Object}
* @property {string} type
* action type
*/
export const logOut = () => ({ type : LOGGED_OUT });
// Epic
/**
* Epic observer that query auth API when triggered
* @param {Object} action$
* action object that trigger the auth API request
* @param {string} action$.type
* action type
* @return {Object}
*/
export const logInEpic = action$ =>
action$.ofType(LOGIN_REQUEST)
.mergeMap(action =>
ajax({
method : 'POST',
url : 'https://reqres.in/api/login',
body : { email : action.login, password : action.password },
crossDomain : true
})
.map(xhr => logInSuccess(xhr.response))
.catch(error => Observable.of(logInFailure(error)))
);
// Reducer
/**
* reducer for auth actions
* @param {Object} state
* current state value
* @param {boolean} state.isFetching
* whether auth process is pending or not
* @param {boolean} state.isAuthenticated
* whether user is authenticated or not
* @param {Object} state.user
* user data
* @param {Object} state.error
* error data
* @param {Object} action
* action to perform on the state
* @param {string} action.type
* describe the action type
* @return {Object}
* @property {boolean} state.isFetching
* whether auth process is pending or not
* @property {boolean} state.isAuthenticated
* whether user is authenticated or not
* @property {Object} state.user
* user data
* @property {Object} state.error
* error data
*/
const authReducer = (
state = {
isFetching : false,
isAuthenticated : false,
user : {},
error : {}
},
action
) => {
switch ( action.type ) {
case LOGIN_REQUEST:
return Object.assign({}, state, {
isFetching : true,
isAuthenticated : false,
user : {},
error : {}
});
case LOGIN_SUCCESS:
return Object.assign({}, state, {
isFetching : false,
isAuthenticated : true,
user : action.user,
error : {}
});
case LOGIN_FAILURE:
return Object.assign({}, state, {
isFetching : false,
isAuthenticated : false,
user : {},
error : action.error
});
case LOGGED_OUT:
return Object.assign({}, state, {
isFetching : false,
isAuthenticated : false,
user : {},
error : {}
});
default:
return state;
}
};
export default authReducer;