Start learning free

LESSON 34 OF 173 · BACKEND: YOUR FIRST API

Project: The Shop So Far

Practice

This project puts most of what you have built so far into one new route. A product page shows the product's rating: the average of the stars in its reviews. The rating belongs to one product, so it gets a nested path under that product, just like the reviews: /products/1/rating.

An average in JavaScript: collect the numbers in an array, add them up with a loop, then divide the total by the array's length. Math.round(... * 100) / 100 keeps 2 decimal places, the way the /stats route does for the prices.

const temperatures = [20, 23, 22];
let total = 0;
for (const temperature of temperatures) {
  total += temperature;
}
const average = Math.round((total / temperatures.length) * 100) / 100;
console.log(average);   // 21.67

No numbers, no average: when the array is empty, its length is 0. In JavaScript, 0 divided by 0 doesn't crash: it gives NaN, "not a number", and JSON has no way to write NaN. So check for an empty array first and answer null, JSON's "no value". A product with no reviews still exists, so it gets 200 with a null rating. A product that isn't in products gets 404, as always.

The test requests, in this order, and what your code must answer:

GET /products/1/rating    →  200  {"product_id": 1, "rating": 4.5}
GET /products/3/rating    →  200  {"product_id": 3, "rating": 2}
GET /products/2/rating    →  200  {"product_id": 2, "rating": null}
GET /products/99/rating   →  404  {"error": "Product not found"}
POST /products/1/reviews  {"stars": 5, "text": "My favourite mug"}  →  201  (the review)
GET /products/1/rating    →  200  {"product_id": 1, "rating": 4.67}
POST /products/2/reviews  {"stars": 3, "text": "Thin pages"}  →  201  (the review)
GET /products/2/rating    →  200  {"product_id": 2, "rating": 3}
DELETE /products/3        →  204  (empty)
GET /products/3/rating    →  404  {"error": "Product not found"}

Your task: just above the last line, app.use(notFound);, add a route for GET /products/:productId/rating. It answers the product_id and a rating: the average of the product's stars rounded to 2 places, or null when the product has no reviews. When no product has that id, it answers 404 with "Product not found".


Assignment
Follow the Coding Tutorial to add the /rating route just above app.use(notFound);: find the product, collect the stars of its reviews, and answer their rounded average, or a null rating when there are none.


Hint
Copy the shape of the GET route for the reviews to read the id, find the product and answer the 404 with errorResponse, and the shape of the /stats route for the array, the empty check and the rounded average. Check for an empty array before you divide.


STEP 1 OF 12
    Ctrl + Enter to check