Skip to content

Commit

Permalink
fix: Main Page constructed with fixes to components
Browse files Browse the repository at this point in the history
- user Reducers implemented
- Higher Order components introduced to protect routes
- Tighter JSDocs introduced
- Redirection of users on Login to Main Page
- Validations for Sign In and Sign Up pages
[finshes #152539728]
  • Loading branch information
Benny Ogidan authored and Benny Ogidan committed Nov 7, 2017
1 parent 483e920 commit 2e69c07
Show file tree
Hide file tree
Showing 33 changed files with 710 additions and 218 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->

#### How should this be manually tested?


#### Screenshots (if appropriate):
Expand Down
10 changes: 10 additions & 0 deletions client/__test__/reducers/userReducers.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import userReducer from '../../src/app/reducers/userReducers';


describe('User Reducer', () => {
it(' has a default state', () => {
expect(userReducer(undefined, { type: 'undefinedAction' })).toEqual({

});
});
});
4 changes: 1 addition & 3 deletions client/src/app/actions/actiontype.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export const USER_LOGGED_IN = 'USER_LOGGED_IN';

export const USER_LOGGED_OUT = 'USER_LOGGED_OUT';

export const USER_SIGN_IN_FAILURE = 'USER_SIGN_IN_FAILURE';
export const USER_SIGN_UP_FAILURE = 'USER_SIGN_UP_FAILURE';

export const SIGNUP_USER_SUCCESS = 'SIGNUP_USER_SUCCESS';

Expand All @@ -13,8 +13,6 @@ export const FETCH_BOOKS_FULFILLED = 'FETCH_BOOKS_FUFILLED';

export const FETCH_BOOKS_REJECTED = 'FETCH_BOOKS_REJECTED';

export const PERSIST_STATE = 'persit/REHYDRATE';

export const SET_CURRENT_USER = 'SET_CURRENT_USER';

export const FETCH_BOOKS_BY_USER_ID = 'FETCH_BOOKS_BY_USER_ID';
Expand Down
50 changes: 28 additions & 22 deletions client/src/app/actions/authenticate.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import jwtdecode from 'jwt-decode';
import Toast from 'react-materialize';
import {showErrorNotification} from '../notifications/notifications';
import {showErrorNotification, showSuccessNotification} from '../notifications/notifications';

import { USER_LOGGED_IN,
USER_LOGGED_OUT,
USER_SIGN_IN_FAILURE,
USER_SIGN_UP_FAILURE,
SIGNUP_USER_FAILURE,
SIGNUP_USER_SUCCESS,
SET_CURRENT_USER } from './actiontype';

Expand All @@ -16,6 +17,14 @@ export const setCurrentUser = user =>
type: SET_CURRENT_USER,
user
});


/**
* create action: userLoggedIn: user
* @function userLoggedIn
* @param {object} response
* @returns {object} action: type and response
*/
export const userLoggedIn = user =>
({
type: USER_LOGGED_IN,
Expand All @@ -31,40 +40,44 @@ export const userLoggedOut = user =>
export const signInUserFailure = error =>
({
type: USER_SIGN_IN_FAILURE,
isAuthenticated: false,
error
});
export const signUpUserFailure = error =>
({
type: USER_SIGN_UP_FAILURE,
error
});
export const signUpUserSuccess = user => ({ type: SIGNUP_USER_SUCCESS, user });


/**
*
* @param {*} data
* @returns {*} user.data
* async helper function: sign in user
* @function signup
* @param {object} credentials
* @returns {function} asynchronous action
*/
export const signup = data => dispatch => api
.user
.signup(data)
.then((user) => {
const data = user.data;
if (user.status !== 200) {
dispatch(signInUserFailure(user));
if (user.status !== 201) {
dispatch(signUpUserFailure(user));
Promise.reject(data);
} else {
dispatch(showSuccessNotification({user}));
dispatch(signUpUserSuccess(user));

return user.data;
}
})
.catch((error) =>{
dispatch(showErrorNotification({ error }));
dispatch(signInUserFailure(error.response));

});

/**
*
* @param {*} credentials
* async helper function: sign in user
* @function login
* @param {object} credentials
* @returns {function} asynchronous action
*/
export const login = credentials => dispatch => api
.user
Expand All @@ -76,19 +89,12 @@ export const login = credentials => dispatch => api
return Promise.reject(token);
}
localStorage.setItem('token', token);
// localStorage.setItem('username', username);

dispatch(showSuccessNotification({user}));
setAuthorizationToken(token);
dispatch(userLoggedIn(user));
// dispatch(setCurrentUser(jwtdecode(token)));
Materialize.toast(user.data.message, 4000);
// return user;
})
.catch(error =>{
console.log(error.response.data.message , '????????')
dispatch(showErrorNotification({ error }))
// dispatch(signInUserFailure(error.response))

});


Expand Down
13 changes: 6 additions & 7 deletions client/src/app/actions/fetchbooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ import {
} from './actiontype';
import api from './api';

export const fetchBooks = books => ({ type: FETCH_BOOKS, books });
export const fetchBooksRejected = error => ({ type: FETCH_BOOKS_REJECTED, error });
export const fetchBooksfufilled = books => ({ type: FETCH_BOOKS_FULFILLED, books });

