From 41499ab6880e43421cfb7f2730042a67a5a1c0b0 Mon Sep 17 00:00:00 2001 From: Steven Snyder Date: Tue, 5 May 2020 17:40:07 -0400 Subject: [PATCH 01/10] added initial structure --- package.json | 2 +- src/App.js | 165 +++--------------------------------- src/Components/Currently.js | 63 ++++++++++++++ src/Components/Read.js | 81 ++++++++++++++++++ src/Components/WantTo.js | 63 ++++++++++++++ src/index.js | 3 +- yarn.lock | 104 ++++++++++++++++++++++- 7 files changed, 325 insertions(+), 156 deletions(-) create mode 100644 src/Components/Currently.js create mode 100644 src/Components/Read.js create mode 100644 src/Components/WantTo.js diff --git a/package.json b/package.json index 579d515885..863f185c86 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,9 @@ "version": "0.1.0", "private": true, "dependencies": { - "prop-types": "^15.6.2", "react": "^16.6.3", "react-dom": "^16.6.3", + "react-router-dom": "^4.3.1", "react-scripts": "2.1.1" }, "scripts": { diff --git a/src/App.js b/src/App.js index 785820d5df..6fc72f0d84 100644 --- a/src/App.js +++ b/src/App.js @@ -2,14 +2,17 @@ import React from 'react' // import * as BooksAPI from './BooksAPI' import './App.css' +// Components +import Currently from './Components/Currently'; +import Read from './Components/Read'; +import WantTo from './Components/WantTo'; + + class BooksApp extends React.Component { state = { - /** - * 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 - * users can use the browser's back and forward buttons to navigate between - * pages, as well as provide a good URL they can bookmark and share. - */ + currentlyReading: null, + wantToRead: null, + read: null, showSearchPage: false } @@ -44,153 +47,9 @@ class BooksApp extends React.Component {
-
-

Currently Reading

-
-
    -
  1. -
    -
    -
    -
    - -
    -
    -
    To Kill a Mockingbird
    -
    Harper Lee
    -
    -
  2. -
  3. -
    -
    -
    -
    - -
    -
    -
    Ender's Game
    -
    Orson Scott Card
    -
    -
  4. -
-
-
-
-

Want to Read

-
-
    -
  1. -
    -
    -
    -
    - -
    -
    -
    1776
    -
    David McCullough
    -
    -
  2. -
  3. -
    -
    -
    -
    - -
    -
    -
    Harry Potter and the Sorcerer's Stone
    -
    J.K. Rowling
    -
    -
  4. -
-
-
-
-

Read

-
-
    -
  1. -
    -
    -
    -
    - -
    -
    -
    The Hobbit
    -
    J.R.R. Tolkien
    -
    -
  2. -
  3. -
    -
    -
    -
    - -
    -
    -
    Oh, the Places You'll Go!
    -
    Seuss
    -
    -
  4. -
  5. -
    -
    -
    -
    - -
    -
    -
    The Adventures of Tom Sawyer
    -
    Mark Twain
    -
    -
  6. -
-
-
+ + +
diff --git a/src/Components/Currently.js b/src/Components/Currently.js new file mode 100644 index 0000000000..10c9b0f35e --- /dev/null +++ b/src/Components/Currently.js @@ -0,0 +1,63 @@ +import React from 'react' +// import * as BooksAPI from './BooksAPI' +import '../App.css' + +export default class Currently extends React.Component { + state = { + /** + * 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 + * users can use the browser's back and forward buttons to navigate between + * pages, as well as provide a good URL they can bookmark and share. + */ + showSearchPage: false + } + + render() { + return ( +
+

Currently Reading

+
+
    +
  1. +
    +
    +
    +
    + +
    +
    +
    To Kill a Mockingbird
    +
    Harper Lee
    +
    +
  2. +
  3. +
    +
    +
    +
    + +
    +
    +
    Ender's Game
    +
    Orson Scott Card
    +
    +
  4. +
+
+
+ ) + } +} diff --git a/src/Components/Read.js b/src/Components/Read.js new file mode 100644 index 0000000000..db3a1ec2a5 --- /dev/null +++ b/src/Components/Read.js @@ -0,0 +1,81 @@ +import React from 'react' +// import * as BooksAPI from './BooksAPI' +import '../App.css' + +export default class Read extends React.Component { + state = { + /** + * 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 + * users can use the browser's back and forward buttons to navigate between + * pages, as well as provide a good URL they can bookmark and share. + */ + showSearchPage: false + } + + render() { + return ( +
+

Read

+
+
    +
  1. +
    +
    +
    +
    + +
    +
    +
    The Hobbit
    +
    J.R.R. Tolkien
    +
    +
  2. +
  3. +
    +
    +
    +
    + +
    +
    +
    Oh, the Places You'll Go!
    +
    Seuss
    +
    +
  4. +
  5. +
    +
    +
    +
    + +
    +
    +
    The Adventures of Tom Sawyer
    +
    Mark Twain
    +
    +
  6. +
+
+
+ ) + } +} diff --git a/src/Components/WantTo.js b/src/Components/WantTo.js new file mode 100644 index 0000000000..aeb632c11a --- /dev/null +++ b/src/Components/WantTo.js @@ -0,0 +1,63 @@ +import React from 'react' +// import * as BooksAPI from './BooksAPI' +import '../App.css' + +export default class WantTo extends React.Component { + state = { + /** + * 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 + * users can use the browser's back and forward buttons to navigate between + * pages, as well as provide a good URL they can bookmark and share. + */ + showSearchPage: false + } + + render() { + return ( +
+

Want to Read

+
+
    +
  1. +
    +
    +
    +
    + +
    +
    +
    1776
    +
    David McCullough
    +
    +
  2. +
  3. +
    +
    +
    +
    + +
    +
    +
    Harry Potter and the Sorcerer's Stone
    +
    J.K. Rowling
    +
    +
  4. +
