Skip to content

Commit

Permalink
Merge 3df628e into 8d9355f
Browse files Browse the repository at this point in the history
  • Loading branch information
WilliamsOhworuka committed Sep 13, 2019
2 parents 8d9355f + 3df628e commit 06762b7
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 63 deletions.
71 changes: 48 additions & 23 deletions src/components/BooksPage/BooksPage.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable no-restricted-globals */
import React, { useContext, useEffect } from 'react';
import ReactRouterPropTypes from 'react-router-prop-types';
import axios from 'axios';
import Filter from './Filter/Filter';
import FilterBox from './FilterBox/FilterBox';
Expand All @@ -10,10 +11,10 @@ import Button from './LoadMoreButton/Button';

const { BACKEND_PATH } = appConfig;

const BooksPage = () => {
const BooksPage = ({ history }) => {
const {
clicked, setOptions, loadMore, setNovels,
setPage, setNotFound, setParam, setLoadMore,
setPage, setNotFound, setLoadMore, getParams,
} = useContext(SearchContext);

useEffect(() => {
Expand All @@ -24,35 +25,59 @@ const BooksPage = () => {
}, []);

useEffect(() => {
const genre = new URLSearchParams(location.search).get('genre');
if (genre) {
axios.get(`${BACKEND_PATH}/novels?genre=${genre}&limit=18`)
.then((res) => {
const { currentPage, totalPages, data } = res.data;
setPage(currentPage + 1);
setNotFound(false);
setParam(`genre=${genre}`);
setNovels(data);
if (currentPage < totalPages) {
setLoadMore(true);
}
})
.catch((err) => {
if (err.response.data.message === 'no novels found in database') {
setNovels([]);
setNotFound(true);
}
});
}
const query = getParams(history.location);
axios.get(`${BACKEND_PATH}/novels?${query}&limit=18`)
.then((res) => {
const { currentPage, totalPages, data } = res.data;
setPage(currentPage + 1);
setNotFound(false);
setNovels(data);
if (currentPage < totalPages) {
setLoadMore(true);
}
})
.catch((err) => {
if (err.response.data.message === 'no novels found in database') {
setNovels([]);
setNotFound(true);
}
});
}, []);

useEffect(() => {
const query = getParams(history.location);
axios.get(`${BACKEND_PATH}/novels?${query}&limit=18`)
.then((res) => {
const { currentPage, totalPages, data } = res.data;
setPage(currentPage + 1);
setNotFound(false);
setNovels(data);
if (currentPage < totalPages) {
setLoadMore(true);
} else {
setLoadMore(false);
}
})
.catch((err) => {
if (err.response.data.message === 'no novels found in database') {
setNovels([]);
setNotFound(true);
}
});
}, [history.location]);

return (
<div className="books-main-page">
<Filter />
{clicked ? <FilterBox /> : null}
{clicked ? <FilterBox history={history} /> : null}
<NovelContainer />
{loadMore ? <Button className="btn get-more-btn" /> : null}
</div>
);
};

BooksPage.propTypes = {
history: ReactRouterPropTypes.history.isRequired,
};

export default BooksPage;
9 changes: 7 additions & 2 deletions src/components/BooksPage/BooksPageWrapper.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import React from 'react';
import { withRouter } from 'react-router-dom';
import ReactRouterPropTypes from 'react-router-prop-types';
import SearchContextProvider from './Hooks/searchContext';
import BooksPage from './BooksPage';
import './BooksPage.scss';

const BooksPageWrapper = () => (
const BooksPageWrapper = ({ history }) => (
<SearchContextProvider>
<BooksPage />
<BooksPage history={history} />
</SearchContextProvider>
);

BooksPageWrapper.propTypes = {
history: ReactRouterPropTypes.history.isRequired,
};

export default withRouter(BooksPageWrapper);
8 changes: 6 additions & 2 deletions src/components/BooksPage/FilterBox/FilterBox.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import React from 'react';
import ReactRouterPropTypes from 'react-router-prop-types';
import Search from '../search/Search';
import SearchButton from '../SearchButton/SearchButton';
import Dropdown from '../../helpers/Dropdown/Dropdown';
import './FilterBox.scss';

const FilterBox = () => (
const FilterBox = ({ history }) => (
<div className="filter-box">
<Search className="book-search" name="Author" id="author" />
<Search className="book-search" name="Title" id="title" />
<Search className="book-search" name="Keyword" id="keyword" />
<Dropdown label="Genre" id="genre" name="Genres" />
<SearchButton />
<SearchButton history={history} />
</div>
);

FilterBox.propTypes = {
history: ReactRouterPropTypes.history.isRequired,
};
export default FilterBox;
63 changes: 29 additions & 34 deletions src/components/BooksPage/Hooks/searchContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,42 +21,37 @@ const SearchContextProvider = ({ children }) => {
const [notFound, setNotFound] = useState(false);
const [page, setPage] = useState(1);
const [loadMore, setLoadMore] = useState(false);
const [params, setParam] = useState('');
let initialParams;
const [params, setParams] = useState();

const handleSearch = () => {
const tempValues = Object.keys(filterValues);
let query = [];
for (let i = 0; i < tempValues.length; i += 1) {
if (tempValues[i] === 'keyword' && filterValues[tempValues[i]] && filterValues[tempValues[i]] !== '') {
query = [`keyword=${filterValues[tempValues[i]]}`];
break;
}
if (filterValues[tempValues[i]] && filterValues[tempValues[i]] !== '') {
query.push(`${tempValues[i]}=${filterValues[tempValues[i]]}`);
}
}
initialParams = query.join('&');
setParam(initialParams);
const getParams = (local) => {
const searchParams = new URLSearchParams(local.search);
const param = [...searchParams.entries()];
setParams(param);
return param.map((query) => query.join('=')).join('&');
};

const isEmpty = (value) => (
(typeof value === 'string' && value.trim().length === 0)
|| (typeof value === 'object' && Object.keys(value) === 0)
|| (value === undefined)
);

const updateUrl = (query, history) => {
const newQuery = new URLSearchParams(query);
history.push(`?${newQuery.toString()}`);
};

if (query.length) {
axios.get(`${BACKEND_PATH}/novels?${initialParams}&limit=18`)
.then((res) => {
const { currentPage, totalPages, data } = res.data;
setPage(currentPage + 1);
setNotFound(false);
setNovels(data);
if (currentPage < totalPages) {
setLoadMore(true);
}
})
.catch((err) => {
if (err.response.data.message === 'no novels found in database') {
setNovels([]);
setNotFound(true);
}
});
const handleSearch = (history) => {
const tempValues = Object.entries(filterValues);
let query;
let values;
if (filterValues.keyword === null || isEmpty(filterValues.keyword)) {
values = tempValues.filter((val) => val[1] !== null && !isEmpty(val[1]));
query = values.map((item) => item.join('=')).join('&');
} else {
query = `keyword=${filterValues.keyword}`;
}
updateUrl(query, history);
};

const handleClick = () => {
Expand Down Expand Up @@ -90,11 +85,11 @@ const SearchContextProvider = ({ children }) => {
notFound,
handleClick,
loadMore,
setParam,
setNovels,
setNotFound,
setPage,
setLoadMore,
getParams,
}}
>
{children}
Expand Down
9 changes: 7 additions & 2 deletions src/components/BooksPage/SearchButton/SearchButton.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import React, { useContext } from 'react';
import ReactRouterPropTypes from 'react-router-prop-types';
import './SearchButton.scss';
import { SearchContext } from '../Hooks/searchContext';

const SearchButton = () => {
const SearchButton = ({ history }) => {
const { handleSearch } = useContext(SearchContext);
return (
<button type="button" className="btn search-btn" onClick={handleSearch}>Search</button>
<button type="button" className="btn search-btn" onClick={() => handleSearch(history)}>Search</button>
);
};

SearchButton.propTypes = {
history: ReactRouterPropTypes.history.isRequired,
};

export default SearchButton;
5 changes: 5 additions & 0 deletions src/components/layout/Navbar/AuthenticatedNav.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import socket from '../../../helpers/socket';
import notificationState from '../../../hooks/Notification';
import Notification from '../../Notification/Notification';
import { markAllAsRead } from '../../../api/notification';
import appConfig from '../../../config/appConfig';

const { FRONTEND_PATH } = appConfig;

const AuthenticatedNav = () => {
const { id } = JSON.parse(window.localStorage.getItem('AuthorsHavenUser'));
Expand Down Expand Up @@ -58,6 +61,8 @@ const AuthenticatedNav = () => {
<nav className={isVerified || location.pathname !== '/confirmation-page' ? 'authenticated-nav navbar' : 'authenticated-nav navbar confirm-page'}>
<div className="nav-wrapper">
<img
onClick={() => { location.href = `${FRONTEND_PATH}/homepage`; }}
role="presentation"
className="brand-logo center"
src="https://res.cloudinary.com/drlcfqzym/image/upload/v1567007007/ah-logo-black.png"
alt="Author's Haven"
Expand Down

0 comments on commit 06762b7

Please sign in to comment.