/googly-search

Search and save any books using Google's book API

Primary LanguageJavaScript

License: MIT

Googly-Search

Our application leverages Google Books API to bring back the most important content from your favorite books. You can then save them into your own collection so you can reference them later.

Please checkout our application!

google-books-search

Table of Contents

  1. Technology
  2. Schema
  3. Utils
  4. React Components
  5. Usage & Features
  6. Installation
  7. License
  8. Future Development
  9. Contact Us



Technology

html   css   javascript   react   react bootstrap   bootstrap   atlas-mongoDB   mongoose   Node.js   npm   express   dotenv   heroku  



Here are the technologies and tools used to build this application.

Schema

Our book schema to store the google api response has 6 properties not including the _id that mongoose assigns.

var BookSchema = new Schema({
    name: {
        type: String,
    },
    author: {
        type: String,
    },
    publishedDate: {
        type: String
    },
    description: {
        type: String
    },
    image: {
        type: String,
    },
    link: {
        type: String,
        required: 'URL can\'t be empty',
    }
})

Utils

On the client side, we have these 4 utility functions to make an api call to our server.

  // Get book based on search
  getBooks: function(book) {
      return axios.get('https://www.googleapis.com/books/v1/volumes?q=' + book)
  },
  // Get list of saved books in database
  getSavedBooks: function() {
      return axios.get('/api/books')
  },
  // Save book to database
  saveBook: function(bookData) {
      return axios.post('/api/books', bookData)
      // Mongoose
  },
  // Delete book from database
  deleteBook: function(bookId) {
      return axios.delete('/api/books/' + bookId)
      //Mongoose 
  },

React Components

Here is our src folder directory with its many components and pages:

<!-- Within our 'client' folder: -->

src
├── components
│   ├── Book
│   │   └── Book.js
│   ├── Jumbotron
│   │   └── Jumbotron.js
│   ├── Main
│   │   └── Main.js
│   ├── Navbar
│   │   └── Navbar.js
│   ├── SavedBook
│   │   └── SavedBook.js
│   └── Search
│       └── Search.js
├── pages
│   └── Home.js
│   └── Saved.js
├── utils
│   └── API.js
├── App.js
├── index.css
├── index.js
└── registerServiceWorker.js

Usage & Features

Google Books API When calling on the API.getBooks we deconstructed the json response so later on downstream in our code it is easier to handle. If you look at about the middle section of the code snippet below you can see where we push in the deconstructed object into newData. Inside the object contains; name, author, publishedDate, description, image, link.

<!-- json deconstruction -->

  handleSearchbutton = () => {
  API.getBooks(this.state.search)
  .then(res => {
    const newData = [];
    console.log(res);
    res.data.items.forEach((book)=>{
      let imageURL;
      if(book.volumeInfo.imageLinks){
        imageURL = book.volumeInfo.imageLinks.thumbnail;
      }else{
        imageURL = "";
      }
      newData.push({
            name: book.volumeInfo.title,
            author: book.volumeInfo.authors[0],
            publishedDate: book.volumeInfo.publishedDate,
            description:book.volumeInfo.description,
            image: imageURL,
            link: book.selfLink
      });
    });
    this.setState({ books: newData })
  });
}

Here is a snippet of what the Google Books API response looks like before we deconstruct it. (not all fields are highlighted below)

api-google-books

MongoDB

We use MongoDB on the backend to store the user's Saved books where they can *view, add, and delete books from their Saved list. Shown below are our mongoose constructor functions:

<!-- Server-side API endpoints and mongoose constructor functions -->

router.get('/books', (req, res) => {
  Book.find({})
    .then(bookData => {
      res.status(200).json(bookData);
    })
    .catch(err => {
      res.status(500).json(err)
    })
});

router.post('/books', (req, res) => {
  Book.create(req.body)
    .then(bookData => {
      res.status(200).json(bookData);
    })
    .catch(err => {
      console.log(err)
      res.status(500).json(err)
    })
});

router.delete('/books/:id', async (req, res) => {
  Book.remove({ _id: req.params.id })
    .then(bookData => {
      res.status(200).json(bookData);
    })
    .catch(err => {
      console.log(err)
      res.status(500).json({ message: "Book not found" })
    })
});

Here you can see how a user's Saved books list and them deleting a book.

saved-delete

Installation

Download the project then run the command:

npm install

Start the App

Run the follwing command:

npm run start:dev

License

MIT License

Copyright (c) 2021 Jake Novelli, Cheng Tang, Liam Stewart, and Dylan Couzon

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Future Development

Some future development opportunities are:

  • onSubmit for the Search bar on the HomePage
  • Interactive confirmation that item is saved i.e. removing the card for Book when it is saved
  • Fix hero image sizing inside of Jumbotron

Contact Us

Please feel free to reach out to us or checkout our other individual works.

Jake Novelli

Dylan Couzon

Liam Stewart

Cheng Tang