← Build · all briefsBrief 1 · after "Connect the market" · demo next class
Brief 1

Review wall

Every card gets a Reviews button. It opens a dialog with that stall's reviews, newest first, and a form to add one. The server validates; the dialog shows what it says. ★☆☆

“Four and a half stars from two people. Who are they, and what did they eat?”

You'll demo (next class): open Taco Bike's reviews, post one, see it at the top with the server's id. Post one that's too short: the message appears under the text field and nothing you typed is lost. Delete the review you just wrote.

The core (start in class if you've connected, the minimum for the demo)

Four things, on top of your connected market. They count when they work with chaos on (control page).

The full feature (finish at home)

What has to work for the demo next class, not how. The core above is part of it.

Requests

  • GET /api/stalls/:id/reviews when the dialog opens, for the stall that was clicked.
  • POST a review as JSON; rating is a number.
  • DELETE /api/reviews/:id for reviews posted from this browser (remember their ids). The server doesn't check ownership (a course simplification): a real API would, because a client-side rule is no rule.

States

  • Loading, empty ("No reviews yet: be the first"), error and ready, inside the dialog.
  • After a 201: the server's review at the top, the form cleared, the card's rating and count updated.
  • The submit button is disabled while posting.

Errors

  • 422: each field's message under its field, aria-invalid on the input.
  • Any other failure: a sentence in the dialog; the form keeps its text.
  • Opening a second stall while the first one's reviews are loading never shows the first stall's reviews.

New tool: <dialog> and showModal(): a modal with focus handling and Esc built in.

The endpoints you need

MethodPathAnswers
GET/api/stalls/:id/reviews200 · array, newest first · 404
POST/api/stalls/:id/reviews201 + Location · 400 · 415 · 422 { fields } · 404
DELETE/api/reviews/:id204 · 404
GET/api/stalls/:id200 · the stall with a fresh rating and reviewCount

Edge cases (with chaos on, minutes 38–43)

Stretch, if you're done early

Stuck? One hint at a time

Network panel first: is the request sent, with what, and what came back? Then a hint.

Hint 1

Where does the dialog find out which stall it's for? The click happened on a card that render() may have replaced since.

Hint 2

After a POST, which number on the card is now wrong, and who knows the right value?

Hint 3

Two requests for two different stalls are in flight. The slower one arrives last. What does the dialog show?

Traps

Open when something behaves strangely

Before you start

This brief assumes Connect the market is done: api.js works, the stalls come from the API, loading and errors are handled. Then: Click a card's button: GET …/reviews appears in the Network panel with a 200, and the JSON is in the console.

Demo · next class, 3 minutes

Your 3 minutes
  1. The happy path, with the Network panel open next to the page.
  2. Chaos on: the loading state, one failure, and how the page recovers.
  3. One request in code: the call, the status codes you handle, where the state changes.
  4. One bug you hit, and the panel or the message that showed it to you.