Skip to content
This repository has been archived by the owner on Jun 28, 2022. It is now read-only.

Sort out component hierarchy #147

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"private": true,
"dependencies": {
"prop-types": "^15.6.2",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "2.1.1"
},
"scripts": {
Expand Down
198 changes: 47 additions & 151 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import React from 'react'
// import * as BooksAPI from './BooksAPI'
import * as BooksAPI from './BooksAPI';
import BookShelf from './BookShelf';
import './App.css'

class BooksApp extends React.Component {
state = {
shelfNames: {
currentlyReading: 'Currently Reading',
wantToRead: 'Want to Read',
read: 'Read',
},
books: [
{imageLinks:{thumbnail: 'http://books.google.com/books/content?id=pD6arNyKyi8C&printsec=frontcover&img=1&zoom=1&imgtk=AFLRE70Rw0CCwNZh0SsYpQTkMbvz23npqWeUoJvVbi_gXla2m2ie_ReMWPl0xoU8Quy9fk0Zhb3szmwe8cTe4k7DAbfQ45FEzr9T7Lk0XhVpEPBvwUAztOBJ6Y0QPZylo4VbB7K5iRSk&source=gbs_api'}, bookTitle: 'The Hobbit', bookAuthors: 'J.R.R. Tolkien', shelf: 'read'},
{imageLinks:{thumbnail: 'http://books.google.com/books/content?id=uu1mC6zWNTwC&printsec=frontcover&img=1&zoom=1&imgtk=AFLRE73pGHfBNSsJG9Y8kRBpmLUft9O4BfItHioHolWNKOdLavw-SLcXADy3CPAfJ0_qMb18RmCa7Ds1cTdpM3dxAGJs8zfCfm8c6ggBIjzKT7XR5FIB53HHOhnsT7a0Cc-PpneWq9zX&source=gbs_api'}, bookTitle: '1776', bookAuthors: 'David McCullough', shelf: 'want to read'},
{imageLinks:{thumbnail: 'http://books.google.com/books/content?id=PGR2AwAAQBAJ&printsec=frontcover&img=1&zoom=1&imgtk=AFLRE73-GnPVEyb7MOCxDzOYF1PTQRuf6nCss9LMNOSWBpxBrz8Pm2_mFtWMMg_Y1dx92HT7cUoQBeSWjs3oEztBVhUeDFQX6-tWlWz1-feexS0mlJPjotcwFqAg6hBYDXuK_bkyHD-y&source=gbs_api'}, title: 'To Kill a Mockingbird', authors: 'Harper Lee', shelf: 'currently reading'},
],
shelf: 'currentlyReading',
searchResult: [],
/**
* TODO: Instead of using this state variable to keep track of which page
* we're on, use the URL in the browser's address bar. This will ensure that
Expand All @@ -13,6 +26,35 @@ class BooksApp extends React.Component {
showSearchPage: false
}

groupBy = (xs, key) => xs.reduce((acc, x) => Object.assign({}, acc, {
[x[key]]: (acc[x[key]] || []).concat(x)
}), [])

async componentDidMount() {
const data = await BooksAPI.getAll();
this.setState({ books: data });
}

getCurBook = id => {
return this.state.books.find(book => book.id === id);
}

handleShelfChange = async(e, id) => {
const { value } = e.target;
const { books } = this.state;
const copyCurBook = this.getCurBook(id);
const curBookIndex = books.indexOf(copyCurBook);
if (copyCurBook) {
copyCurBook.shelf = value
this.setState(prevState => {
prevState.books.splice(curBookIndex, 1, copyCurBook)
return { books: prevState.books }
});
await BooksAPI.update(copyCurBook, value);
}
}


render() {
return (
<div className="app">
Expand All @@ -34,7 +76,9 @@ class BooksApp extends React.Component {
</div>
</div>
<div className="search-books-results">
<ol className="books-grid"></ol>
<ol className="books-grid">

</ol>
</div>
</div>
) : (
Expand All @@ -43,155 +87,7 @@ class BooksApp extends React.Component {
<h1>MyReads</h1>
</div>
<div className="list-books-content">
<div>
<div className="bookshelf">
<h2 className="bookshelf-title">Currently Reading</h2>
<div className="bookshelf-books">
<ol className="books-grid">
<li>
<div className="book">
<div className="book-top">
<div className="book-cover" style={{ width: 128, height: 193, backgroundImage: 'url("http://books.google.com/books/content?id=PGR2AwAAQBAJ&printsec=frontcover&img=1&zoom=1&imgtk=AFLRE73-GnPVEyb7MOCxDzOYF1PTQRuf6nCss9LMNOSWBpxBrz8Pm2_mFtWMMg_Y1dx92HT7cUoQBeSWjs3oEztBVhUeDFQX6-tWlWz1-feexS0mlJPjotcwFqAg6hBYDXuK_bkyHD-y&source=gbs_api")' }}></div>
<div className="book-shelf-changer">
<select>
<option value="move" disabled>Move to...</option>
<option value="currentlyReading">Currently Reading</option>
<option value="wantToRead">Want to Read</option>
<option value="read">Read</option>
<option value="none">None</option>
</select>
</div>
</div>
<div className="book-title">To Kill a Mockingbird</div>
<div className="book-authors">Harper Lee</div>
</div>
</li>
<li>
<div className="book">
<div className="book-top">
<div className="book-cover" style={{ width: 128, height: 188, backgroundImage: 'url("http://books.google.com/books/content?id=yDtCuFHXbAYC&printsec=frontcover&img=1&zoom=1&imgtk=AFLRE72RRiTR6U5OUg3IY_LpHTL2NztVWAuZYNFE8dUuC0VlYabeyegLzpAnDPeWxE6RHi0C2ehrR9Gv20LH2dtjpbcUcs8YnH5VCCAH0Y2ICaKOTvrZTCObQbsfp4UbDqQyGISCZfGN&source=gbs_api")' }}></div>
<div className="book-shelf-changer">
<select>
<option value="move" disabled>Move to...</option>
<option value="currentlyReading">Currently Reading</option>
<option value="wantToRead">Want to Read</option>
<option value="read">Read</option>
<option value="none">None</option>
</select>
</div>
</div>
<div className="book-title">Ender's Game</div>
<div className="book-authors">Orson Scott Card</div>
</div>
</li>
</ol>
</div>
</div>
<div className="bookshelf">
<h2 className="bookshelf-title">Want to Read</h2>
<div className="bookshelf-books">
<ol className="books-grid">
<li>
<div className="book">
<div className="book-top">
<div className="book-cover" style={{ width: 128, height: 193, backgroundImage: 'url("http://books.google.com/books/content?id=uu1mC6zWNTwC&printsec=frontcover&img=1&zoom=1&imgtk=AFLRE73pGHfBNSsJG9Y8kRBpmLUft9O4BfItHioHolWNKOdLavw-SLcXADy3CPAfJ0_qMb18RmCa7Ds1cTdpM3dxAGJs8zfCfm8c6ggBIjzKT7XR5FIB53HHOhnsT7a0Cc-PpneWq9zX&source=gbs_api")' }}></div>
<div className="book-shelf-changer">
<select>
<option value="move" disabled>Move to...</option>
<option value="currentlyReading">Currently Reading</option>
<option value="wantToRead">Want to Read</option>
<option value="read">Read</option>
<option value="none">None</option>
</select>
</div>
</div>
<div className="book-title">1776</div>
<div className="book-authors">David McCullough</div>
</div>
</li>
<li>
<div className="book">
<div className="book-top">
<div className="book-cover" style={{ width: 128, height: 192, backgroundImage: 'url("http://books.google.com/books/content?id=wrOQLV6xB-wC&printsec=frontcover&img=1&zoom=1&imgtk=AFLRE72G3gA5A-Ka8XjOZGDFLAoUeMQBqZ9y-LCspZ2dzJTugcOcJ4C7FP0tDA8s1h9f480ISXuvYhA_ZpdvRArUL-mZyD4WW7CHyEqHYq9D3kGnrZCNiqxSRhry8TiFDCMWP61ujflB&source=gbs_api")' }}></div>
<div className="book-shelf-changer">
<select>
<option value="move" disabled>Move to...</option>
<option value="currentlyReading">Currently Reading</option>
<option value="wantToRead">Want to Read</option>
<option value="read">Read</option>
<option value="none">None</option>
</select>
</div>
</div>
<div className="book-title">Harry Potter and the Sorcerer's Stone</div>
<div className="book-authors">J.K. Rowling</div>
</div>
</li>
</ol>
</div>
</div>
<div className="bookshelf">
<h2 className="bookshelf-title">Read</h2>
<div className="bookshelf-books">
<ol className="books-grid">
<li>
<div className="book">
<div className="book-top">
<div className="book-cover" style={{ width: 128, height: 192, backgroundImage: 'url("http://books.google.com/books/content?id=pD6arNyKyi8C&printsec=frontcover&img=1&zoom=1&imgtk=AFLRE70Rw0CCwNZh0SsYpQTkMbvz23npqWeUoJvVbi_gXla2m2ie_ReMWPl0xoU8Quy9fk0Zhb3szmwe8cTe4k7DAbfQ45FEzr9T7Lk0XhVpEPBvwUAztOBJ6Y0QPZylo4VbB7K5iRSk&source=gbs_api")' }}></div>
<div className="book-shelf-changer">
<select>
<option value="move" disabled>Move to...</option>
<option value="currentlyReading">Currently Reading</option>
<option value="wantToRead">Want to Read</option>
<option value="read">Read</option>
<option value="none">None</option>
</select>
</div>
</div>
<div className="book-title">The Hobbit</div>
<div className="book-authors">J.R.R. Tolkien</div>
</div>
</li>
<li>
<div className="book">
<div className="book-top">
<div className="book-cover" style={{ width: 128, height: 174, backgroundImage: 'url("http://books.google.com/books/content?id=1q_xAwAAQBAJ&printsec=frontcover&img=1&zoom=1&imgtk=AFLRE712CA0cBYP8VKbEcIVEuFJRdX1k30rjLM29Y-dw_qU1urEZ2cQ42La3Jkw6KmzMmXIoLTr50SWTpw6VOGq1leINsnTdLc_S5a5sn9Hao2t5YT7Ax1RqtQDiPNHIyXP46Rrw3aL8&source=gbs_api")' }}></div>
<div className="book-shelf-changer">
<select>
<option value="move" disabled>Move to...</option>
<option value="currentlyReading">Currently Reading</option>
<option value="wantToRead">Want to Read</option>
<option value="read">Read</option>
<option value="none">None</option>
</select>
</div>
</div>
<div className="book-title">Oh, the Places You'll Go!</div>
<div className="book-authors">Seuss</div>
</div>
</li>
<li>
<div className="book">
<div className="book-top">
<div className="book-cover" style={{ width: 128, height: 192, backgroundImage: 'url("http://books.google.com/books/content?id=32haAAAAMAAJ&printsec=frontcover&img=1&zoom=1&imgtk=AFLRE72yckZ5f5bDFVIf7BGPbjA0KYYtlQ__nWB-hI_YZmZ-fScYwFy4O_fWOcPwf-pgv3pPQNJP_sT5J_xOUciD8WaKmevh1rUR-1jk7g1aCD_KeJaOpjVu0cm_11BBIUXdxbFkVMdi&source=gbs_api")' }}></div>
<div className="book-shelf-changer">
<select>
<option value="move" disabled>Move to...</option>
<option value="currentlyReading">Currently Reading</option>
<option value="wantToRead">Want to Read</option>
<option value="read">Read</option>
<option value="none">None</option>
</select>
</div>
</div>
<div className="book-title">The Adventures of Tom Sawyer</div>
<div className="book-authors">Mark Twain</div>
</div>
</li>
</ol>
</div>
</div>
</div>
<BookShelf books={ this.state.books } groupBy={ this.groupBy } shelfNames={ this.state.shelfNames } handleShelfChange={ this.handleShelfChange } />
</div>
<div className="open-search">
<button onClick={() => this.setState({ showSearchPage: true })}>Add a book</button>
Expand Down
43 changes: 43 additions & 0 deletions src/BookShelf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import BookShelfChanger from './BookShelfChanger';


function BookShelf(props){
const { books, groupBy, shelfNames, handleShelfChange } = props;

const groupByShelf = groupBy(books, 'shelf');

return (
<div>
{
Object.entries(groupByShelf).map(([key, value])=>(
<div className="bookshelf" key={ key }>
<h2 className="bookshelf-title">{ shelfNames[key] }</h2>
<div className="bookshelf-books">
<ol className="books-grid">
{
value.map(({ imageLinks: {thumbnail = ''} = {}, title, authors, id, shelf }, index) => {
return (
<li key={index}>
<div className="book">
<div className="book-top">
<div className="book-cover" style={{ width: 128, height: 193, backgroundImage: `url("${ thumbnail }")` }}></div>
<BookShelfChanger handleShelfChange={ handleShelfChange } bookId={ id } currentShelf={ shelf } />
</div>
<div className="book-title">{title}</div>
<div className="book-authors">{authors}</div>
</div>
</li>
)
})
}
</ol>
</div>
</div>
))
}
</div>
);
}

export default BookShelf;
19 changes: 19 additions & 0 deletions src/BookShelfChanger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';

function BookShelfChanger(props) {
const { handleShelfChange, currentShelf, bookId } = props;

return (
<div className="book-shelf-changer">
<select value={ currentShelf } onChange={ e => handleShelfChange(e, bookId) }>
<option value="move" disabled>Move to...</option>
<option value="currentlyReading">Currently Reading</option>
<option value="wantToRead">Want to Read</option>
<option value="read">Read</option>
<option value="none">None</option>
</select>
</div>
);
}

export default BookShelfChanger;
29 changes: 13 additions & 16 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7753,15 +7753,14 @@ react-dev-utils@^6.1.1:
strip-ansi "4.0.0"
text-table "0.2.0"

react-dom@^16.6.3:
version "16.6.3"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.6.3.tgz#8fa7ba6883c85211b8da2d0efeffc9d3825cccc0"
integrity sha512-8ugJWRCWLGXy+7PmNh8WJz3g1TaTUt1XyoIcFN+x0Zbkoz+KKdUyx1AQLYJdbFXjuF41Nmjn5+j//rxvhFjgSQ==
react-dom@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"
scheduler "^0.11.2"
scheduler "^0.20.2"

react-error-overlay@^5.1.0:
version "5.1.0"
Expand Down Expand Up @@ -7823,15 +7822,13 @@ [email protected]:
optionalDependencies:
fsevents "1.2.4"

react@^16.6.3:
version "16.6.3"
resolved "https://registry.yarnpkg.com/react/-/react-16.6.3.tgz#25d77c91911d6bbdd23db41e70fb094cc1e0871c"
integrity sha512-zCvmH2vbEolgKxtqXL2wmGCUxUyNheYn/C+PD1YAjfxHC54+MhdruyhO7QieQrYsYeTxrn93PM2y0jRH1zEExw==
react@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"
scheduler "^0.11.2"

read-pkg-up@^1.0.1:
version "1.0.1"
Expand Down Expand Up @@ -8278,10 +8275,10 @@ saxes@^3.1.3:
dependencies:
xmlchars "^1.3.1"

scheduler@^0.11.2:
version "0.11.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.11.2.tgz#a8db5399d06eba5abac51b705b7151d2319d33d3"
integrity sha512-+WCP3s3wOaW4S7C1tl3TEXp4l9lJn0ZK8G3W3WKRWmw77Z2cIFUW2MiNTMHn5sCjxN+t7N43HAOOgMjyAg5hlg==
scheduler@^0.20.2:
version "0.20.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
Expand Down