From 7bba62696ac066d3428693d61f04a52220cdb038 Mon Sep 17 00:00:00 2001 From: Gitte Beckmann Date: Wed, 4 Dec 2024 16:39:49 +0100 Subject: [PATCH 1/5] - added endpoint books and filter option title --- package.json | 2 +- server.js | 28 ++++++++++++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index f93ddb524..5b9297a64 100644 --- a/package.json +++ b/package.json @@ -16,4 +16,4 @@ "express": "^4.17.3", "nodemon": "^3.0.1" } -} +} \ No newline at end of file diff --git a/server.js b/server.js index b5fec6fe2..7a6714bd2 100644 --- a/server.js +++ b/server.js @@ -1,13 +1,6 @@ import express from "express"; import cors from "cors"; - -// If you're using one of our datasets, uncomment the appropriate import below -// to get started! -// import avocadoSalesData from "./data/avocado-sales.json"; -// import booksData from "./data/books.json"; -// import goldenGlobesData from "./data/golden-globes.json"; -// import netflixData from "./data/netflix-titles.json"; -// import topMusicData from "./data/top-music.json"; +import booksData from "./data/books.json"; // Defines the port the app will run on. Defaults to 8080, but can be overridden // when starting the server. Example command to overwrite PORT env variable value: @@ -24,7 +17,26 @@ app.get("/", (req, res) => { res.send("Hello Technigo!"); }); +app.get('/books', (req, res) => { + const titleQuery = req.query.title; + + if (!titleQuery) { + return res.status(400).json({ error: "Title query parameter is required" }); + } + + const filteredBooks = booksData.filter(book => + book.title.toLowerCase().includes(titleQuery.toLowerCase()) + ); + + if (filteredBooks.length === 0) { + return res.status(404).json({ error: "No books found with the given title" }); + } + + res.json(filteredBooks); +}); + // Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); }); + From f502b73ec604b892c0640c477a23dd67fce98f54 Mon Sep 17 00:00:00 2001 From: Gitte Beckmann Date: Wed, 4 Dec 2024 17:49:40 +0100 Subject: [PATCH 2/5] - added enpoint authors --- server.js | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/server.js b/server.js index 7a6714bd2..6ed1f1829 100644 --- a/server.js +++ b/server.js @@ -17,7 +17,8 @@ app.get("/", (req, res) => { res.send("Hello Technigo!"); }); -app.get('/books', (req, res) => { +// title +app.get("/books/title", (req, res) => { const titleQuery = req.query.title; if (!titleQuery) { @@ -31,10 +32,48 @@ app.get('/books', (req, res) => { if (filteredBooks.length === 0) { return res.status(404).json({ error: "No books found with the given title" }); } - res.json(filteredBooks); }); +app.get("/books/authors", (req, res) => { + const authorQuery = req.query.author; + + if (!authorQuery) { + return res.status(400).json({ error: "Author query parameter is required" }); + } + + // Filtere Bücher basierend auf dem Autor + const filteredBooks = booksData.filter(book => { + if (!book.authors) return false; // Verhindere Fehler, wenn keine Autoren vorhanden sind + const authorsArray = book.authors.split("-").map(author => author.trim().toLowerCase()); + return authorsArray.some(author => author.includes(authorQuery.toLowerCase())); + }); + + if (filteredBooks.length === 0) { + return res.status(404).json({ error: "No books found with the given author" }); + } + + res.status(200).json(filteredBooks); // Antwort mit gefilterten Büchern +}); + + +// ISBN +app.get("/books/:isbn", (req, res) => { + const isbn = req.params.isbn + + const book = booksData.find(book => book.isbn === +isbn) + res.json(book); { + if (book) { + res.status(200).json(book) + } else { + res.status(404).send("no book found with that ISBN") + } + } +}) + +// Author + + // Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); From d4582e9b694734ae281d9d4156e3ee908ec71639 Mon Sep 17 00:00:00 2001 From: Gitte Beckmann Date: Thu, 5 Dec 2024 07:26:18 +0100 Subject: [PATCH 3/5] - added list with endpoints --- package.json | 3 ++- server.js | 25 +++++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 5b9297a64..fcbf92020 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@babel/preset-env": "^7.16.11", "cors": "^2.8.5", "express": "^4.17.3", + "express-list-endpoints": "^7.1.1", "nodemon": "^3.0.1" } -} \ No newline at end of file +} diff --git a/server.js b/server.js index 6ed1f1829..a342546c2 100644 --- a/server.js +++ b/server.js @@ -7,6 +7,7 @@ import booksData from "./data/books.json"; // PORT=9000 npm start const port = process.env.PORT || 8080; const app = express(); +const listEndpoints = require("express-list-endpoints"); // Add middlewares to enable cors and json body parsing app.use(cors()); @@ -14,7 +15,15 @@ app.use(express.json()); // Start defining your routes here app.get("/", (req, res) => { - res.send("Hello Technigo!"); + const endpoints = listEndpoints(app); + res.json({ + message: "API Documentation", + endpoints: endpoints + }); +}); + +app.get("/books", (req, res) => { + res.json(booksData); }); // title @@ -35,6 +44,7 @@ app.get("/books/title", (req, res) => { res.json(filteredBooks); }); +// Author app.get("/books/authors", (req, res) => { const authorQuery = req.query.author; @@ -42,9 +52,9 @@ app.get("/books/authors", (req, res) => { return res.status(400).json({ error: "Author query parameter is required" }); } - // Filtere Bücher basierend auf dem Autor const filteredBooks = booksData.filter(book => { - if (!book.authors) return false; // Verhindere Fehler, wenn keine Autoren vorhanden sind + if (!book.authors) return false; + const authorsArray = book.authors.split("-").map(author => author.trim().toLowerCase()); return authorsArray.some(author => author.includes(authorQuery.toLowerCase())); }); @@ -53,10 +63,9 @@ app.get("/books/authors", (req, res) => { return res.status(404).json({ error: "No books found with the given author" }); } - res.status(200).json(filteredBooks); // Antwort mit gefilterten Büchern + res.status(200).json(filteredBooks); }); - // ISBN app.get("/books/:isbn", (req, res) => { const isbn = req.params.isbn @@ -71,11 +80,7 @@ app.get("/books/:isbn", (req, res) => { } }) -// Author - - // Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); -}); - +}); \ No newline at end of file From c23efa09a54999033396153d5646b4e39e2a7d63 Mon Sep 17 00:00:00 2001 From: Gitte Beckmann Date: Thu, 5 Dec 2024 08:05:20 +0100 Subject: [PATCH 4/5] - added popular books and restructured the /books endpoint so that users can search for author and title --- server.js | 51 ++++++++++++++++++++------------------------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/server.js b/server.js index a342546c2..c72ca0d39 100644 --- a/server.js +++ b/server.js @@ -17,50 +17,40 @@ app.use(express.json()); app.get("/", (req, res) => { const endpoints = listEndpoints(app); res.json({ - message: "API Documentation", + message: "Welcome to the Book API!", endpoints: endpoints }); }); -app.get("/books", (req, res) => { - res.json(booksData); +// Popular books with rating >4 +app.get("/books/popular", (req, res) => { + const popularBooks = booksData.filter(book => book.average_rating && parseFloat(book.average_rating) > +4) + res.status(200).json(popularBooks) }); -// title -app.get("/books/title", (req, res) => { - const titleQuery = req.query.title; - - if (!titleQuery) { - return res.status(400).json({ error: "Title query parameter is required" }); - } +// author and title +app.get("/books", (req, res) => { + const { title, author } = req.query; - const filteredBooks = booksData.filter(book => - book.title.toLowerCase().includes(titleQuery.toLowerCase()) - ); + let filteredBooks = booksData; - if (filteredBooks.length === 0) { - return res.status(404).json({ error: "No books found with the given title" }); + if (title) { + filteredBooks = filteredBooks.filter(book => + book.title.toLowerCase().includes(title.toLowerCase()) + ); } - res.json(filteredBooks); -}); -// Author -app.get("/books/authors", (req, res) => { - const authorQuery = req.query.author; + if (author) { + filteredBooks = filteredBooks.filter(book => { + if (!book.authors) return false; - if (!authorQuery) { - return res.status(400).json({ error: "Author query parameter is required" }); + const authorsArray = book.authors.split("-").map(author => author.trim().toLowerCase()); + return authorsArray.some(auth => auth.includes(author.toLowerCase())); + }); } - const filteredBooks = booksData.filter(book => { - if (!book.authors) return false; - - const authorsArray = book.authors.split("-").map(author => author.trim().toLowerCase()); - return authorsArray.some(author => author.includes(authorQuery.toLowerCase())); - }); - if (filteredBooks.length === 0) { - return res.status(404).json({ error: "No books found with the given author" }); + return res.status(404).json({ error: "No books found matching the criteria" }); } res.status(200).json(filteredBooks); @@ -69,7 +59,6 @@ app.get("/books/authors", (req, res) => { // ISBN app.get("/books/:isbn", (req, res) => { const isbn = req.params.isbn - const book = booksData.find(book => book.isbn === +isbn) res.json(book); { if (book) { From 2d2e215485524e17432b93120a2a201a3c24696d Mon Sep 17 00:00:00 2001 From: Gitte Beckmann Date: Thu, 5 Dec 2024 08:17:57 +0100 Subject: [PATCH 5/5] - added link for live view --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5241826b3..728ec9938 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,4 @@ Describe how you approached to problem, and what tools and techniques you used t ## View it live -Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. +https://project-express-api-17pi.onrender.com