export const fetchBooksById = books => ({ type: FETCH_BOOKS_BY_USER_ID, books });
export const fetchBooksByIdRejected = error => ({ type: FETCH_BOOKS_REJECTED_BY_USER_ID, error });
export const fetchBooksByIdfufilled = books => ({ type: FETCH_BOOKS_FULFILLED_BY_USER_ID, books });
export const fetchBooks = books => ({type: FETCH_BOOKS, books});
export const fetchBooksRejected = error => ({type: FETCH_BOOKS_REJECTED, error});
export const fetchBooksfufilled = books => ({type: FETCH_BOOKS_FULFILLED, books});

export const fetchBooksById = books => ({type: FETCH_BOOKS_BY_USER_ID, books});
export const fetchBooksByIdRejected = error => ({type: FETCH_BOOKS_REJECTED_BY_USER_ID, error});
export const fetchBooksByIdfufilled = books => ({type: FETCH_BOOKS_FULFILLED_BY_USER_ID, books});

/**
*
Expand Down
Empty file.
2 changes: 1 addition & 1 deletion client/src/app/components/Root.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import {Row, Col} from 'react-materialize'
import Header from '../components/presentation/common/header/Header.jsx'
import Header from '../components/container/header/Header.jsx'
import { Bottom } from '../components/presentation/common/Footer.jsx'


Expand Down
1 change: 1 addition & 0 deletions client/src/app/components/container/LandingPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {connect} from 'react-redux';
import { fetchBooksforDashboard } from '../../actions/fetchbooks';
import LandingPage from '../presentation/LandingPage.jsx';


const mapStateToProps = (state) => {
return {
books: state.bookReducer.books.books
Expand Down
30 changes: 30 additions & 0 deletions client/src/app/components/container/authentication/SignInPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {login} from '../../../actions/authenticate';
import {connect} from 'react-redux';
import SignInForm from '../../presentation/authentication/SignInPage.jsx'

class SignInPage extends React.Component {
submit = (data)=> {
this.props.
login(data)
.then(()=>{this.props.history.push('/mainpage')})

}
render() {
return (
<SignInForm submit={this.submit}/>

);
}

}


SignInPage.propTypes = {
login: PropTypes.func.isRequired

};


export default connect(null , { login }) (SignInPage);
32 changes: 32 additions & 0 deletions client/src/app/components/container/authentication/SignUpPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {signup} from '../../../actions/authenticate';
import {connect} from 'react-redux';
import SignUpform from '../../container/authentication/SignUpPage.jsx'


class SignUpPage extends React.Component {
submit = (data)=> {
this.props.
signup(data)
.then(()=>{console.log('Nice to meet you')})

}
render() {

return (
<SignUpForm submit={this.submit}/>

);
}

}


SignUpPage.propTypes = {
signup: PropTypes.func.isRequired

};


export default connect(null , { signup }) (SignUpPage);
11 changes: 11 additions & 0 deletions client/src/app/components/container/header/Header.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {connect} from 'react-redux';
import Header from '../../presentation/common/header/Header.jsx';


const mapStateToProps = (state) => {
return {
isAuthenticated: state.userReducer.isAuthenticated
};
}

export default connect(mapStateToProps)(Header);
97 changes: 55 additions & 42 deletions client/src/app/components/presentation/LandingPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,85 @@ import {Row, Preloader} from 'react-materialize';
import PropTypes from 'prop-types';
import {Book} from '../presentation/common/Book/DisplayBook.jsx';



class LandingPage extends React.Component{
constructor(props) {
/**
* @description Component for Welcome Page for all users
* @class Landing Page
* @extends {Component}
*/
class LandingPage extends React.Component {
constructor(props) {
super(props);
this.state = {
limit: 8,
offset: 0
};
}
componentWillMount() {
componentDidMount() {
this
.props
.fetchBooksforDashboard(this.state.offset, this.state.limit)
.props
.fetchBooksforDashboard(this.state.offset, this.state.limit)
}

/**
* render Landing page component
* @method render
* @member LandingPage
* @returns {object} component
*/
render() {
if (!this.props.books) {
return <Preloader size='big' className="center-align"/>
}


render() {
if (!this.props.books) {
return <Preloader size='big' className="center-align"/>
}

const getAllBooks = this
const getAllBooks = this
.props
.books
.map((book) => {
return (<Book
key={book.id}
title={book.title}
author
={book.author}
category={book.category}
description={book.description}
image={book.bookimage}/>);
return (<Book
key={book.id}
title={book.title}
author
={book.author}
category={book.category}
description={book.description}
image={book.bookimage}/>);
});
return (

<div>
<div className ='header-wrapper'>
<div>
<div className='header-wrapper'>
<Row>
<div className= 'header-text'><h1> Welcome!.</h1>
<h1>to Hello Books</h1>
</div>
<div className='header-text'>
<h1>
Welcome!.</h1>
<h1>to Hello Books</h1>
</div>
</Row>
</div>
<Row>

<div className='body-wrapper'>
<div className='overlay-main'>
<Row>
<div className='overlay'>
<h3>Latest Books Available: </h3>
<hr/>
<h5> To Borrow any Books, Please <a href>Login</a></h5>

<p>Click a book for a look at the description</p>
<div className='body-wrapper'>
<div className='overlay-main'>
<Row>
<div className='overlay'>
<h3>Latest Books Available:
</h3>
<hr/>
<h5>
To Borrow any Books, Please
<a href='/login'> Login</a>
</h5>

{[...getAllBooks]}
<p>Click a book for a look at the description</p>

{[...getAllBooks]}

</div>
</Row>
</div>
</div>
</Row>
</div>
</div>
</Row>
</div>
</Row>
</div>

);
}
Expand Down
Loading

0 comments on commit 2e69c07

Please sign in to comment.