DEV Community

Kofi Amo-Antwi for Inside GusLift

Posted on

Building a Trust Layer: Ratings in GusLift (Current State)

GusLift is a campus rideshare app for students at our university. After shipping ride history and profile photos, the next obvious gap was trust: before someone gets in a car (or offers a seat), they want a signal that the other person has shown up and behaved well on past trips.

Data model: one row per person, per ride
Ratings live in Supabase in a ratings table keyed by the ride and who is giving the rating. Conceptually each row stores: which ride it was, who rated (from_user_id), who was rated (to_user_id), and an integer score from 1 to 5.

On the API side, POST /api/ratings validates that payload and upserts on conflict so a user can adjust their score for the same ride without creating duplicates. GET /api/ratings?user_id=… aggregates every rating received by that user and returns a rounded average plus a count, which is what powers the driver’s headline number on the home screen.

Ride history as the glue
The ride history endpoint already loads completed trips, riders, drivers, and cars. It now also pulls all ratings for those ride IDs and, for the currently logged-in user, attaches my_rating: the score they already submitted for that trip, if any.

That single field unlocks two different UX needs:

Lists can show a small “you rated this 4/5” pill without a second round-trip per row.
Home can ask “do you have any completed rides where you still have not rated?” by scanning history for the first ride with my_rating == null.
So history stays the source of truth for “what happened,” and ratings are a thin join on top.

Rider experience: celebrate, then ask
On the rider side, the flow is deliberately emotional before it is transactional. When a ride completes, a full-screen “Ride completed” overlay gives a moment of closure. After it dismisses, a bottom toast slides in: driver name, five stars, optional skip, and a link to ride details.

The toast is time-limited (progress bar + auto-dismiss), posts to POST /api/ratings on star tap, and shows a short thank-you state before sliding away. If the user skipped the prompt earlier, a best-effort check against ride history can still surface the toast for the oldest unrated completed trip so people are not stuck forever.

Ride detail (from history or from the toast’s “view details” path) also includes an inline star control so a rating can be submitted or changed later, using the same API.

Driver experience: reputation, not nagging (for now)
Drivers see their aggregate rating and count on the driver home hero when the GET endpoint returns data. History and detail screens can show the driver’s own past rating for a trip where that applies.

The backend is symmetric (any user can rate any counterparty on a ride), but the mobile prompts are currently centered on riders rating drivers. Reciprocal “rate your rider” flows are a natural follow-up now that POST and history enrichment are in place.

Top comments (0)