diff --git a/client/src/app/actions/api.js b/client/src/app/actions/api.js index c315131..b056f19 100644 --- a/client/src/app/actions/api.js +++ b/client/src/app/actions/api.js @@ -13,9 +13,9 @@ export default { fetchRecentBooks: (offset, limit) => axios .get(`api/v1/auth/books/recentbooks?offset=${offset}&limit=${limit}`) .then(res => res.data), - fetchOverdueBooks: (offset,limit) => axios - .get(`api/v1/users/getoverduebooks?offset=${offset}&limit=${limit}`) - .then(res=>res.data), + fetchOverdueBooks: (offset, limit) => axios + .get(`api/v1/users/getoverduebooks?offset=${offset}&limit=${limit}`) + .then(res => res.data), fetchbooksbyUserId: (offset, limit) => axios .get(`api/v1/users/borrowedbooks?offset=${offset}&limit=${limit}&returned=false`) .then(res => res.data), @@ -23,7 +23,7 @@ export default { .then(res => res.data), returnbook: data => axios.put('api/v1/users/returnbook', data) .then(res => res.data), - loanhistory:(offset, limit) => axios + loanhistory: (offset, limit) => axios .get(`api/v1/users/getloanhistory?offset=${offset}&limit=${limit}`) .then(res => res.data) } diff --git a/client/src/app/actions/authenticate.js b/client/src/app/actions/authenticate.js index e9f244a..256c5ef 100644 --- a/client/src/app/actions/authenticate.js +++ b/client/src/app/actions/authenticate.js @@ -13,7 +13,7 @@ import setAuthorizationToken from '../utils/setAuthorizationToken'; /** * create action: userLoggedIn: user * @function userLoggedIn - * @param {object} response + * @param {object} data * @returns {object} action: type and response */ export const userLoggedIn = data => @@ -31,7 +31,7 @@ export const userLogInFailure = error => /** * create action: userLoggedIn: user * @function userLoggedOut - * @param {object} response + * @param {object} user * @returns {object} action: type and response */ export const userLoggedOut = user => @@ -43,7 +43,7 @@ export const userLoggedOut = user => /** * create action: sign : user * @function userAuthFailure - * @param {object} response + * @param {object} user * @returns {object} action: type and response */ export const signUpUserFailure = user => @@ -55,7 +55,7 @@ export const signUpUserFailure = user => /** * create action: signUpUserSuccess : user * @function signUpUserSuccess - * @param {object} response + * @param {object} user * @returns {object} action: type and response */ export const signUpUserSuccess = user => @@ -67,7 +67,7 @@ export const signUpUserSuccess = user => /** * async helper function: sign up user * @function signup - * @param {object} credentials + * @param {object} data * @returns {function} asynchronous action */ export const signup = data => dispatch => api diff --git a/client/src/app/actions/borrowbooks.js b/client/src/app/actions/borrowbooks.js index 39731ed..fe9076e 100644 --- a/client/src/app/actions/borrowbooks.js +++ b/client/src/app/actions/borrowbooks.js @@ -11,6 +11,7 @@ export const LoanBooksRejected = error => ({ type: BORROW_BOOKS_FAIL, error }); /** * async helper function: log in user * @function BorrowBooks + * @param {object} data * @returns {function} asynchronous action */ export const borrowbooks = data => dispatch => api diff --git a/client/src/app/actions/fetchbooks.js b/client/src/app/actions/fetchbooks.js index efd9966..381473f 100644 --- a/client/src/app/actions/fetchbooks.js +++ b/client/src/app/actions/fetchbooks.js @@ -14,7 +14,7 @@ export const fetchRecentBooks = books => ({ type: FETCH_ALL_RECENT_BOOKS, books export const fetchBooks = books => ({ type: FETCH_ALL_BOOKS, books }); export const fetchBooksByUserId = books => ({ type: FETCH_BOOKS_BY_USER_ID, books }); export const fetchingBooks = state => ({ type: FETCHING_BOOKS, state }); -export const fetchOverdueBooks = books => ({ type: FETCH_ALL_OVERDUE_BOOKS, books }); +export const fetchOverdueBooks = books => ({ type: FETCH_ALL_OVERDUE_BOOKS, books }); /** * async helper function: log in user @@ -32,7 +32,7 @@ export const fetchAllBooks = (offset, limit) => dispatch => api return response; }) .catch((error) => { - dispatch(showErrorNotification({ error })) + dispatch(showErrorNotification({ error })); dispatch(fetchBooksRejected({ error })); dispatch(fetchingBooks(false)); }); @@ -45,16 +45,16 @@ export const fetchAllBooks = (offset, limit) => dispatch => api * @returns {function} asynchronous action */ export const fetchOverdueBookstoDashboard = (offset, limit) => dispatch => api -.book -.fetchOverdueBooks(offset, limit) -.then((response) => { - dispatch(fetchOverdueBooks(response)); - return response; -}) -.catch((error) => { - dispatch(showErrorNotification({ error })) - dispatch(fetchBooksRejected({ error })); -}); + .book + .fetchOverdueBooks(offset, limit) + .then((response) => { + dispatch(fetchOverdueBooks(response)); + return response; + }) + .catch((error) => { + dispatch(showErrorNotification({ error })); + dispatch(fetchBooksRejected({ error })); + }); /** @@ -64,7 +64,7 @@ export const fetchOverdueBookstoDashboard = (offset, limit) => dispatch => api * @param {integer} limit * @returns {function} asynchronous action */ -export const fetchBooksforDashboard = (offset, limit) => dispatch => api +export const fetchAllRecentBooks = (offset, limit) => dispatch => api .book .fetchRecentBooks(offset, limit) .then((response) => { @@ -73,7 +73,7 @@ export const fetchBooksforDashboard = (offset, limit) => dispatch => api return response; }) .catch((error) => { - dispatch(showErrorNotification({ error })) + dispatch(showErrorNotification({ error })); dispatch(fetchBooksRejected({ error })); dispatch(fetchingBooks(false)); }); @@ -92,6 +92,6 @@ export const fetchAllBooksbyId = (offset, limit) => dispatch => api dispatch(fetchBooksByUserId(response)); }) .catch((error) => { - dispatch(showErrorNotification({ error })) + dispatch(showErrorNotification({ error })); dispatch(fetchBooksRejected({ error })); }); diff --git a/client/src/app/actions/loanhistory.js b/client/src/app/actions/loanhistory.js index ce5eeab..33b08cf 100644 --- a/client/src/app/actions/loanhistory.js +++ b/client/src/app/actions/loanhistory.js @@ -23,6 +23,6 @@ export const loanhistory = (offset, limit) => dispatch => api return response; }) .catch((error) => { - dispatch(showErrorNotification({ error })) + dispatch(showErrorNotification({ error })); dispatch(loanhistoryFailure({ error })); }); diff --git a/client/src/app/actions/returnbooks.js b/client/src/app/actions/returnbooks.js index 38e2be4..5373990 100644 --- a/client/src/app/actions/returnbooks.js +++ b/client/src/app/actions/returnbooks.js @@ -8,6 +8,7 @@ export const ReturnBookRejected = error => ({ type: RETURN_BOOKS_FAIL, error }); /** * async helper function: Return book * @function ReturnBooks + * @param {object} data * @returns {function} asynchronous action */ export const returnbook = data => dispatch => api diff --git a/client/src/app/actions/uploadImage.js b/client/src/app/actions/uploadImage.js index b06b4f8..6c3cf1f 100644 --- a/client/src/app/actions/uploadImage.js +++ b/client/src/app/actions/uploadImage.js @@ -1,5 +1,6 @@ -import { showErrorNotification, showSuccessNotification } from './notifications'; import request from 'superagent'; +import { showErrorNotification } from './notifications'; + import { UPLOAD_TO_CLOUD_IMAGE_SUCCESS, UPLOAD_TO_CLOUD_IMAGE_FAILURE, @@ -20,7 +21,7 @@ export const imageUploadToCloud = (username, imageData) => (dispatch) => { return (response.body); }) .catch((error) => { - dispatch(showErrorNotification({ error })) + dispatch(showErrorNotification({ error })); UploadImageToCloudFailure(error); }); }; diff --git a/client/src/app/components/container/Dashboard.jsx b/client/src/app/components/container/Dashboard.jsx index ca02113..ed425fe 100644 --- a/client/src/app/components/container/Dashboard.jsx +++ b/client/src/app/components/container/Dashboard.jsx @@ -11,7 +11,7 @@ Dashboard.propTypes = { Dashboard.defaultProps = { username: '', - firstname:'', + firstname: '', email: '', }; @@ -19,7 +19,8 @@ Dashboard.defaultProps = { const mapStateToProps = state => ({ username: state.userReducer.user.username, firstname: state.userReducer.user.firstname, - email: state.userReducer.user.email + email: state.userReducer.user.email, + profilePic: state.userReducer.user.profilePic }); export default connect(mapStateToProps)(Dashboard); diff --git a/client/src/app/components/container/authentication/Logout.jsx b/client/src/app/components/container/authentication/Logout.jsx index 0fbd758..cf2434a 100644 --- a/client/src/app/components/container/authentication/Logout.jsx +++ b/client/src/app/components/container/authentication/Logout.jsx @@ -37,6 +37,9 @@ class Logout extends Component { Logout.propTypes = { logout: PropTypes.func.isRequired, + history: PropTypes.shape({ + push: PropTypes.object + }).isRequired }; diff --git a/client/src/app/components/container/booklist/DisplayAllBooks.jsx b/client/src/app/components/container/booklist/DisplayAllBooks.jsx index 2b1875d..4f329cc 100644 --- a/client/src/app/components/container/booklist/DisplayAllBooks.jsx +++ b/client/src/app/components/container/booklist/DisplayAllBooks.jsx @@ -12,6 +12,13 @@ import PaginationWrapper from '../common/Pagination.jsx'; * @extends {Component} */ class DisplayAllBooks extends React.Component { + /** + * Creates an instance of DisplayAllBooks. + * @param {any} props + * @param {object} offset + * @param {object} limit + * @memberOf DisplayAllBooks + */ constructor(props) { super(props); this.state = { @@ -19,7 +26,6 @@ class DisplayAllBooks extends React.Component { offset: 0 }; } - /** * @description dispatch actions that help populate the dashboard with books * fetch books for the dashboard @@ -33,7 +39,7 @@ class DisplayAllBooks extends React.Component { /** * render Display All Books page component * @method render - * @member Display All Books + * @member DisplayAllBooks * @returns {object} component */ render() { @@ -47,9 +53,8 @@ this.props.allBooksList.books.map(book => ( id={book.id} title={book.title} author={book.author} - category={book.category} description={book.description} - image={book.bookimage} + image={book.bookImage} quantity={book.quantity} /> )); @@ -58,7 +63,6 @@ this.props.allBooksList.books.map(book => ( items: pagination.pageCount, activePage: pagination.page }; - return (
@@ -72,15 +76,29 @@ this.props.allBooksList.books.map(book => ( numberOfRecords={this.state.limit} fetch={this.props.fetchAllBooks} /> -
); } } -// DisplayAllBooks.propTypes = { -// allBooksList: PropTypes. -// }; +DisplayAllBooks.propTypes = { + allBooksList: PropTypes.shape({ + title: PropTypes.string, + author: PropTypes.string, + quantity: PropTypes.number, + description: PropTypes.string, + id: PropTypes.number, + map: PropTypes.object, + pagination: PropTypes.object, + books: PropTypes.arrayOf(PropTypes.shape({ + title: PropTypes.string.isRequired, + author: PropTypes.string.isRequired, + quantity: PropTypes.number.isRequired, + description: PropTypes.string, + })) + }), + fetchAllBooks: PropTypes.func.isRequired +}; DisplayAllBooks.defaultProps = { allBooksList: null diff --git a/client/src/app/components/container/booklist/DisplayBorrowedBooks.jsx b/client/src/app/components/container/booklist/DisplayBorrowedBooks.jsx index be45476..3ffc81c 100644 --- a/client/src/app/components/container/booklist/DisplayBorrowedBooks.jsx +++ b/client/src/app/components/container/booklist/DisplayBorrowedBooks.jsx @@ -13,6 +13,13 @@ import MessageforNoBooks from '../../presentation/messages/dashboardMessages/Mes * @extends {Component} */ class DisplayAllBorrowedBooks extends React.Component { + /** + * Creates an instance of DisplayAllBorrowedBooks. + * @param {any} props + * @param {object} offset + * @param {object} limit + * @memberOf DisplayAllBorrowedBooks + */ constructor(props) { super(props); this.state = { @@ -20,7 +27,6 @@ class DisplayAllBorrowedBooks extends React.Component { offset: 0 }; } - /** * @description dispatch actions that help populate the dashboard with books * fetch books for the current user @@ -29,12 +35,11 @@ class DisplayAllBorrowedBooks extends React.Component { * @returns {void} */ componentDidMount() { -
- {this.state.isLoading && } -
; + if (!this.props.borrowedBooks) { + return ; + } this.props.fetchAllBooksbyId(this.state.offset, this.state.limit); } - /** * render Landing page component * @method render @@ -51,7 +56,6 @@ class DisplayAllBorrowedBooks extends React.Component { key={book.book.id} title={book.book.title} author={book.book.author} - category={book.book.category} description={book.book.description} quantity={book.book.quantity} image={book.book.bookimage} @@ -64,29 +68,44 @@ class DisplayAllBorrowedBooks extends React.Component { activePage: pagination.page }; - return (
- - -
- {[...getAllBooks]} -
- -
- - -
); + return ( +
+ + +
+ {[...getAllBooks]} +
+ +
+ +
); } } -DisplayAllBorrowedBooks.PropTypes = { - borrowedBooks: PropTypes.array +DisplayAllBorrowedBooks.propTypes = { + borrowedBooks: PropTypes.shape({ + title: PropTypes.string, + author: PropTypes.string, + quantity: PropTypes.number, + description: PropTypes.string, + id: PropTypes.number, + map: PropTypes.object, + pagination: PropTypes.object, + books: PropTypes.arrayOf(PropTypes.shape({ + title: PropTypes.string.isRequired, + author: PropTypes.string.isRequired, + quantity: PropTypes.number.isRequired, + description: PropTypes.string, + })) + }), + fetchAllBooksbyId: PropTypes.func.isRequired }; DisplayAllBorrowedBooks.defaultProps = { - boorowedBooks: null, + borrowedBooks: null }; diff --git a/client/src/app/components/container/booklist/DisplayLandingBooks.jsx b/client/src/app/components/container/booklist/DisplayLandingBooks.jsx deleted file mode 100644 index 508da55..0000000 --- a/client/src/app/components/container/booklist/DisplayLandingBooks.jsx +++ /dev/null @@ -1,95 +0,0 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { PropTypes } from 'prop-types'; -import { Preloader, Row } from 'react-materialize'; -import Book from '../../presentation/common/book/DisplayBook.jsx'; -import { fetchBooksforDashboard } from '../../../actions/fetchbooks'; - - -/** - * @description Component for Display Books on the Landing page for all users - * @class DisplayLandingBooks - * @extends {Component} DisplayLandingBooks - * @param {object} props - * @param {object} state - * @param {number} limit - * @param {number} offset - * @return {Component} DisplayLandingBooks - */ -class DisplayLandingBooks extends React.Component { - constructor(props) { - super(props); - this.state = { - limit: 8, - offset: 0, - isLoading: false - }; - } - - /** - * @description dispatch actions that help populate the dashboard with books - * fetch books for the dashboard - * @method componentDidMount - * @memberof DisplayLandingBooks - * @returns {void} - */ - componentDidMount() { - this.setState({ isFetching: true }); - if (this.props.books) { - return; - } - this - .props - .fetchBooksforDashboard(this.state.offset, this.state.limit); - } - /** - * render Landing page component - * @method render - * @member LandingPage - * @returns {object} component - */ - render() { - const fetchingState = this.props.isFetching ? - : null; - const getAllBooks = (this - .props - .recentBooks) ? this - .props - .recentBooks - .map(book => ()) : []; - - return ( -
- -
- {[...getAllBooks]} -
-
-
- ); - } -} - -DisplayLandingBooks.PropTypes = { - books: PropTypes.array -}; - -DisplayLandingBooks.defaultProps = { - books: null, -}; - -const mapStateToProps = ({ bookReducer }) => ({ - recentBooks: bookReducer.recentBooksList, - isFetching: bookReducer.fetchingBooks -}); - -export default connect(mapStateToProps, { fetchBooksforDashboard })(DisplayLandingBooks); diff --git a/client/src/app/components/container/booklist/DisplayOverdueBooks.jsx b/client/src/app/components/container/booklist/DisplayOverdueBooks.jsx index 762fe49..0575438 100644 --- a/client/src/app/components/container/booklist/DisplayOverdueBooks.jsx +++ b/client/src/app/components/container/booklist/DisplayOverdueBooks.jsx @@ -13,6 +13,13 @@ import MessageforNoOverdueBooks from '../../presentation/messages/dashboardMessa * @extends {Component} */ class DisplayOverdueBooks extends React.Component { + /** + * Creates an instance of DisplayAllBorrowedBooks. + * @param {any} props + * @param {object} offset + * @param {object} limit + * @memberOf DisplayAllBorrowedBooks + */ constructor(props) { super(props); this.state = { @@ -29,10 +36,10 @@ class DisplayOverdueBooks extends React.Component { * @returns {void} */ componentDidMount() { -
- {this.state.isLoading && } -
; - this.props.fetchOverdueBookstoDashboard (this.state.offset, this.state.limit); + if (!this.props.overdueBooks) { + return ; + } + this.props.fetchOverdueBookstoDashboard(this.state.offset, this.state.limit); } /** * render Landing page component @@ -63,25 +70,42 @@ class DisplayOverdueBooks extends React.Component { activePage: pagination.page }; - return (
- - -
- {[...getAllBooks]} -
- -
- -
); + return ( +
+ + +
+ {[...getAllBooks]} +
+ +
+ +
); } } -// DisplayOverdueBooks.PropTypes = { -// overdueBooks: PropTypes.array -// }; +DisplayOverdueBooks.propTypes = { + overdueBooks: PropTypes.shape({ + title: PropTypes.string, + author: PropTypes.string, + quantity: PropTypes.number, + description: PropTypes.string, + id: PropTypes.number, + map: PropTypes.object, + pagination: PropTypes.object, + books: PropTypes.arrayOf(PropTypes.shape({ + title: PropTypes.string.isRequired, + author: PropTypes.string.isRequired, + quantity: PropTypes.number.isRequired, + description: PropTypes.string, + })) + }), + fetchOverdueBookstoDashboard: PropTypes.func.isRequired + +}; DisplayOverdueBooks.defaultProps = { overdueBooks: null, @@ -93,4 +117,4 @@ const mapStateToProps = ({ bookReducer }) => ({ overdueBooks: bookReducer.overdueBooksList }); -export default connect(mapStateToProps, { fetchOverdueBookstoDashboard})(DisplayOverdueBooks); +export default connect(mapStateToProps, { fetchOverdueBookstoDashboard })(DisplayOverdueBooks); diff --git a/client/src/app/components/container/booklist/DisplayRecentBooks.jsx b/client/src/app/components/container/booklist/DisplayRecentBooks.jsx new file mode 100644 index 0000000..978444c --- /dev/null +++ b/client/src/app/components/container/booklist/DisplayRecentBooks.jsx @@ -0,0 +1,110 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { PropTypes } from 'prop-types'; +import { Preloader, Row } from 'react-materialize'; +import Book from '../../presentation/common/book/DisplayBook.jsx'; +import { fetchAllRecentBooks } from '../../../actions/fetchbooks'; + + +/** + * @description Component for Display Books on the Landing page for all users + * @class DisplayLandingBooks + * @extends {React.Component} DisplayLandingBooks + * @return {Component} DisplayLandingBooks + */ +class DisplayRecentBooks extends React.Component { + /** + * Creates an instance of DisplayRecentBooks. + * @param {any} props + * @param {object} offset + * @param {object} limit + * @memberOf DisplayRecentBooks + */ + constructor(props) { + super(props); + this.state = { + limit: 8, + offset: 0 + }; + } + + /** + * @description dispatch actions that help populate the dashboard with books + * fetch books for the dashboard + * @method componentDidMount + * @memberof DisplayLandingBooks + * @returns {void} + */ + componentWillMount() { + if (this.props.books) { + return ; + } + this + .props + .fetchAllRecentBooks(this.state.offset, this.state.limit); + } + /** + * render Display Recent component + * @method render + * @member DisplayRecentBooks + * @returns {object} component + */ + render() { + const getAllBooks = (this + .props + .recentBooks) ? this + .props + .recentBooks + .map(book => ()) : []; + + return ( +
+ +
+ {[...getAllBooks]} +
+
+
+ ); + } +} + +DisplayRecentBooks.propTypes = { + books: PropTypes.shape({ + title: PropTypes.string, + author: PropTypes.string, + quantity: PropTypes.number, + description: PropTypes.string, + id: PropTypes.number, + map: PropTypes.object, + pagination: PropTypes.object, + books: PropTypes.arrayOf(PropTypes.shape({ + title: PropTypes.string.isRequired, + author: PropTypes.string.isRequired, + quantity: PropTypes.number.isRequired, + description: PropTypes.string, + })) + }), + fetchAllRecentBooks: PropTypes.func.isRequired, + recentBooks: PropTypes.arrayOf(PropTypes.shape({ + id: PropTypes.integer + })) +}; +DisplayRecentBooks.defaultProps = { + books: null, + recentBooks: [] +}; + +const mapStateToProps = ({ bookReducer }) => ({ + recentBooks: bookReducer.recentBooksList +}); + +export default connect(mapStateToProps, { fetchAllRecentBooks })(DisplayRecentBooks); diff --git a/client/src/app/components/container/common/Pagination.jsx b/client/src/app/components/container/common/Pagination.jsx index f0d9909..eec50b8 100644 --- a/client/src/app/components/container/common/Pagination.jsx +++ b/client/src/app/components/container/common/Pagination.jsx @@ -2,6 +2,12 @@ import React from 'react'; import { PropTypes } from 'prop-types'; import { Pagination, Row } from 'react-materialize'; +/** + * + * + * @class PaginationWrapper + * @extends {React.Component} + */ class PaginationWrapper extends React.Component { pageLimit = (pagenumber, numberOfRecords) => { let pageOffset; diff --git a/client/src/app/components/container/header/Header.jsx b/client/src/app/components/container/header/Header.jsx index adff143..65c4d86 100644 --- a/client/src/app/components/container/header/Header.jsx +++ b/client/src/app/components/container/header/Header.jsx @@ -1,12 +1,12 @@ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import Header from '../../presentation/common/header/Header.jsx'; -const mapStateToProps = (state) => { - return { - isAuthenticated: !!state.userReducer.isAuthenticated, - tokenExists: !!localStorage.getItem('token') - }; -} +const mapStateToProps = state => ({ + + isAuthenticated: !!state.userReducer.isAuthenticated, + tokenExists: !!localStorage.getItem('token') + +}); export default connect(mapStateToProps)(Header); diff --git a/client/src/app/components/container/loanhistory/LoanHistory.jsx b/client/src/app/components/container/loanhistory/LoanHistory.jsx index c83a39d..72da9ba 100644 --- a/client/src/app/components/container/loanhistory/LoanHistory.jsx +++ b/client/src/app/components/container/loanhistory/LoanHistory.jsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React from 'react'; import { connect } from 'react-redux'; import { Preloader } from 'react-materialize'; import PropTypes from 'prop-types'; @@ -12,21 +12,39 @@ import LoanHistoryTable from '../../presentation/loanhistory/LoanHistoryTable.js * @extends {React.Component} */ class LoanHistory extends React.Component { + /** + * Creates an instance of DisplayAllBorrowedBooks. + * @param {any} props + * @param {object} offset + * @param {object} limit + * @memberOf DisplayAllBorrowedBooks + */ constructor(props) { super(props); this.state = { limit: 5, offset: 0, - isLoading: false }; } + /** + * @description dispatch actions that help populate the dashboard with loan history + * fetch books for the dashboard + * @method componentDidMount + * @memberof DisplayLandingBooks + * @returns {void} + */ componentDidMount() { - $("body").css("background-color","#ffff") + $('body').css('background-color', '#ffff'); this.props .loanhistory(this.state.offset, this.state.limit); } - + /** + * render Loan History component + * @method render + * @member loanHistory + * @returns {object} component + */ render() { if (!this.props.bookOperations) { return ; @@ -49,11 +67,25 @@ class LoanHistory extends React.Component { } } +LoanHistory.propTypes = { + bookOperations: PropTypes.PropTypes.shape({ + title: PropTypes.string, + author: PropTypes.string, + quantity: PropTypes.number, + description: PropTypes.string, + id: PropTypes.number, + map: PropTypes.object, + pagination: PropTypes.object, + books: PropTypes.arrayOf(PropTypes.shape({ + title: PropTypes.string.isRequired, + author: PropTypes.string.isRequired, + quantity: PropTypes.number.isRequired, + description: PropTypes.string, + })) + }), + loanhistory: PropTypes.func.isRequired -// LoanHistory.propTypes = { -// bookOperations: PropTypes.array - -// }; +}; LoanHistory.defaultProps = { diff --git a/client/src/app/components/hoc/GuestRoutes.jsx b/client/src/app/components/hoc/GuestRoutes.jsx index 69529e5..b8d08a3 100644 --- a/client/src/app/components/hoc/GuestRoutes.jsx +++ b/client/src/app/components/hoc/GuestRoutes.jsx @@ -3,6 +3,7 @@ import { PropTypes } from 'prop-types'; import { Redirect, Route } from 'react-router-dom'; import { connect } from 'react-redux'; + const GuestRoutes = ({ isAuthenticated, component: Component, @@ -18,7 +19,7 @@ const GuestRoutes = ({ ); GuestRoutes.propTypes = { - component: PropTypes.func, + component: PropTypes.func.isRequired, isAuthenticated: PropTypes.bool.isRequired }; diff --git a/client/src/app/components/hoc/UserRoutes.jsx b/client/src/app/components/hoc/UserRoutes.jsx index d97cd03..1a88c39 100644 --- a/client/src/app/components/hoc/UserRoutes.jsx +++ b/client/src/app/components/hoc/UserRoutes.jsx @@ -6,20 +6,21 @@ import { connect } from 'react-redux'; const UserRoutes = ({ isAuthenticated, tokenExists, - component: Component, + component : Component, ...rest }) => ( (isAuthenticated && tokenExists ? - : )} + : )} /> ); UserRoutes.propTypes = { - component: PropTypes.func, - isAuthenticated: PropTypes.bool.isRequired + component: PropTypes.func.isRequired, + isAuthenticated: PropTypes.bool.isRequired, + tokenExists: PropTypes.bool.isRequired }; const mapStateToProps = state => ({ diff --git a/client/src/app/components/presentation/Dashboard.jsx b/client/src/app/components/presentation/Dashboard.jsx index c0a50c8..980d1bc 100644 --- a/client/src/app/components/presentation/Dashboard.jsx +++ b/client/src/app/components/presentation/Dashboard.jsx @@ -5,7 +5,6 @@ import SideNav from '../presentation/common/SideNav/index.jsx'; import DisplayAllBorrowedBooks from '../container/booklist/DisplayBorrowedBooks.jsx'; import DisplayAllBooks from '../container/booklist/DisplayAllBooks.jsx'; import LoanHistoryTable from '../container/loanhistory/LoanHistory.jsx'; -import MessageforNoOverdueBooks from '../presentation/messages/dashboardMessages/MessageforNoOverdueBooks.jsx'; import DisplayOverdueBooks from '../container/booklist/DisplayOverdueBooks.jsx'; /** @@ -39,10 +38,10 @@ const Dashoard = props => - + - + diff --git a/client/src/app/components/presentation/LandingPage.jsx b/client/src/app/components/presentation/LandingPage.jsx index 1282bff..0ee0e4f 100644 --- a/client/src/app/components/presentation/LandingPage.jsx +++ b/client/src/app/components/presentation/LandingPage.jsx @@ -3,7 +3,7 @@ import { Row } from 'react-materialize'; import PropTypes from 'prop-types'; import WelcomeMessage from './messages/WelcomeMessage.jsx'; import Bottom from '../presentation/common/Footer.jsx'; -import DisplayLandingBooks from '../container/booklist/DisplayLandingBooks.jsx'; +import DisplayRecentBooks from '../container/booklist/DisplayRecentBooks.jsx'; /** * @description Component for Landong Page presentaion component @@ -27,7 +27,7 @@ const LandingPage = ({ isAuthenticated }) => (

Latest Books Available:


{!isAuthenticated && }
- + diff --git a/client/src/app/components/presentation/common/Footer.jsx b/client/src/app/components/presentation/common/Footer.jsx index 3b06d0d..803b61e 100644 --- a/client/src/app/components/presentation/common/Footer.jsx +++ b/client/src/app/components/presentation/common/Footer.jsx @@ -12,7 +12,7 @@ const Bottom = () => ( copyrights="© 2017 Copyright Benny Ogidan and Andela" moreLinks={ -Partners + Partners } /> diff --git a/client/src/app/components/presentation/common/Preloader/ShowProgressBar.jsx b/client/src/app/components/presentation/common/Preloader/ShowProgressBar.jsx index fd780ec..863f312 100644 --- a/client/src/app/components/presentation/common/Preloader/ShowProgressBar.jsx +++ b/client/src/app/components/presentation/common/Preloader/ShowProgressBar.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import {Col, Row, ProgressBar} from 'react-materialize'; +import { Col, Row, ProgressBar } from 'react-materialize'; /** * @description Component for Progress Bar, @@ -7,10 +7,10 @@ import {Col, Row, ProgressBar} from 'react-materialize'; */ const ShowProgressBar = () => ( - + Loading.... - - + + ); diff --git a/client/src/app/components/presentation/common/book/DisplayBook.jsx b/client/src/app/components/presentation/common/book/DisplayBook.jsx index 29e182a..10e6275 100644 --- a/client/src/app/components/presentation/common/book/DisplayBook.jsx +++ b/client/src/app/components/presentation/common/book/DisplayBook.jsx @@ -1,8 +1,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import ReactTooltip from 'react-tooltip'; -import { Modal } from 'react-materialize'; -import DisplayBookModal from './DisplayBookModal.jsx'; + +import DisplayBookModal from './DisplayBookModal.jsx'; /** * @description Book component taking book props @@ -11,47 +11,40 @@ import DisplayBookModal from './DisplayBookModal.jsx'; */ const Book = books => (
- + ); -Book.propTypes = { - books: PropTypes.arrayOf(PropTypes.shape({ - title: PropTypes.string.isRequired, - category: PropTypes.string.isRequired, - author: PropTypes.string.isRequired, - quantity: PropTypes.number.isRequired, - description: PropTypes.string, - index: PropTypes.number - })) - -}; export default Book; diff --git a/client/src/app/components/presentation/common/book/DisplayBookModal.jsx b/client/src/app/components/presentation/common/book/DisplayBookModal.jsx index b9f5985..dd9eccb 100644 --- a/client/src/app/components/presentation/common/book/DisplayBookModal.jsx +++ b/client/src/app/components/presentation/common/book/DisplayBookModal.jsx @@ -83,8 +83,6 @@ else } - - handleBorrowClick = (event) => { event.preventDefault(); const dateString = this.state.returndate.format("YYYY-MM-DD") diff --git a/client/src/app/components/presentation/common/header/NavigationBar.jsx b/client/src/app/components/presentation/common/header/NavigationBar.jsx index 6f735d2..82aba68 100644 --- a/client/src/app/components/presentation/common/header/NavigationBar.jsx +++ b/client/src/app/components/presentation/common/header/NavigationBar.jsx @@ -1,7 +1,7 @@ import React from 'react'; -import {NavLink} from 'react-router-dom'; -import {Navbar} from 'react-materialize'; -import {PropTypes} from 'prop-types'; +import { NavLink } from 'react-router-dom'; +import { Navbar } from 'react-materialize'; +import { PropTypes } from 'prop-types'; /** * @description Component for Navigation @@ -18,7 +18,8 @@ const Navigation = (props) => { key={link} className={props.activeLink === link ? 'active' - : ''}> + : ''} + > {link.toUpperCase()} diff --git a/client/src/app/components/presentation/common/modal/UploadModal.jsx b/client/src/app/components/presentation/common/modal/UploadModal.jsx index a4e07d8..9069f06 100644 --- a/client/src/app/components/presentation/common/modal/UploadModal.jsx +++ b/client/src/app/components/presentation/common/modal/UploadModal.jsx @@ -1,8 +1,8 @@ import React from 'react'; import PropTypes from 'prop-types'; -import {connect} from 'react-redux'; -import { imageUploadToCloud, imageUploadToDb } from '../../../../actions/uploadImage'; -import ShowProgressBar from '../Preloader/ShowProgressBar.jsx' +import { connect } from 'react-redux'; +import { imageUploadToCloud } from '../../../../actions/uploadImage'; +import ShowProgressBar from '../Preloader/ShowProgressBar.jsx'; /** * display modal with a file input field and a submit button @@ -10,10 +10,24 @@ import ShowProgressBar from '../Preloader/ShowProgressBar.jsx' * @extends CommonModal */ class UploadModal extends React.Component { + /** + * + * @static + * @param {string} filename + * @return {string} filename + * + * @memberOf UploadModal + */ + static getFileExtension(filename) { + return filename + .split('.') + .pop(); + } /** * @constructor * @extends React.Component * @param {object} props + * @param {object} state */ constructor(props) { super(props); @@ -28,7 +42,7 @@ class UploadModal extends React.Component { this.onInputChange = this .onInputChange .bind(this); - this.onClick = this + this.onClick = this .onClick .bind(this); } @@ -42,40 +56,34 @@ class UploadModal extends React.Component { */ onInputChange(event) { event.preventDefault(); - this.setState({isLoading: true}); + this.setState({ isLoading: true }); const profilePic = event.target.files[0]; const fileExt = UploadModal.getFileExtension(event.target.files[0].name); const filename = `${this.props.username}.${fileExt}` || event.target.files[0].name; - + this .props .imageUploadToCloud(this.props.username, profilePic) - .then((response)=>{ - this.setState({isLoading: false}) - this.setState({filename}); - } - - ) - + .then(() => { + this.setState({ isLoading: false }); + this.setState({ filename }); + }); } - - onClick(event){ +/** + * + * @param {object} event + * @returns {string} string + * @memberOf UploadModal + */ + onClick(event) { event.preventDefault(); - this.setState({isLoading: true}); - if(this.state.filename) - { - console.log('I am here', this.props.secure_url) - - } - + this.setState({ isLoading: true }); + if (this.state.filename) { + console.log('I am here', this.props.secureUrl); + } } - static getFileExtension(filename) { - return filename - .split('.') - .pop(); - } /** * trigger file selection * @method triggerFileSelect @@ -94,7 +102,6 @@ class UploadModal extends React.Component { * @return {void} */ render() { - return (
{this.state.content} @@ -102,17 +109,18 @@ class UploadModal extends React.Component {

Change profile picture

- - {!this.props.image && + + {!this.props.image && - {this.props.username} + {this.props.username} } + tabIndex="0" + > + className="hidden" + />
- {this.state.isLoading && } + {this.state.isLoading && }
- +
{this.state.footer} {(this.state.filename) ? ( @@ -139,11 +148,12 @@ class UploadModal extends React.Component { : null } Uploadsend + className="modal-action modal-close waves-effect waves-green btn-flat" + >Uploadsend
@@ -153,22 +163,24 @@ class UploadModal extends React.Component { } UploadModal.propTypes = { - updateProfilePicture: PropTypes.func, + imageUploadToCloud: PropTypes.func, image: PropTypes.string, - username: PropTypes.string + username: PropTypes.string, + secureUrl: PropTypes.string }; UploadModal.defaultProps = { - image: null + image: null, + imageUploadToCloud: null, + username: '', + secureUrl: '' }; -const mapStateToProps = state => { - return { - // image: state.userReducer.user.data.userimage, - username: (state.userReducer.user.data) - ? state.userReducer.user.data.username - : '', - secure_url: state.imageReducer.url - } -}; +const mapStateToProps = state => ({ + // image: state.userReducer.user.profilePic, + username: (state.userReducer.user) + ? state.userReducer.user.username + : '', + secureUrl: state.imageReducer.url +}); -export default connect(mapStateToProps, {imageUploadToCloud})(UploadModal); +export default connect(mapStateToProps, { imageUploadToCloud })(UploadModal); diff --git a/client/src/app/components/presentation/loanhistory/LoanHistoryTable.jsx b/client/src/app/components/presentation/loanhistory/LoanHistoryTable.jsx index f5748a5..455ee4b 100644 --- a/client/src/app/components/presentation/loanhistory/LoanHistoryTable.jsx +++ b/client/src/app/components/presentation/loanhistory/LoanHistoryTable.jsx @@ -20,7 +20,7 @@ const BorrowHistoryTable = (props) => { {book.userReturndate ? moment(book.userReturndate).format('LL') || 'N/A' : '-'} {book.returnstatus ? 'Returned' : 'Still Out on Loan'} {/* {moment(book.returndate) > moment() ?
Overdue
: '-'} */} - {(moment(book.returndate) < moment() && book.returnstatus == false )?
Overdue
: '-'} + {(moment(book.returndate) < moment() && book.returnstatus === false) ?
Overdue
: '-'} )) : null; return (rows ? diff --git a/client/src/app/css/style.scss b/client/src/app/css/style.scss index 1343b49..bd9831e 100644 --- a/client/src/app/css/style.scss +++ b/client/src/app/css/style.scss @@ -111,13 +111,13 @@ form p { .book-modal { padding: 10px; } -.loan-status-text{ +.loan-status-text { color: $secondary-color; } -.modal-image{ - max-width : 90%; +.modal-image { + max-width: 90%; } -.loan-status{ +.loan-status { padding: 10px; } .modal-title { @@ -374,7 +374,7 @@ footer { margin-left: auto; } -.overdue{ +.overdue { color: $base-orange; } .nobooks-message { @@ -400,16 +400,17 @@ footer { @media screen and (min-width: 776px) { .overlay-main { - margin-top: -61vh; + margin-top: -58vh; } } + @media screen and (max-width: 776px) { .landing-page-image .card { max-width: 73% !important; margin-left: 10px; } .overlay-main { - margin-top: -51vh; + padding: 14px !important; } } @@ -419,6 +420,12 @@ footer { } } +@media screen and (max-width: 979px) { + .overlay-main { + margin-top: -60vh; + } +} + @media only screen and (max-width: 992px) { header, .main-wrapper, @@ -433,7 +440,7 @@ footer { @media only screen and (min-width: 1078px) { .overlay-main { - margin-top: -60vh; + margin-top: -58vh; } } @media only screen and (min-width: 1600px) { diff --git a/client/src/app/mainRoot.jsx b/client/src/app/mainRoot.jsx index 616093f..7c473c8 100644 --- a/client/src/app/mainRoot.jsx +++ b/client/src/app/mainRoot.jsx @@ -1,7 +1,7 @@ -import React, { Component } from 'react'; +import React from 'react'; import 'redux-notifications/lib/styles.css'; import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; -import Root from './components/Root.jsx'; +import Root from './components/Root.jsx'; import LandingPage from './components/container/LandingPage.jsx'; import Login from './components/container/authentication/SignInPage.jsx'; import SignUp from './components/container/authentication/SignUpPage.jsx'; @@ -9,32 +9,23 @@ import Dashboard from './components/container/Dashboard.jsx'; import Logout from './components/container/authentication/Logout.jsx'; import UserRoutes from './components/hoc/UserRoutes.jsx'; import '../app/css/style.scss'; - -/** - * - * @export - * @class MainRoot - * @extends {Component} - */ -export default class MainRoot extends Component { - render() { - return ( - - - - - - - - - +const MainRoot = () => ( + + + + + + + + + + + {/* */} + + + +); +export default MainRoot; - {/* */} - - - - ); - } -} diff --git a/client/src/app/reducers/bookReducers.js b/client/src/app/reducers/bookReducers.js index fede32c..3a6d248 100644 --- a/client/src/app/reducers/bookReducers.js +++ b/client/src/app/reducers/bookReducers.js @@ -18,7 +18,6 @@ import { * * @export * @param {object} [state={ - * * }] * @param {object} action * @returns {object} state @@ -39,92 +38,92 @@ export default function bookReducer(state = { }; } case FETCH_BOOKS_BY_USER_ID: - { - return { - ...state, - borrowedBooksList: action.books - }; - } + { + return { + ...state, + borrowedBooksList: action.books + }; + } case FETCH_ALL_RECENT_BOOKS: - { - return { - ...state, - recentBooksList: action.books.books - }; - } + { + return { + ...state, + recentBooksList: action.books.books + }; + } case FETCH_ALL_BOOKS: - { - return { - ...state, - allBooksList: action.books - }; - } + { + return { + ...state, + allBooksList: action.books + }; + } case FETCH_BOOKS_REJECTED: - { - return { - ...state, - error: action - }; - } + { + return { + ...state, + error: action + }; + } case BORROW_BOOKS_SUCCESS: - { - return { - ...state, - loanbooks: action - } - } + { + return { + ...state, + loanbooks: action + }; + } case BORROW_BOOKS_FAIL: - { - return { - ...state, - loanbooks: {}, - error: action - } - } + { + return { + ...state, + loanbooks: {}, + error: action + }; + } case RETURN_BOOKS_SUCCESS: - { - return { - ...state, - borrowedBooksList: { - ...state.borrowedBooksList, - books: state - .borrowedBooksList - .books - .filter((book) => book.bookid !== action.returnedBook.id) - }, - overdueBooksList:{ - ...state.overdueBooksList, - books: state - .overdueBooksList - .books - .filter((book) => book.bookid !== action.returnedBook.id) - } - + { + return { + ...state, + borrowedBooksList: { + ...state.borrowedBooksList, + books: state + .borrowedBooksList + .books + .filter(book => book.bookid !== action.returnedBook.id) + }, + overdueBooksList: { + ...state.overdueBooksList, + books: state + .overdueBooksList + .books + .filter(book => book.bookid !== action.returnedBook.id) } - } + + }; + } case RETURN_BOOKS_FAIL: - { - return { - ...state, - returnedbooks: {}, - error: action - } - } + { + return { + ...state, + returnedbooks: {}, + error: action + }; + } case LOAN_HISTORY_FAILURE: - { - return { - ...state, - error + { + return { + ...state, + error: action - } - } + }; + } case LOAN_HISTORY_SUCCESS: - { - return { - ...state, - bookOperations: action.bookOperations - } - } + { + return { + ...state, + bookOperations: action.bookOperations + }; + } default: return state; diff --git a/client/src/app/reducers/imageReducers.js b/client/src/app/reducers/imageReducers.js index 9175016..681db50 100644 --- a/client/src/app/reducers/imageReducers.js +++ b/client/src/app/reducers/imageReducers.js @@ -1,29 +1,35 @@ import { UPLOAD_TO_CLOUD_IMAGE_SUCCESS, UPLOAD_TO_CLOUD_IMAGE_FAILURE -} from '../actions/actiontype' +} from '../actions/actiontype'; const INITIAL_STATE = { body: {} }; -export default function imageReducer(state=INITIAL_STATE,action={}) -{ - switch(action.type){ +/** + * + * @export + * @param {any} [state=INITIAL_STATE] + * @param {any} [action={}] + * @param {object} error + * @returns {object} state + */ +export default function imageReducer(state = INITIAL_STATE, action = {}) { + switch (action.type) { case UPLOAD_TO_CLOUD_IMAGE_SUCCESS: - return{ - ...state, - body: action.response, - url: action.response.secure_url, - upload: 'Success' - }; + return { + ...state, + body: action.response, + url: action.response.secureUrl, + upload: 'Success' + }; case UPLOAD_TO_CLOUD_IMAGE_FAILURE: - return{ - ...state, - error:error - }; + return { + ...state, + error: action.response + }; default: - return state; + return state; } - } diff --git a/client/src/app/store/configStore.prod.js b/client/src/app/store/configStore.prod.js index 2d27bf7..23834d5 100644 --- a/client/src/app/store/configStore.prod.js +++ b/client/src/app/store/configStore.prod.js @@ -1,4 +1,3 @@ -import jwtdecode from 'jwt-decode'; import throttle from 'lodash/throttle'; import { createStore, applyMiddleware } from 'redux'; diff --git a/client/src/app/utils/localSave.js b/client/src/app/utils/localSave.js index b88993d..8fc43c2 100644 --- a/client/src/app/utils/localSave.js +++ b/client/src/app/utils/localSave.js @@ -24,6 +24,6 @@ export const loadState = () => { } return JSON.parse(serializedState); } catch (error) { - return; + console.log(error); } }; diff --git a/package.json b/package.json index 1a35cb1..3233ffa 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,10 @@ "test": "export NODE_ENV=test && mocha server/dist/test/index.spec.js --timeout 10000 && export NODE_ENV=development", "client:test": "jest client/ --coverage", "coverage": "export NODE_ENV=test && npm run pretest && nyc --reporter=lcov --reporter=text --reporter=lcovonly mocha --compilers js:babel-register server/src/test/*", - "start:migrate": "sequelize db:migrate", - "undo:migrate": "sequelize db:migrate:undo:all", + "start:migrate": "sequelize db:migrate ", + "undo:migrate": "sequelize db:migrate:undo:all", + "seed:all":"sequelize db:seed:all", + "undo:seed":"sequelize db:seed:undo:all", "start:dev": "babel-node server/dist/bin/www.js", "start:webdev": "webpack -d && webpack-dev-server && --content-base client/src/ --inline --hot", "start-prod": "babel server/src --out-dir server/dist --presets es2015 && npm run heroku-postbuild", diff --git a/server/src/controllers/books.js b/server/src/controllers/books.js index 56062a9..57bce7d 100644 --- a/server/src/controllers/books.js +++ b/server/src/controllers/books.js @@ -111,8 +111,6 @@ export default { .catch(error => res.status(400).send(error.message)); }); }, - - /** * Route: GET: /books * @description returns a list of all books diff --git a/server/src/controllers/category.js b/server/src/controllers/category.js index fa07f53..6d02654 100644 --- a/server/src/controllers/category.js +++ b/server/src/controllers/category.js @@ -59,7 +59,7 @@ export default { }).then((foundCategory) => { if (foundCategory) { return res.status(409) - .send({ message: 'You have not renamed the category' }); + .send({ message: 'This Category already exists' }); } category.update({ categoryName: req.body.categoryName diff --git a/server/src/seeders/seedbooks.js b/server/src/seeders/seedbooks.js index 4f52132..19094ba 100644 --- a/server/src/seeders/seedbooks.js +++ b/server/src/seeders/seedbooks.js @@ -4,45 +4,181 @@ module.exports = { up: queryInterface => queryInterface.bulkInsert('Books', [ { - title: faker.company.catchPhrase(), - author: faker.name.firstName(), + title: 'Cthulhu', + author: 'Wes Dreamins', categoryId: '3', - quantity: '20', + quantity: '21', description: faker.lorem.paragraphs(), - ISBN: 1222222222, + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,h_499,w_325/v1507396542/CLD-front-cover-preview-v4-3-1_e9bolq.jpg', + ISBN: 1222222, createdAt: new Date(), updatedAt: new Date(), }, { - title: 'Benny goes to school', - author: 'Andela Human', + title: 'Star Wars Deathtroopers', + author: 'Joe Schreiber', + categoryId: '1', + quantity: '21', + description: faker.lorem.paragraphs(), + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,h_499,w_325/v1507396541/cover_bg_d3mob5.jpg', + ISBN: 12343432, + createdAt: new Date(), + updatedAt: new Date(), + }, + { + title: 'Scary or Die', + author: 'Corbin Bleu', + categoryId: '3', + quantity: '21', + description: faker.lorem.paragraphs(), + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,h_499,w_325/v1507396540/images_tlhli6.jpg', + ISBN: 12334542, + createdAt: new Date(), + updatedAt: new Date(), + }, + { + title: 'Origin', + author: 'Dan Brown', + categoryId: '1', + quantity: '21', + description: faker.lorem.paragraphs(), + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,h_499,w_325/v1507396540/9780593078754_cxma9t.jpg', + ISBN: 12336342, + createdAt: new Date(), + updatedAt: new Date(), + }, + { + title: 'A Column of Fire', + author: 'Ken Follet', + categoryId: '2', + quantity: '21', + description: faker.lorem.paragraphs(), + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,h_499,w_325/v1507396540/9781447278733_atkrje.jpg', + ISBN: 123362332, + createdAt: new Date(), + updatedAt: new Date(), + }, + { + title: 'Decay', + author: 'Lockhart', + categoryId: '1', + quantity: '21', + description: faker.lorem.paragraphs(), + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,h_499,w_325/v1507396540/6018732-3x4-700x933_lgudvq.jpg', + ISBN: 123363432, + createdAt: new Date(), + updatedAt: new Date(), + }, + { + title: 'Angel of Repose', + author: 'Wallace Stegner', + categoryId: '2', + quantity: '21', + description: faker.lorem.paragraphs(), + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,h_499,w_325/v1507396540/9781101872765_aikbtf.jpg', + ISBN: 1324222, + createdAt: new Date(), + updatedAt: new Date(), + }, + { + title: 'Capital', + author: 'Thomas Piketty', + categoryId: '1', + quantity: '21', + description: faker.lorem.paragraphs(), + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,h_499,w_325/v1507396539/Capital_in_the_First_Century_bc4bfw.webp', + ISBN: 12163242, + createdAt: new Date(), + updatedAt: new Date(), + }, + { + title: 'The House on the Borderland', + author: 'William Hope Hodgson', + categoryId: '2', + quantity: '21', + description: faker.lorem.paragraphs(), + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,h_499,w_325/v1507396518/51iMfGw6LcL._AC_UL320_SR202_320__ret7dc.jpg', + ISBN: 124363242, + createdAt: new Date(), + updatedAt: new Date(), + }, + { + title: 'Dare', + author: 'Barry McDonagh', + categoryId: '2', + quantity: '23', + description: faker.lorem.paragraphs(), + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,h_499,w_325/v1506272698/book_1_gudyxi.jpg', + ISBN: 121633242, + createdAt: new Date(), + updatedAt: new Date(), + }, + { + title: 'A Room Full of Bones', + author: 'Elly Griffiths', + categoryId: '5', + quantity: '21', + description: faker.lorem.paragraphs(), + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/v1506272697/book4_dwjtvv.jpg', + ISBN: 123343242, + createdAt: new Date(), + updatedAt: new Date(), + }, + { + title: 'I am Watching You', + author: 'Teresa Driscoll', categoryId: '1', quantity: '25', description: faker.lorem.paragraphs(), - ISBN: 1222221212, + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,h_499,w_399/v1506272698/book2_rxfkg9.jpg', + ISBN: 133633242, createdAt: new Date(), updatedAt: new Date(), }, { - title: faker.company.catchPhrase(), - author: faker.name.firstName(), + title: 'The Litigators', + author: 'John Grisham', categoryId: '1', - quantity: '20', + quantity: '19', description: faker.lorem.paragraphs(), - ISBN: 1222343432, + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,w_325/v1506272697/book3_cmhfot.jpg', + ISBN: 123363242, createdAt: new Date(), updatedAt: new Date(), }, { - title: faker.company.catchPhrase(), - author: faker.name.firstName(), - categoryId: 2, - quantity: 20, + title: 'End of Watch', + author: 'Stephen King', + categoryId: '1', + quantity: '24', description: faker.lorem.paragraphs(), - ISBN: 1222343432, + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/v1506272697/book6_v1ufwj.jpg', + ISBN: 123343242, createdAt: new Date(), updatedAt: new Date(), - } + }, + { + title: 'The Redbreast Jo Nesbo', + author: 'Harry Hole', + categoryId: '4', + quantity: '23', + description: faker.lorem.paragraphs(), + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/v1506272697/book5_cpffhx.jpg', + ISBN: 12333233, + createdAt: new Date(), + updatedAt: new Date(), + }, + { + title: 'Fix Entrepreneur and you Fix Nigeria', + author: 'S. K. Ogidan', + categoryId: '1', + quantity: '21', + description: faker.lorem.paragraphs(), + bookImage: 'http://res.cloudinary.com/digpnxufx/image/upload/c_scale,h_499,w_325/v1511882088/20171115_221213_ltwmmw.png', + ISBN: 13223242, + createdAt: new Date(), + updatedAt: new Date(), + }, ]), down: queryInterface => queryInterface.bulkDelete('Books', [{ diff --git a/server/src/seeders/seedcategories.js b/server/src/seeders/seedcategories.js index 7d50c79..82f517b 100644 --- a/server/src/seeders/seedcategories.js +++ b/server/src/seeders/seedcategories.js @@ -12,7 +12,12 @@ module.exports = { updatedAt: new Date(), }, { - categoryName: 'Biography', + categoryName: 'Horror', + createdAt: new Date(), + updatedAt: new Date(), + }, + { + categoryName: 'Thriller', createdAt: new Date(), updatedAt: new Date(), }, @@ -20,9 +25,17 @@ module.exports = { categoryName: 'Action', createdAt: new Date(), updatedAt: new Date(), + }, + { + categoryName: 'Science', + createdAt: new Date(), + updatedAt: new Date(), + }, + { + categoryName: 'Comedy', + createdAt: new Date(), + updatedAt: new Date(), } - - ]), down: queryInterface => diff --git a/server/src/seeders/seedlevels.js b/server/src/seeders/seedlevels.js index 6fe900f..c4b2b98 100644 --- a/server/src/seeders/seedlevels.js +++ b/server/src/seeders/seedlevels.js @@ -18,6 +18,14 @@ module.exports = { createdAt: new Date(), updatedAt: new Date(), }, + { + levelName: 'Gold', + level: 3, + maxDays: 10, + maxBooks: 7, + createdAt: new Date(), + updatedAt: new Date(), + }, { levelName: 'Platinium', level: 4, diff --git a/server/src/seeders/seedusers.js b/server/src/seeders/seedusers.js index 274d1ab..16d8fa3 100644 --- a/server/src/seeders/seedusers.js +++ b/server/src/seeders/seedusers.js @@ -7,17 +7,8 @@ module.exports = { up: queryInterface => queryInterface.bulkInsert('User', [ { - username: faker.internet.userName(), - password: bcrypt.hashSync('bookiiii', 10), - email: faker.internet.email(), - firstname: faker.name.firstName(), - lastname: faker.name.lastName(), - createdAt: new Date(), - updatedAt: new Date(), - }, - { - username: 'fakeadministrator', - password: bcrypt.hashSync('bennyogidan', bcrypt.genSaltSync(10)), + username: 'testuser', + password: bcrypt.hashSync('testuser', bcrypt.genSaltSync(10)), email: 'sample@email.com', firstname: faker.name.firstName(), lastname: faker.name.lastName(), @@ -28,7 +19,7 @@ module.exports = { username: 'bennyogidan', password: bcrypt.hashSync('bennyogidan', bcrypt.genSaltSync(10)), email: 'benfluleck@gmail.com', - firstname: faker.name.firstName(), + firstname: 'Administrator', isAdmin: true, lastname: faker.name.lastName(), createdAt: new Date(), diff --git a/server/src/test/books.spec.js b/server/src/test/books.spec.js index faf927d..eb21684 100644 --- a/server/src/test/books.spec.js +++ b/server/src/test/books.spec.js @@ -250,8 +250,8 @@ describe('HelloBooks', () => { .set('Accept', 'application/x-www-form-urlencoded') .set('x-access-token', token) .send({ - title: 'Benny goes to school', - author: 'Andela Human', + title: 'Learn Java', + author: 'Sleeping Master', categoryId: '1', quantity: '20', description: 'This needs to be a long description', @@ -310,7 +310,7 @@ describe('HelloBooks', () => { }); }); it('should return 200 when searching all books in a category', (done) => { - chai.request(app).get('/api/v1/books/search?searchTerm=Ben&categoryId=1').set('x-access-token', token) + chai.request(app).get('/api/v1/books/search?searchTerm=Sta&categoryId=1').set('x-access-token', token) .end((err, res) => { expect(res.status) .to diff --git a/server/src/test/categories.spec.js b/server/src/test/categories.spec.js index 8686c67..a1eb269 100644 --- a/server/src/test/categories.spec.js +++ b/server/src/test/categories.spec.js @@ -133,9 +133,9 @@ describe('Categories', () => { } ); it('should return 200 when a category is modified', (done) => { - chai.request(app).put('/api/v1/admin/category/2').set('x-access-token', adminToken) + chai.request(app).put('/api/v1/admin/category/7').set('x-access-token', adminToken) .send({ - categoryName: 'Thriller' + categoryName: 'Test Category' }) .end((err, res) => { expect(res.status).to.equal(200); @@ -155,7 +155,7 @@ describe('Categories', () => { (done) => { chai.request(app).put('/api/v1/admin/category/nkkkj').set('x-access-token', adminToken) .send({ - name: 'Thriller' + name: 'Test Category' }) .end((err, res) => { expect(res.status).to.equal(400); @@ -168,7 +168,7 @@ describe('Categories', () => { (done) => { chai.request(app).put('/api/v1/admin/category/404').set('x-access-token', adminToken) .send({ - categoryName: 'Thriller' + categoryName: 'Test Category' }) .end((err, res) => { expect(res.status).to.equal(404); @@ -181,7 +181,7 @@ describe('Categories', () => { (done) => { chai.request(app).put('/api/v1/admin/category/2').set('x-access-token', adminToken) .send({ - categoryName: 'Thriller' + categoryName: 'Test Category' }) .end((err, res) => { expect(res.status).to.equal(409); @@ -192,7 +192,7 @@ describe('Categories', () => { it( 'should return 200 when category is deleted', (done) => { - chai.request(app).delete('/api/v1/admin/category/5').set('x-access-token', adminToken) + chai.request(app).delete('/api/v1/admin/category/7').set('x-access-token', adminToken) .end((err, res) => { expect(res.status).to.equal(200); done(); @@ -202,9 +202,9 @@ describe('Categories', () => { it( 'should return 404 when category to delete is not found', (done) => { - chai.request(app).put('/api/v1/admin/category/5').set('x-access-token', adminToken) + chai.request(app).put('/api/v1/admin/category/7').set('x-access-token', adminToken) .send({ - categoryName: 'Thriller' + categoryName: 'Test Category' }) .end((err, res) => { expect(res.status).to.equal(404);