Skip to content
Permalink
Browse files

feat: book detail page

  • Loading branch information...
Param-Harrison committed Jun 12, 2019
1 parent 147ce15 commit de644a750b935268c085cc83d5771a9b88e17432
Showing with 249 additions and 56 deletions.
  1. +1 −0 package.json
  2. +15 −47 src/App.js
  3. +26 −0 src/components/bookDetail.js
  4. +8 −6 src/components/booksList.js
  5. +47 −0 src/pages/bookDetailPage.js
  6. +55 −0 src/pages/searchPage.js
  7. +97 −3 yarn.lock
@@ -6,6 +6,7 @@
"axios": "^0.19.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-router-dom": "^5.0.1",
"react-scripts": "3.0.1"
},
"scripts": {
@@ -1,55 +1,23 @@
import React, { useState } from 'react';
import axios from 'axios';
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";

import BookSearchForm from './components/bookSearchForm';
import Loader from './components/loader';
import SearchPage from './pages/searchPage.js';
import BookDetailPage from './pages/bookDetailPage';
import './App.css';
import BooksList from './components/booksList';

const App = () => {
const [searchTerm, setSearchTerm] = useState('');
const [books, setBooks] = useState({items: []});
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);

let API_URL = `https://www.googleapis.com/books/v1/volumes`;

const fetchBooks = async () => {
setLoading(true);
setError(false);
try {
const result = await axios.get(`${API_URL}?q=${searchTerm}`);
setBooks(result.data);
}
catch(error) {
setError(true);
}
setLoading(false);
}

const onInputChange = (e) => {
setSearchTerm(e.target.value);
}

const onSubmitHandler = (e) => {
e.preventDefault();
fetchBooks();
}
const NoMatchRoute = () => (
<div>404 Page</div>
);

const App = () => {
return (
<>
<BookSearchForm
onSubmitHandler={onSubmitHandler}
onInputChange={onInputChange}
searchTerm={searchTerm}
error={error}
/>
<Loader
searchTerm={searchTerm}
loading={loading}
/>
<BooksList books={books} />
</>
<Router>
<Switch>
<Route path="/" exact component={SearchPage} />
<Route path="/book/:bookId" exact component={BookDetailPage} />
<Route component={NoMatchRoute} />
</Switch>
</Router>
);
}

@@ -0,0 +1,26 @@
import React from 'react';

import { bookAuthors } from '../utils';

const BookDetail = ({ book }) => {

const createDescMarkup = (description) => { return {__html: description}; };

return (
<section>
<div>
<img alt={`${book.volumeInfo.title} book`} src={`http://books.google.com/books/content?id=${book.id}&printsec=frontcover&img=1&zoom=1&source=gbs_api`} />
<div>
<h3><strong>Title:</strong> { book.volumeInfo.title }</h3>
<p><strong>Authors:</strong> { bookAuthors(book.volumeInfo.authors) }</p>
<p><strong>Published Date:</strong> {book.volumeInfo.publishedDate}</p>
<p><strong>Publisher:</strong> {book.volumeInfo.publisher}</p>
<p><strong>Page Count:</strong> {book.volumeInfo.pageCount}</p>
<div dangerouslySetInnerHTML={createDescMarkup(book.volumeInfo.description)} />
</div>
</div>
</section>
)
};

export default BookDetail;
@@ -1,17 +1,19 @@
import React from 'react';
import { Link } from "react-router-dom";

import { bookAuthors } from '../utils';

const Book = ({ book }) => {
return (
<li>
<div>
<img alt={`${book.volumeInfo.title} book`} src={`http://books.google.com/books/content?id=${book.id}&printsec=frontcover&img=1&zoom=1&source=gbs_api`} />
<div>
<h3>{ book.volumeInfo.title }</h3>
<p>{ bookAuthors(book.volumeInfo.authors) }</p>
<p>{book.volumeInfo.publishedDate}</p>
</div>
<img alt={`${book.volumeInfo.title} book`} src={`http://books.google.com/books/content?id=${book.id}&printsec=frontcover&img=1&zoom=1&source=gbs_api`} />
<div>
<h3>{ book.volumeInfo.title }</h3>
<p>{ bookAuthors(book.volumeInfo.authors) }</p>
<p>{book.volumeInfo.publishedDate}</p>
<Link to={`/book/${book.id}`}>Show details</Link>
</div>
</div>
<hr />
</li>
@@ -0,0 +1,47 @@
import React, { useState, useEffect } from 'react';
import { Link } from "react-router-dom";
import axios from 'axios';

import BookDetail from '../components/bookDetail';

const BookDetailPage = ({ match }) => {
const { params: { bookId } } = match;
const [book, setBook] = useState(null);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);

useEffect(() => {
const API_BASE_URL = `https://www.googleapis.com/books/v1/volumes`;
const fetchBook = async () => {
setLoading(true);
setError(false);
try {
const result = await axios.get(`${API_BASE_URL}/${bookId}`);
setBook(result.data);
}
catch(error) {
setError(true);
}
setLoading(false);
}
// Call the API
fetchBook();
}, [bookId]);

return (
<>
<Link to={`/`}>Go back to search books</Link>
{
loading && <div style={{ color: `green` }}>loading book detail for book ID: <strong>{bookId}</strong></div>
}
{
error && <div style={{ color: `red` }}>some error occurred, while fetching api</div>
}
{
book && <BookDetail book={book} />
}
</>
);
};

export default BookDetailPage;
@@ -0,0 +1,55 @@
import React, { useState } from 'react';
import axios from 'axios';

import BookSearchForm from '../components/bookSearchForm';
import Loader from '../components/loader';
import BooksList from '../components/booksList';

const SearchPage = () => {
const [searchTerm, setSearchTerm] = useState('');
const [books, setBooks] = useState({items: []});
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);

const API_BASE_URL = `https://www.googleapis.com/books/v1/volumes`;

const fetchBooks = async () => {
setLoading(true);
setError(false);
try {
const result = await axios.get(`${API_BASE_URL}?q=${searchTerm}`);
setBooks(result.data);
}
catch(error) {
setError(true);
}
setLoading(false);
}

const onInputChange = (e) => {
setSearchTerm(e.target.value);
}

const onSubmitHandler = (e) => {
e.preventDefault();
fetchBooks();
}

return (
<>
<BookSearchForm
onSubmitHandler={onSubmitHandler}
onInputChange={onInputChange}
searchTerm={searchTerm}
error={error}
/>
<Loader
searchTerm={searchTerm}
loading={loading}
/>
<BooksList books={books} />
</>
);
}

export default SearchPage;

0 comments on commit de644a7

Please sign in to comment.
You can’t perform that action at this time.