+
+
+ ) + } +} diff --git a/src/index.js b/src/index.js index fde0d67bd1..2657df6ab1 100644 --- a/src/index.js +++ b/src/index.js @@ -2,5 +2,6 @@ import React from 'react' import ReactDOM from 'react-dom' import App from './App' import './index.css' +import { BrowserRouter } from 'react-router-dom' -ReactDOM.render(, document.getElementById('root')) +ReactDOM.render(, document.getElementById('root')) diff --git a/yarn.lock b/yarn.lock index 7a897f026f..53e971e497 100644 --- a/yarn.lock +++ b/yarn.lock @@ -788,6 +788,13 @@ dependencies: regenerator-runtime "^0.12.0" +"@babel/runtime@^7.1.2": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f" + integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.1.0", "@babel/template@^7.1.2": version "7.1.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.1.2.tgz#090484a574fef5a2d2d7726a674eceda5c5b5644" @@ -4261,6 +4268,18 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== +history@^4.7.2: + version "4.10.1" + resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" + integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== + dependencies: + "@babel/runtime" "^7.1.2" + loose-envify "^1.2.0" + resolve-pathname "^3.0.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + value-equal "^1.0.1" + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -4275,6 +4294,11 @@ hoek@4.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" integrity sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA== +hoist-non-react-statics@^2.5.0: + version "2.5.5" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" + integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== + home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" @@ -5785,7 +5809,7 @@ loglevel@^1.4.1: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po= -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -6748,6 +6772,13 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= +path-to-regexp@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== + dependencies: + isarray "0.0.1" + path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -7548,6 +7579,15 @@ prompts@^0.1.9: kleur "^2.0.1" sisteransi "^0.1.1" +prop-types@^15.6.1, prop-types@^15.7.2: + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" @@ -7768,6 +7808,36 @@ react-error-overlay@^5.1.0: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-5.1.0.tgz#c516995a5652e7bfbed8b497910d5280df74a7e8" integrity sha512-akMy/BQT5m1J3iJIHkSb4qycq2wzllWsmmolaaFVnb+LPV9cIJ/nTud40ZsiiT0H3P+/wXIdbjx2fzF61OaeOQ== +react-is@^16.8.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-router-dom@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.3.1.tgz#4c2619fc24c4fa87c9fd18f4fb4a43fe63fbd5c6" + integrity sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA== + dependencies: + history "^4.7.2" + invariant "^2.2.4" + loose-envify "^1.3.1" + prop-types "^15.6.1" + react-router "^4.3.1" + warning "^4.0.1" + +react-router@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.3.1.tgz#aada4aef14c809cb2e686b05cee4742234506c4e" + integrity sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg== + dependencies: + history "^4.7.2" + hoist-non-react-statics "^2.5.0" + invariant "^2.2.4" + loose-envify "^1.3.1" + path-to-regexp "^1.7.0" + prop-types "^15.6.1" + warning "^4.0.1" + react-scripts@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-2.1.1.tgz#c2959a756b0b61d3090adece0d7aedd324dff8a5" @@ -7935,6 +8005,11 @@ regenerator-runtime@^0.12.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== +regenerator-runtime@^0.13.4: + version "0.13.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" + integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== + regenerator-transform@^0.13.3: version "0.13.3" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.3.tgz#264bd9ff38a8ce24b06e0636496b2c856b57bcbb" @@ -8140,6 +8215,11 @@ resolve-from@^3.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" integrity sha1-six699nWiBvItuZTM17rywoYh0g= +resolve-pathname@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" + integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -8993,6 +9073,16 @@ timsort@^0.3.0: resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= +tiny-invariant@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" + integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== + +tiny-warning@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -9331,6 +9421,11 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +value-equal@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" + integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== + vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -9380,6 +9475,13 @@ walker@~1.0.5: dependencies: makeerror "1.0.x" +warning@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" + integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== + dependencies: + loose-envify "^1.0.0" + watch@~0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" From 47818c9dc1ef1af85ce9d976f5367409d871c91a Mon Sep 17 00:00:00 2001 From: Steven Snyder Date: Wed, 6 May 2020 00:59:05 -0400 Subject: [PATCH 02/10] added currentreads functionality to display list of books with api --- src/App.js | 42 ++++++++++++++++++++-- src/Components/Currently.js | 72 +++++++++++++------------------------ 2 files changed, 65 insertions(+), 49 deletions(-) diff --git a/src/App.js b/src/App.js index 6fc72f0d84..f594865b6d 100644 --- a/src/App.js +++ b/src/App.js @@ -1,7 +1,8 @@ import React from 'react' -// import * as BooksAPI from './BooksAPI' +import * as BooksAPI from './BooksAPI' import './App.css' + // Components import Currently from './Components/Currently'; import Read from './Components/Read'; @@ -16,7 +17,43 @@ class BooksApp extends React.Component { showSearchPage: false } + componentDidMount() { + BooksAPI.getAll() + .then((books) => { + this.setState(() => ({ + books + })) + }).then(() => { + this.setState({ + currentlyReading: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'currentlyReading' + )) + }) + }) + } + // removeContact = (contact) => { + // this.setState((currentState) => ({ + // contacts: currentState.contacts.filter((c) => { + // return c.id !== contact.id + // }) + // })) + + // BooksAPI.remove(contact) + // } + // createContact = (contact) => { + // BooksAPI.create(contact) + // .then((contact) => { + // this.setState((currentState) => ({ + // contacts: currentState.contacts.concat([contact]) + // })) + // }) + // } + render() { + const currentReads = this.state.books && Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'currentlyReading' + )) + console.log(this.state.books) return (
{this.state.showSearchPage ? ( @@ -47,7 +84,8 @@ class BooksApp extends React.Component {
- + +
diff --git a/src/Components/Currently.js b/src/Components/Currently.js index 10c9b0f35e..d05574efd2 100644 --- a/src/Components/Currently.js +++ b/src/Components/Currently.js @@ -2,62 +2,40 @@ import React from 'react' // import * as BooksAPI from './BooksAPI' import '../App.css' -export default class Currently extends React.Component { - state = { - /** - * 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 - * users can use the browser's back and forward buttons to navigate between - * pages, as well as provide a good URL they can bookmark and share. - */ - showSearchPage: false - } +export default function Currently(props) { + + const { currentBooks } = props - render() { return (

Currently Reading

    -
  1. -
    -
    -
    -
    - -
    -
    -
    To Kill a Mockingbird
    -
    Harper Lee
    + { + currentBooks && currentBooks.map((smoke, index) => ( +
  2. +
    +
    +
    +
    +
    -
  3. -
  4. -
    -
    -
    -
    - -
    -
    -
    Ender's Game
    -
    Orson Scott Card
    -
    -
  5. +
+
{smoke.title}
+
{smoke.authors}
+
+ + + )) + }
) } -} From 2d4c0ca084b1aea28f738de6c2d86f2e3cc5731a Mon Sep 17 00:00:00 2001 From: Steven Snyder Date: Thu, 7 May 2020 13:53:55 -0400 Subject: [PATCH 03/10] Added functionality to update API to all child components of BooksApp --- src/App.js | 117 ++++++++++++++++++------------- src/Components/Currently.js | 82 +++++++++++++--------- src/Components/Read.js | 133 ++++++++++++++++-------------------- src/Components/Search.js | 46 +++++++++++++ src/Components/WantTo.js | 114 +++++++++++++++---------------- 5 files changed, 278 insertions(+), 214 deletions(-) create mode 100644 src/Components/Search.js diff --git a/src/App.js b/src/App.js index f594865b6d..08669b333f 100644 --- a/src/App.js +++ b/src/App.js @@ -2,7 +2,6 @@ import React from 'react' import * as BooksAPI from './BooksAPI' import './App.css' - // Components import Currently from './Components/Currently'; import Read from './Components/Read'; @@ -11,6 +10,7 @@ import WantTo from './Components/WantTo'; class BooksApp extends React.Component { state = { + books: [], currentlyReading: null, wantToRead: null, read: null, @@ -27,74 +27,95 @@ class BooksApp extends React.Component { this.setState({ currentlyReading: Object.values(this.state.books).filter((smoke) => ( smoke.shelf === 'currentlyReading' + )), + read: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'read' + )), + wantToRead: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'wantToRead' )) }) + }).then(() => { + console.log(this.state) }) } - // removeContact = (contact) => { - // this.setState((currentState) => ({ - // contacts: currentState.contacts.filter((c) => { - // return c.id !== contact.id - // }) - // })) - // BooksAPI.remove(contact) - // } - // createContact = (contact) => { - // BooksAPI.create(contact) - // .then((contact) => { - // this.setState((currentState) => ({ - // contacts: currentState.contacts.concat([contact]) - // })) - // }) - // } + changeShelf = (book, shelf) => { + BooksAPI.update(book, shelf) + .then(() => + BooksAPI.getAll() + .then((books) => { + this.setState(() => ({ + books + })) + }).then(() => { + this.setState({ + currentlyReading: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'currentlyReading' + )), + read: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'read' + )), + wantToRead: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'wantToRead' + )) + }) + }) + ) + } render() { - const currentReads = this.state.books && Object.values(this.state.books).filter((smoke) => ( - smoke.shelf === 'currentlyReading' - )) - console.log(this.state.books) - return ( -
- {this.state.showSearchPage ? ( -
-
- -
- {/* - NOTES: The search from BooksAPI is limited to a particular set of search terms. - You can find these search terms here: - https://github.com/udacity/reactnd-project-myreads-starter/blob/master/SEARCH_TERMS.md + const readBooks = this.state.read && this.state.read.map((daBooks, index) => { + return + }) - However, remember that the BooksAPI.search method DOES search by title or author. So, don't worry if - you don't find a specific author or title. Every search is limited by search terms. - */} - + const wantToReadBooks = this.state.wantToRead && this.state.wantToRead.map((daBooks, index) => { + return + }) -
-
-
-
    -
    -
    - ) : ( + const currentlyReading = this.state.currentlyReading && this.state.currentlyReading.map((daBooks, index) => { + return + }) + + + return ( +

    MyReads

    - - - - +
    +

    Currently Reading

    +
    +
      + {currentlyReading} +
    +
    +
    +
    +

    Want To Read

    +
    +
      + {wantToReadBooks} +
    +
    +
    +
    +

    Read

    +
    +
      + {readBooks} +
    +
    +
    - )}
    ) } diff --git a/src/Components/Currently.js b/src/Components/Currently.js index d05574efd2..7fe7b7054c 100644 --- a/src/Components/Currently.js +++ b/src/Components/Currently.js @@ -1,41 +1,59 @@ import React from 'react' -// import * as BooksAPI from './BooksAPI' import '../App.css' -export default function Currently(props) { + export default class Currently extends React.Component { + constructor(props) { + super(props); + this.state = { + value: 'currentlyReading', + currentBook: null + }; + + + this.handleChange = this.handleChange.bind(this); + } - const { currentBooks } = props + componentDidMount() { + this.setState({ + currentBook: this.props.myBook + }) + } + handleChange(event) { + this.setState({ + value: event.target.value + }, + () => { + this.props.updateShelf(this.state.currentBook, this.state.value) + }); + } + + render() { + const {myBook } = this.props + const ifMultipleAuthors = myBook.authors.length === 1 ? myBook.authors : myBook.authors.map((writers, index) => { return
    {writers}
    }) return ( -
    -

    Currently Reading

    -
    -
      - { - currentBooks && currentBooks.map((smoke, index) => ( -
    1. -
      -
      -
      -
      - +
      + { +
    2. +
      +
      +
      +
      + +
      -
      -
      {smoke.title}
      -
      {smoke.authors}
      -
    - - - )) +
    {myBook.title}
    +
    {ifMultipleAuthors}
    +
    + } - -
    - ) - } + ) + } + } \ No newline at end of file diff --git a/src/Components/Read.js b/src/Components/Read.js index db3a1ec2a5..a3959aaf7a 100644 --- a/src/Components/Read.js +++ b/src/Components/Read.js @@ -1,81 +1,62 @@ import React from 'react' -// import * as BooksAPI from './BooksAPI' import '../App.css' -export default class Read extends React.Component { - state = { - /** - * 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 - * users can use the browser's back and forward buttons to navigate between - * pages, as well as provide a good URL they can bookmark and share. - */ - showSearchPage: false - } + export default class Read extends React.Component { + constructor(props) { + super(props); + this.state = { + value: 'read', + currentBook: null + }; + + + this.handleChange = this.handleChange.bind(this); + } + + componentDidMount() { + this.setState({ + currentBook: this.props.myBook + }) + } + + handleChange(event) { + this.setState({ + value: event.target.value + }, + () => { + this.props.updateShelf(this.state.currentBook, this.state.value) + + }); + } + + render() { + + const {myBook } = this.props + const ifMultipleAuthors = myBook.authors.length === 1 ? myBook.authors : myBook.authors.map((writers, index) => { return
    {writers}
    }) - render() { return ( -
    -

    Read

    -
    -
      -
    1. -
      -
      -
      -
      - -
      -
      -
      The Hobbit
      -
      J.R.R. Tolkien
      -
      -
    2. -
    3. -
      -
      -
      -
      - -
      -
      -
      Oh, the Places You'll Go!
      -
      Seuss
      -
      -
    4. -
    5. -
      -
      -
      -
      - -
      -
      -
      The Adventures of Tom Sawyer
      -
      Mark Twain
      -
      -
    6. -
    -
    -
    - ) - } -} +
    + { +
  1. +
    +
    +
    +
    + +
    +
    +
    {myBook.title}
    +
    {ifMultipleAuthors}
    +
    +
  2. + } +
    + ) + } + } \ No newline at end of file diff --git a/src/Components/Search.js b/src/Components/Search.js new file mode 100644 index 0000000000..098ee935e0 --- /dev/null +++ b/src/Components/Search.js @@ -0,0 +1,46 @@ +import React from 'react' +import '../App.css' + + export default class Search extends React.Component { + constructor(props) { + super(props); + this.state = { + value: 'currentlyReading', + currentBook: null + }; + + + this.handleChange = this.handleChange.bind(this); + } + + componentDidMount() { + this.setState({ + currentBook: this.props.myBook + }) + } + + render() { + return ( +
    +
    + +
    + {/* + NOTES: The search from BooksAPI is limited to a particular set of search terms. + You can find these search terms here: + https://github.com/udacity/reactnd-project-myreads-starter/blob/master/SEARCH_TERMS.md + + However, remember that the BooksAPI.search method DOES search by title or author. So, don't worry if + you don't find a specific author or title. Every search is limited by search terms. + */} + + +
    +
    +
    +
      +
      +
      + ) + } + } \ No newline at end of file diff --git a/src/Components/WantTo.js b/src/Components/WantTo.js index aeb632c11a..5a00657252 100644 --- a/src/Components/WantTo.js +++ b/src/Components/WantTo.js @@ -1,63 +1,61 @@ import React from 'react' -// import * as BooksAPI from './BooksAPI' import '../App.css' -export default class WantTo extends React.Component { - state = { - /** - * 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 - * users can use the browser's back and forward buttons to navigate between - * pages, as well as provide a good URL they can bookmark and share. - */ - showSearchPage: false - } + export default class WantTo extends React.Component { + constructor(props) { + super(props); + this.state = { + value: 'wantToRead', + currentBook: null + }; + + + this.handleChange = this.handleChange.bind(this); + } - render() { + componentDidMount() { + this.setState({ + currentBook: this.props.myBook + }) + } + + handleChange(event) { + this.setState({ + value: event.target.value + }, + () => { + this.props.updateShelf(this.state.currentBook, this.state.value) + + }); + } + + render() { + + const { myBook } = this.props + const ifMultipleAuthors = myBook.authors.length === 1 ? myBook.authors : myBook.authors.map((writers, index) => { return
      {writers}
      }) return ( -
      -

      Want to Read

      -
      -
        -
      1. -
        -
        -
        -
        - -
        -
        -
        1776
        -
        David McCullough
        -
        -
      2. -
      3. -
        -
        -
        -
        - -
        -
        -
        Harry Potter and the Sorcerer's Stone
        -
        J.K. Rowling
        -
        -
      4. -
      -
      -
      - ) - } -} +
      + { +
    1. +
      +
      +
      +
      + +
      +
      +
      {myBook.title}
      +
      {ifMultipleAuthors}
      +
      +
    2. + } +
      + ) + } + } \ No newline at end of file From 752ba7002763a39522be6c25260a6ba3aeaecf74 Mon Sep 17 00:00:00 2001 From: Steven Snyder Date: Thu, 7 May 2020 15:38:44 -0400 Subject: [PATCH 04/10] added browser router and routing of search component --- src/App.js | 129 ++++-------------------------------- src/Components/BooksList.js | 127 +++++++++++++++++++++++++++++++++++ src/Components/Search.js | 13 ++-- 3 files changed, 145 insertions(+), 124 deletions(-) create mode 100644 src/Components/BooksList.js diff --git a/src/App.js b/src/App.js index 08669b333f..c48eed8157 100644 --- a/src/App.js +++ b/src/App.js @@ -1,124 +1,23 @@ import React from 'react' -import * as BooksAPI from './BooksAPI' +import BooksList from './Components/BooksList' +import Search from './Components/Search' import './App.css' +import { Route } from 'react-router-dom' -// Components -import Currently from './Components/Currently'; -import Read from './Components/Read'; -import WantTo from './Components/WantTo'; - - -class BooksApp extends React.Component { - state = { - books: [], - currentlyReading: null, - wantToRead: null, - read: null, - showSearchPage: false - } - - componentDidMount() { - BooksAPI.getAll() - .then((books) => { - this.setState(() => ({ - books - })) - }).then(() => { - this.setState({ - currentlyReading: Object.values(this.state.books).filter((smoke) => ( - smoke.shelf === 'currentlyReading' - )), - read: Object.values(this.state.books).filter((smoke) => ( - smoke.shelf === 'read' - )), - wantToRead: Object.values(this.state.books).filter((smoke) => ( - smoke.shelf === 'wantToRead' - )) - }) - }).then(() => { - console.log(this.state) - }) - } - - changeShelf = (book, shelf) => { - BooksAPI.update(book, shelf) - .then(() => - BooksAPI.getAll() - .then((books) => { - this.setState(() => ({ - books - })) - }).then(() => { - this.setState({ - currentlyReading: Object.values(this.state.books).filter((smoke) => ( - smoke.shelf === 'currentlyReading' - )), - read: Object.values(this.state.books).filter((smoke) => ( - smoke.shelf === 'read' - )), - wantToRead: Object.values(this.state.books).filter((smoke) => ( - smoke.shelf === 'wantToRead' - )) - }) - }) - ) - } - - render() { - const readBooks = this.state.read && this.state.read.map((daBooks, index) => { - return - }) - - const wantToReadBooks = this.state.wantToRead && this.state.wantToRead.map((daBooks, index) => { - return - }) - - const currentlyReading = this.state.currentlyReading && this.state.currentlyReading.map((daBooks, index) => { - return - }) - + function App() { return ( -
      -
      -
      -

      MyReads

      -
      -
      -
      -
      -

      Currently Reading

      -
      -
        - {currentlyReading} -
      -
      -
      -
      -

      Want To Read

      -
      -
        - {wantToReadBooks} -
      -
      -
      -
      -

      Read

      -
      -
        - {readBooks} -
      -
      -
      -
      -
      -
      - -
      -
      +
      + ( + + )} /> + ( + + )} />
      ) } -} -export default BooksApp +export default App diff --git a/src/Components/BooksList.js b/src/Components/BooksList.js new file mode 100644 index 0000000000..a4762287f0 --- /dev/null +++ b/src/Components/BooksList.js @@ -0,0 +1,127 @@ +import React from 'react' +import { Link } from 'react-router-dom' +import * as BooksAPI from '../BooksAPI' +import '../App.css' + +// Components +import Currently from './Currently'; +import Read from './Read'; +import WantTo from './WantTo'; + + +class BooksList extends React.Component { + state = { + books: [], + currentlyReading: null, + wantToRead: null, + read: null, + showSearchPage: false + } + + componentDidMount() { + BooksAPI.getAll() + .then((books) => { + this.setState(() => ({ + books + })) + }).then(() => { + this.setState({ + currentlyReading: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'currentlyReading' + )), + read: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'read' + )), + wantToRead: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'wantToRead' + )) + }) + }).then(() => { + console.log(this.state) + }) + } + + changeShelf = (book, shelf) => { + BooksAPI.update(book, shelf) + .then(() => + BooksAPI.getAll() + .then((books) => { + this.setState(() => ({ + books + })) + }).then(() => { + this.setState({ + currentlyReading: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'currentlyReading' + )), + read: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'read' + )), + wantToRead: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'wantToRead' + )) + }) + }) + ) + } + + render() { + const readBooks = this.state.read && this.state.read.map((daBooks, index) => { + return + }) + + const wantToReadBooks = this.state.wantToRead && this.state.wantToRead.map((daBooks, index) => { + return + }) + + const currentlyReading = this.state.currentlyReading && this.state.currentlyReading.map((daBooks, index) => { + return + }) + + + return ( +
      +
      +
      +

      MyReads

      +
      +
      +
      +
      +

      Currently Reading

      +
      +
        + {currentlyReading} +
      +
      +
      +
      +

      Want To Read

      +
      +
        + {wantToReadBooks} +
      +
      +
      +
      +

      Read

      +
      +
        + {readBooks} +
      +
      +
      +
      +
      +
      + + + +
      +
      +
      + ) + } +} + +export default BooksList diff --git a/src/Components/Search.js b/src/Components/Search.js index 098ee935e0..409687e84d 100644 --- a/src/Components/Search.js +++ b/src/Components/Search.js @@ -1,29 +1,24 @@ import React from 'react' import '../App.css' +import { Link } from 'react-router-dom' export default class Search extends React.Component { constructor(props) { super(props); this.state = { - value: 'currentlyReading', - currentBook: null }; - - - this.handleChange = this.handleChange.bind(this); } componentDidMount() { - this.setState({ - currentBook: this.props.myBook - }) } render() { return (
      - + + +
      {/* NOTES: The search from BooksAPI is limited to a particular set of search terms. From 9622379aea075fe45a43ef45726fe43f01c01ed7 Mon Sep 17 00:00:00 2001 From: Steven Snyder Date: Fri, 8 May 2020 12:40:29 -0400 Subject: [PATCH 05/10] fixed search errors, handled search query error in booksapi function --- src/App.js | 38 ++++++++++++- src/BooksAPI.js | 13 ++++- src/Components/Search.js | 118 +++++++++++++++++++++++++++++---------- 3 files changed, 137 insertions(+), 32 deletions(-) diff --git a/src/App.js b/src/App.js index c48eed8157..e37abb9af8 100644 --- a/src/App.js +++ b/src/App.js @@ -3,9 +3,41 @@ import BooksList from './Components/BooksList' import Search from './Components/Search' import './App.css' import { Route } from 'react-router-dom' +import * as BooksAPI from './BooksAPI' - function App() { +export default class App extends React.Component { + state = { + books: [], + currentlyReading: null, + wantToRead: null, + read: null, + showSearchPage: false + } + + componentDidMount() { + BooksAPI.getAll() + .then((books) => { + this.setState(() => ({ + books + })) + }).then(() => { + this.setState({ + currentlyReading: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'currentlyReading' + )), + read: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'read' + )), + wantToRead: Object.values(this.state.books).filter((smoke) => ( + smoke.shelf === 'wantToRead' + )) + }) + }).then(() => { + console.log(this.state) + }) + } +render() { return (
      ( @@ -14,10 +46,10 @@ import { Route } from 'react-router-dom' )} /> ( )} />
      ) } - -export default App +} diff --git a/src/BooksAPI.js b/src/BooksAPI.js index 99b00b788e..f0192aa3fd 100644 --- a/src/BooksAPI.js +++ b/src/BooksAPI.js @@ -41,4 +41,15 @@ export const search = (query) => }, body: JSON.stringify({ query }) }).then(res => res.json()) - .then(data => data.books) + .then((data) => { + console.log(data.books) + if (data.books.error === 'empty query') { + return [] + } else { + return data.books + } + }) + .catch((error) => { + console.error('Error:', error); + return [] + }); diff --git a/src/Components/Search.js b/src/Components/Search.js index 409687e84d..9e6cd6bd02 100644 --- a/src/Components/Search.js +++ b/src/Components/Search.js @@ -1,41 +1,103 @@ import React from 'react' import '../App.css' import { Link } from 'react-router-dom' +import * as BooksAPI from '../BooksAPI' - export default class Search extends React.Component { - constructor(props) { - super(props); - this.state = { - }; - } +export default class Search extends React.Component { + constructor(props) { + super(props); + this.state = { + searchBooks: [], + query: '' + }; + } - componentDidMount() { - } +componentDidMount() { + this.setState({ + books: this.props.books + }) +} + +updateQuery = (query) => { + if (query === '') { + this.setState(() => ({ + searchBooks: [], + query: query.trim() + })) + } else { + this.setState(() => ({ + query: query.trim() + }), () => + BooksAPI.search(this.state.query) + .then((newBooks) => + this.setState({ + searchBooks: newBooks + }) + ))} + } + +clearQuery = () => { + this.updateQuery('') + } + +render() { - render() { - return ( -
      -
      - - - -
      - {/* - NOTES: The search from BooksAPI is limited to a particular set of search terms. - You can find these search terms here: - https://github.com/udacity/reactnd-project-myreads-starter/blob/master/SEARCH_TERMS.md + const { query, searchBooks } = this.state + const bookList = searchBooks !== [] ? searchBooks.map((booksMan, index) => { + const noThumb = booksMan.imageLinks !== undefined ? booksMan.imageLinks.smallThumbnail : 'https://getuikit.com/v2/docs/images/placeholder_600x400.svg' + const ifMultipleAuthors = booksMan.authors !== undefined ? booksMan.authors.length === 1 ? booksMan.authors : booksMan.authors.map((writers, index) => { return
      {writers}
      }) : null - However, remember that the BooksAPI.search method DOES search by title or author. So, don't worry if - you don't find a specific author or title. Every search is limited by search terms. - */} - + return ( +
    3. +
      +
      +
      +
      + +
      +
      +
      {booksMan.title}
      +
      {ifMultipleAuthors}
      +
      +
    4. + ) -
      + }) : null + return ( +
      +
      + + + +
      + {/* + NOTES: The search from BooksAPI is limited to a particular set of search terms. + You can find these search terms here: + https://github.com/udacity/reactnd-project-myreads-starter/blob/master/SEARCH_TERMS.md + + However, remember that the BooksAPI.search method DOES search by title or author. So, don't worry if + you don't find a specific author or title. Every search is limited by search terms. + */} + this.updateQuery(event.target.value)} + /> + +
      -
        +
          {bookList}
        +
        -
        ) } - } \ No newline at end of file +} \ No newline at end of file From 0b2d3b97894f341f49f6ff5718028a2c7d772e93 Mon Sep 17 00:00:00 2001 From: Steven Snyder Date: Sat, 9 May 2020 16:50:53 -0400 Subject: [PATCH 06/10] added searched books functionality to add to shelf --- src/BooksAPI.js | 10 ++++++ src/Components/Search.js | 26 +++----------- src/Components/SearchBooks.js | 67 +++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 21 deletions(-) create mode 100644 src/Components/SearchBooks.js diff --git a/src/BooksAPI.js b/src/BooksAPI.js index f0192aa3fd..199e7a01cb 100644 --- a/src/BooksAPI.js +++ b/src/BooksAPI.js @@ -32,6 +32,16 @@ export const update = (book, shelf) => body: JSON.stringify({ shelf }) }).then(res => res.json()) + export const addBook = (book, shelf) => + fetch(`${api}/books/${book.id}`, { + method: 'POST', + headers: { + ...headers, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ shelf }) + }).then(res => res.json()) + export const search = (query) => fetch(`${api}/search`, { method: 'POST', diff --git a/src/Components/Search.js b/src/Components/Search.js index 9e6cd6bd02..5f4baa00c2 100644 --- a/src/Components/Search.js +++ b/src/Components/Search.js @@ -2,6 +2,7 @@ import React from 'react' import '../App.css' import { Link } from 'react-router-dom' import * as BooksAPI from '../BooksAPI' +import SearchBooks from './SearchBooks' export default class Search extends React.Component { constructor(props) { @@ -44,31 +45,14 @@ render() { const { query, searchBooks } = this.state const bookList = searchBooks !== [] ? searchBooks.map((booksMan, index) => { - const noThumb = booksMan.imageLinks !== undefined ? booksMan.imageLinks.smallThumbnail : 'https://getuikit.com/v2/docs/images/placeholder_600x400.svg' - const ifMultipleAuthors = booksMan.authors !== undefined ? booksMan.authors.length === 1 ? booksMan.authors : booksMan.authors.map((writers, index) => { return
        {writers}
        }) : null return ( -
      1. -
        -
        -
        -
        - -
        -
        -
        {booksMan.title}
        -
        {ifMultipleAuthors}
        -
        -
      2. +
        + +
        ) - }) : null + }) :

        No books Match Search Criteria

        return (
        diff --git a/src/Components/SearchBooks.js b/src/Components/SearchBooks.js new file mode 100644 index 0000000000..c30d09f4ea --- /dev/null +++ b/src/Components/SearchBooks.js @@ -0,0 +1,67 @@ +import React from 'react' +import '../App.css' +import * as BooksAPI from '../BooksAPI' + +export default class SearchBooks extends React.Component { + constructor(props) { + super(props); + this.state = { + value: 'none', + currentBook: null + }; + + + this.handleChange = this.handleChange.bind(this); + } + +componentDidMount() { + Object.assign(this.props.searchList, {shelf: "none"}); + this.setState({ + currentBook: this.props.searchList + },() => console.log(this.state)) +} + +changeShelf = (book, shelf) => { + BooksAPI.update(book, shelf).then(console.log('it worked')) + } + +handleChange(event) { + this.setState({ + value: event.target.value + }, + () => { + this.changeShelf(this.state.currentBook, this.state.value) + }); + } + + render() { + const {searchList } = this.props + const noThumb = searchList.imageLinks !== undefined ? searchList.imageLinks.smallThumbnail : 'https://getuikit.com/v2/docs/images/placeholder_600x400.svg' + const ifMultipleAuthors = searchList.authors !== undefined ? searchList.authors.length === 1 ? searchList.authors : searchList.authors.map((writers, index) => { return
        {writers}
        }) : null + + return ( +
        + { +
      3. +
        +
        +
        +
        + +
        +
        +
        {searchList.title}
        +
        {ifMultipleAuthors}
        +
        +
      4. + } +
        + ) + } + } \ No newline at end of file From 010cb39c550714ca7615659c468d267202847ca0 Mon Sep 17 00:00:00 2001 From: Steven Snyder Date: Sat, 9 May 2020 17:01:29 -0400 Subject: [PATCH 07/10] updated readme --- README.md | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index ce4ea2eb85..0fae566af9 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,10 @@ # MyReads Project -This is the starter template for the final assessment project for Udacity's React Fundamentals course. The goal of this template is to save you time by providing a static example of the CSS and HTML markup that may be used, but without any of the React code that is needed to complete the project. If you choose to start with this template, your job will be to add interactivity to the app by refactoring the static code in this template. - -Of course, you are free to start this project from scratch if you wish! Just be sure to use [Create React App](https://github.com/facebookincubator/create-react-app) to bootstrap the project. - -## TL;DR - -To get started developing right away: - +To get started developing or using this repository: +* Git clone into the directory of your choice * install all project dependencies with `npm install` * start the development server with `npm start` +* Valid search terms include: 'Android', 'Art', 'Artificial Intelligence', 'Astronomy', 'Austen', 'Baseball', 'Basketball', 'Bhagat', 'Biography', 'Brief', 'Business', 'Camus', 'Cervantes', 'Christie', 'Classics', 'Comics', 'Cook', 'Cricket', 'Cycling', 'Desai', 'Design', 'Development', 'Digital Marketing', 'Drama', 'Drawing', 'Dumas', 'Education', 'Everything', 'Fantasy', 'Film', 'Finance', 'First', 'Fitness', 'Football', 'Future', 'Games', 'Gandhi', 'Homer', 'Horror', 'Hugo', 'Ibsen', 'Journey', 'Kafka', 'King', 'Lahiri', 'Larsson', 'Learn', 'Literary Fiction', 'Make', 'Manage', 'Marquez', 'Money', 'Mystery', 'Negotiate', 'Painting', 'Philosophy', 'Photography', 'Poetry', 'Production', 'Programming', 'React', 'Redux', 'River', 'Robotics', 'Rowling', 'Satire', 'Science Fiction', 'Shakespeare', 'Singh', 'Swimming', 'Tale', 'Thrun', 'Time', 'Tolstoy', 'Travel', 'Ultimate', 'Virtual Reality', 'Web Development', 'iOS' ## What You're Getting ```bash @@ -33,8 +28,6 @@ To get started developing right away: └── index.js # You should not need to modify this file. It is used for DOM rendering only. ``` -Remember that good React design practice is to create new JS files for each component and use import/require statements to include them where they are needed. - ## Backend Server To simplify your development process, we've provided a backend server for you to develop against. The provided file [`BooksAPI.js`](src/BooksAPI.js) contains the methods you will need to perform necessary operations on the backend: @@ -84,9 +77,3 @@ The backend API uses a fixed set of cached search results and is limited to a pa ## Create React App This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app). You can find more information on how to perform common tasks [here](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md). - -## Contributing - -This repository is the starter code for _all_ Udacity students. Therefore, we most likely will not accept pull requests. - -For details, check out [CONTRIBUTING.md](CONTRIBUTING.md). From 19b88f1b281f3b6950062063c14458484ff13ced Mon Sep 17 00:00:00 2001 From: Steven Snyder Date: Sun, 10 May 2020 13:25:28 -0400 Subject: [PATCH 08/10] updated functionality on search.js to include prop to pass value of shelf to searchbooks.js --- src/App.js | 46 +++++++++++++++++------------------ src/BooksAPI.js | 1 - src/Components/Search.js | 23 ++++++++++++------ src/Components/SearchBooks.js | 6 ++--- 4 files changed, 42 insertions(+), 34 deletions(-) diff --git a/src/App.js b/src/App.js index e37abb9af8..95841cb2a7 100644 --- a/src/App.js +++ b/src/App.js @@ -3,7 +3,7 @@ import BooksList from './Components/BooksList' import Search from './Components/Search' import './App.css' import { Route } from 'react-router-dom' -import * as BooksAPI from './BooksAPI' +// import * as BooksAPI from './BooksAPI' export default class App extends React.Component { state = { @@ -14,28 +14,28 @@ export default class App extends React.Component { showSearchPage: false } - componentDidMount() { - BooksAPI.getAll() - .then((books) => { - this.setState(() => ({ - books - })) - }).then(() => { - this.setState({ - currentlyReading: Object.values(this.state.books).filter((smoke) => ( - smoke.shelf === 'currentlyReading' - )), - read: Object.values(this.state.books).filter((smoke) => ( - smoke.shelf === 'read' - )), - wantToRead: Object.values(this.state.books).filter((smoke) => ( - smoke.shelf === 'wantToRead' - )) - }) - }).then(() => { - console.log(this.state) - }) - } + // componentDidMount() { + // BooksAPI.getAll() + // .then((books) => { + // this.setState(() => ({ + // books + // })) + // }).then(() => { + // this.setState({ + // currentlyReading: Object.values(this.state.books).filter((smoke) => ( + // smoke.shelf === 'currentlyReading' + // )), + // read: Object.values(this.state.books).filter((smoke) => ( + // smoke.shelf === 'read' + // )), + // wantToRead: Object.values(this.state.books).filter((smoke) => ( + // smoke.shelf === 'wantToRead' + // )) + // }) + // }).then(() => { + // console.log(this.state) + // }) + // } render() { return ( diff --git a/src/BooksAPI.js b/src/BooksAPI.js index 199e7a01cb..e2daab231e 100644 --- a/src/BooksAPI.js +++ b/src/BooksAPI.js @@ -52,7 +52,6 @@ export const search = (query) => body: JSON.stringify({ query }) }).then(res => res.json()) .then((data) => { - console.log(data.books) if (data.books.error === 'empty query') { return [] } else { diff --git a/src/Components/Search.js b/src/Components/Search.js index 5f4baa00c2..5d754dab66 100644 --- a/src/Components/Search.js +++ b/src/Components/Search.js @@ -9,14 +9,18 @@ export default class Search extends React.Component { super(props); this.state = { searchBooks: [], - query: '' + query: '', + books: [] }; } componentDidMount() { - this.setState({ - books: this.props.books - }) + BooksAPI.getAll() + .then((books) => { + this.setState(() => ({ + books + })) + }) } updateQuery = (query) => { @@ -27,7 +31,7 @@ updateQuery = (query) => { })) } else { this.setState(() => ({ - query: query.trim() + query: query }), () => BooksAPI.search(this.state.query) .then((newBooks) => @@ -43,9 +47,14 @@ clearQuery = () => { render() { - const { query, searchBooks } = this.state + const { query, searchBooks, books } = this.state const bookList = searchBooks !== [] ? searchBooks.map((booksMan, index) => { - + books.forEach(element => { + if (element.title.toLowerCase().replace(" ", "") === booksMan.title.toLowerCase().replace(" ", "")) { + Object.assign(booksMan, {shelf: element.shelf}); + } + }); + return (
        diff --git a/src/Components/SearchBooks.js b/src/Components/SearchBooks.js index c30d09f4ea..097628ddfa 100644 --- a/src/Components/SearchBooks.js +++ b/src/Components/SearchBooks.js @@ -15,10 +15,10 @@ export default class SearchBooks extends React.Component { } componentDidMount() { - Object.assign(this.props.searchList, {shelf: "none"}); this.setState({ - currentBook: this.props.searchList - },() => console.log(this.state)) + currentBook: this.props.searchList, + value: this.props.searchList.shelf + }) } changeShelf = (book, shelf) => { From de133d64b8adb09cbc923ac0b800832c39f6fa2b Mon Sep 17 00:00:00 2001 From: Steven Snyder Date: Sun, 10 May 2020 13:32:21 -0400 Subject: [PATCH 09/10] updated readme --- README.md | 48 ++++++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 0fae566af9..b0300dbc8d 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,24 @@ -# MyReads Project +# MyReads Project Overview + +In the MyReads project, you'll create a bookshelf app that allows you to select and categorize books you have read, are currently reading, or want to read. The project emphasizes using React to build the application and provides an API server and client library that you will use to persist information as you interact with the application. + + +App Functionality In this application: +The main page displays a list of "shelves" (i.e. categories), each of which contains a number of books. The three shelves are: +Read, Currently Reading and Want to Read. + +There is also a second search page that includes an API call in order to add books to your collection under the title of your choice if you are currently reading, read or want to read so you can keep track of your collection. + +The API is restricted to the following search terms: +'Android', 'Art', 'Artificial Intelligence', 'Astronomy', 'Austen', 'Baseball', 'Basketball', 'Bhagat', 'Biography', 'Brief', 'Business', 'Camus', 'Cervantes', 'Christie', 'Classics', 'Comics', 'Cook', 'Cricket', 'Cycling', 'Desai', 'Design', 'Development', 'Digital Marketing', 'Drama', 'Drawing', 'Dumas', 'Education', 'Everything', 'Fantasy', 'Film', 'Finance', 'First', 'Fitness', 'Football', 'Future', 'Games', 'Gandhi', 'Homer', 'Horror', 'Hugo', 'Ibsen', 'Journey', 'Kafka', 'King', 'Lahiri', 'Larsson', 'Learn', 'Literary Fiction', 'Make', 'Manage', 'Marquez', 'Money', 'Mystery', 'Negotiate', 'Painting', 'Philosophy', 'Photography', 'Poetry', 'Production', 'Programming', 'React', 'Redux', 'River', 'Robotics', 'Rowling', 'Satire', 'Science Fiction', 'Shakespeare', 'Singh', 'Swimming', 'Tale', 'Thrun', 'Time', 'Tolstoy', 'Travel', 'Ultimate', 'Virtual Reality', 'Web Development', 'iOS' + To get started developing or using this repository: * Git clone into the directory of your choice * install all project dependencies with `npm install` * start the development server with `npm start` -* Valid search terms include: 'Android', 'Art', 'Artificial Intelligence', 'Astronomy', 'Austen', 'Baseball', 'Basketball', 'Bhagat', 'Biography', 'Brief', 'Business', 'Camus', 'Cervantes', 'Christie', 'Classics', 'Comics', 'Cook', 'Cricket', 'Cycling', 'Desai', 'Design', 'Development', 'Digital Marketing', 'Drama', 'Drawing', 'Dumas', 'Education', 'Everything', 'Fantasy', 'Film', 'Finance', 'First', 'Fitness', 'Football', 'Future', 'Games', 'Gandhi', 'Homer', 'Horror', 'Hugo', 'Ibsen', 'Journey', 'Kafka', 'King', 'Lahiri', 'Larsson', 'Learn', 'Literary Fiction', 'Make', 'Manage', 'Marquez', 'Money', 'Mystery', 'Negotiate', 'Painting', 'Philosophy', 'Photography', 'Poetry', 'Production', 'Programming', 'React', 'Redux', 'River', 'Robotics', 'Rowling', 'Satire', 'Science Fiction', 'Shakespeare', 'Singh', 'Swimming', 'Tale', 'Thrun', 'Time', 'Tolstoy', 'Travel', 'Ultimate', 'Virtual Reality', 'Web Development', 'iOS' - -## What You're Getting -```bash -├── CONTRIBUTING.md -├── README.md - This file. -├── SEARCH_TERMS.md # The whitelisted short collection of available search terms for you to use with your app. -├── package.json # npm package manager file. It's unlikely that you'll need to modify this. -├── public -│   ├── favicon.ico # React Icon, You may change if you wish. -│   └── index.html # DO NOT MODIFY -└── src - ├── App.css # Styles for your app. Feel free to customize this as you desire. - ├── App.js # This is the root of your app. Contains static HTML right now. - ├── App.test.js # Used for testing. Provided with Create React App. Testing is encouraged, but not required. - ├── BooksAPI.js # A JavaScript API for the provided Udacity backend. Instructions for the methods are below. - ├── icons # Helpful images for your app. Use at your discretion. - │   ├── add.svg - │   ├── arrow-back.svg - │   └── arrow-drop-down.svg - ├── index.css # Global styles. You probably won't need to change anything here. - └── index.js # You should not need to modify this file. It is used for DOM rendering only. -``` - -## Backend Server - -To simplify your development process, we've provided a backend server for you to develop against. The provided file [`BooksAPI.js`](src/BooksAPI.js) contains the methods you will need to perform necessary operations on the backend: -* [`getAll`](#getall) -* [`update`](#update) -* [`search`](#search) +## The following queries are used in order to perform necessary calls in the application if you would like to modify: ### `getAll` @@ -72,7 +56,7 @@ search(query) * These books do not know which shelf they are on. They are raw results only. You'll need to make sure that books have the correct state while on the search page. ## Important -The backend API uses a fixed set of cached search results and is limited to a particular set of search terms, which can be found in [SEARCH_TERMS.md](SEARCH_TERMS.md). That list of terms are the _only_ terms that will work with the backend, so don't be surprised if your searches for Basket Weaving or Bubble Wrap don't come back with any results. +The backend API uses a fixed set of cached search results and is limited to a particular set of search terms, which can be found above That list of terms are the _only_ terms that will work with the backend, so don't be surprised if your searches for Basket Weaving or Bubble Wrap don't come back with any results. ## Create React App From e0460bee96439e42e0f4de6b9d4cb6e6e0a6172d Mon Sep 17 00:00:00 2001 From: Steven Snyder Date: Sun, 10 May 2020 13:41:52 -0400 Subject: [PATCH 10/10] added 404 page --- src/App.js | 29 +++++------------------------ src/Components/NoMatch.js | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 24 deletions(-) create mode 100644 src/Components/NoMatch.js diff --git a/src/App.js b/src/App.js index 95841cb2a7..61cf7f1865 100644 --- a/src/App.js +++ b/src/App.js @@ -2,8 +2,8 @@ import React from 'react' import BooksList from './Components/BooksList' import Search from './Components/Search' import './App.css' -import { Route } from 'react-router-dom' -// import * as BooksAPI from './BooksAPI' +import { Route,Switch } from 'react-router-dom' +import NoMatch from './Components/NoMatch' export default class App extends React.Component { state = { @@ -14,32 +14,11 @@ export default class App extends React.Component { showSearchPage: false } - // componentDidMount() { - // BooksAPI.getAll() - // .then((books) => { - // this.setState(() => ({ - // books - // })) - // }).then(() => { - // this.setState({ - // currentlyReading: Object.values(this.state.books).filter((smoke) => ( - // smoke.shelf === 'currentlyReading' - // )), - // read: Object.values(this.state.books).filter((smoke) => ( - // smoke.shelf === 'read' - // )), - // wantToRead: Object.values(this.state.books).filter((smoke) => ( - // smoke.shelf === 'wantToRead' - // )) - // }) - // }).then(() => { - // console.log(this.state) - // }) - // } render() { return (
        + ( @@ -49,6 +28,8 @@ render() { books={this.state.books} /> )} /> + +
        ) } diff --git a/src/Components/NoMatch.js b/src/Components/NoMatch.js new file mode 100644 index 0000000000..eb70313d41 --- /dev/null +++ b/src/Components/NoMatch.js @@ -0,0 +1,14 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; + +export default function NoMatch() { + return ( +
        +

        404!

        +

        PAGE NOT FOUND

        +

        + Go to Home +

        +
        + ) +} \ No newline at end of file