Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Muhammadbugaje/trustride/llms.txt

Use this file to discover all available pages before exploring further.

Riders are the primary consumers on TrustRide. They search for intercity routes, select individual seats on a visual seat map, transfer payment to the driver’s bank account, and track confirmation status in their personal dashboard. All rider actions are scoped to users with role=rider.

Registration

Riders register at POST /register/ by submitting a form with the following required fields:
FieldTypeNotes
emailEmailFieldUsed as the username for login. Must be unique.
phoneCharFieldMust be a valid Nigerian number (e.g., 08012345678 or +2348012345678).
first_nameCharFieldMax 100 characters.
last_nameCharFieldMax 100 characters.
genderCharFieldmale or female. Used to enforce driver-set gender restrictions on trips.
roleCharFieldMust be set to rider at registration.
passwordStandard Django password with hashing.
After successful registration a welcome email is dispatched. If the email service is unavailable, the account is still created and the failure is logged without interrupting the flow.
Riders do not need email verification to search for trips, but the dashboard displays a prompt until is_email_verified is True. Profile completeness (first_name, last_name, phone, gender all non-empty) is required to place bookings.

Rider Dashboard

GET /rider/dashboard/ — requires login and role=rider. The rider dashboard is the central hub for all rider activity. It displays:
  • Upcoming trips — bookings with status in reserved or confirmed and a future departure date.
  • Booking history — all bookings ordered by date, with status badges.
  • Stats summary — total trips taken, total amount spent, and count of pending refund requests.
  • Quick actions — links to search trips, view all bookings, and manage refunds.
  • Ambassador panel — if the rider is also an active ambassador, their trip approvals and pending requests are shown in the same view.
# Key context variables passed to rider/dashboard.html
{
    'recent_bookings':    bookings[:5],
    'total_trips':        bookings.count(),
    'upcoming_trips':     ...,  # count of future confirmed/reserved
    'total_spent':        ...,  # sum of confirmed booking prices
    'pending_refunds':    ...,  # count of requested refunds
    'is_verified':        user.is_email_verified,
    'is_profile_complete': user.is_profile_complete(),
}

Booking Flow

Riders book seats through a multi-step process initiated from the trip detail page.
1

Search for a Trip

Use the homepage search form or GET /search/ with query parameters origin, destination, departure_date, and passengers. Only published trips with available_seats >= passengers are returned. Gender-restricted trips are filtered automatically for logged-in users.
2

Select a Seat

Open the trip detail page at /trip/<uuid>/. The page renders a visual seat map built from the vehicle’s seat_layout JSON. Each seat is labelled (e.g., A1, B2) and coloured to indicate availability. Booked seats (status reserved, pending_verification, or confirmed) are disabled.
3

Submit Booking

POST /book/<uuid>/ with seat_ids (comma-separated seat IDs) or a single seat_id. The server places a row-level lock on the trip, checks availability, and creates one Booking record per seat with status=reserved. Available seat count is decremented atomically.
4

Upload Payment Receipt

A payment instructions screen is shown immediately after booking at /booking-success/<uuid>/. The rider transfers the exact amount to the bank account listed and uploads a receipt screenshot in the booking chat (using the 📷 icon). The booking advances to pending_verification.
5

Await Driver Confirmation

The driver reviews the receipt and calls POST /booking/<uuid>/approve/. The booking moves to confirmed and the rider receives an email with a QR-code ticket and an in-app notification.
Each seat reservation expires after a configurable window (default 30 minutes, controlled by the booking_expiry_minutes app setting). If payment is not uploaded before expiry, the status advances to expired and the seat is released back to the pool automatically.
For full details on booking statuses and the payment verification flow, see the Bookings reference.

My Bookings

GET /my-bookings/ lists all bookings for the logged-in rider, with tab-based filtering:
FilterShows
allEvery booking regardless of status
upcomingreserved or confirmed bookings with a future departure date
pendingBookings awaiting driver verification (pending_verification)
confirmedConfirmed bookings
pastCompleted, cancelled, expired, or refunded bookings
Each row links to GET /booking/<uuid>/ for the full booking detail, which includes the payment receipt chat, trip info, and available actions (cancel, refund request, or rate).

Refund Requests

Riders can request a refund on any confirmed booking before the departure date.
  • View refundsGET /rider/refunds/ shows all refund requests with their status (requested, approved, rejected), alongside a list of refundable bookings not yet submitted.
  • Submit a refundPOST /booking/<uuid>/refund/ with a reason field. A Refund record is created with status=requested and the driver is notified.
  • Outcome — the driver approves at POST /refund/<uuid>/approve/ or rejects at POST /refund/<uuid>/reject/. On approval, the seat is released and the rider receives a confirmation email.

Rating a Driver

After a trip is marked completed, a rider can rate the driver once. GET /booking/<uuid>/rate/ — renders a 1–5 star rating form with an optional written review.
POST /booking/<uuid>/rate/ — creates a Rating record linking the trip, reviewer (rider), and reviewee (driver). Each reviewer can submit only one rating per trip (unique_together = ['trip', 'reviewer', 'reviewee']).
# Rating model
class Rating(UUIDModel, TimeStampedModel):
    trip        = models.ForeignKey(Trip, ...)
    reviewer    = models.ForeignKey(User, related_name='reviews_given')
    reviewee    = models.ForeignKey(User, related_name='reviews_received')
    rating      = models.IntegerField(choices=RATING_CHOICES)   # 1–5
    review_text = models.TextField(blank=True)
Driver average ratings are computed with Avg('rating') and displayed on the trip detail page and driver profile.

Future Trip Interest

If no trip exists for a rider’s desired route and date, they can register interest so TrustRide notifies them when a matching trip is published. GET/POST /interest/future-interest/ — riders submit:
FieldDescription
originDeparture city
destinationArrival city
preferred_dateMust be a future date
time_of_daymorning (6 AM–12 PM), afternoon (12–6 PM), or evening (6–12 AM)
genderGender preference for the trip: anyone, male, or female
The FutureTripInterest model enforces a unique_together constraint on [user, origin, destination, preferred_date], preventing duplicate interests for the same route and day. When a matching trip is published, is_notified is set to True and notified_at is recorded.
Riders can view all other users’ future trip interests at /interest/all/. Drivers use this page to gauge demand and decide which routes to publish next.

Waitlist

When a trip is fully booked (available_seats = 0), riders can join a position-based waitlist. POST /join-waitlist/<uuid>/ — creates a WaitlistEntry with:
  • queue_position — automatically assigned as current_count + 1
  • status — starts as pending
  • expires_at — defaults to 30 minutes from entry creation
The waitlist capacity equals the vehicle’s seating_capacity. When a seat becomes available (booking cancelled or refunded), the next rider in queue is notified automatically via notify_next_in_waitlist().
# WaitlistEntry model (simplified)
class WaitlistEntry(UUIDModel, TimeStampedModel):
    user           = models.ForeignKey(User, related_name='waitlist_entries')
    trip           = models.ForeignKey(Trip, related_name='waitlist_entries')
    queue_position = models.IntegerField(validators=[MinValueValidator(1)])
    status         = models.CharField(choices=['pending', 'notified', 'claimed', 'expired', 'assigned'])
    expires_at     = models.DateTimeField()

Next of Kin

For safety, TrustRide stores next-of-kin information in the UserProfile model. Riders fill this in at /profile/edit/.
FieldDescription
next_of_kin_nameFull name of the emergency contact
next_of_kin_phonePhone number of the emergency contact
next_of_kin_relationshipRelationship to the rider (e.g., parent, spouse)
Next-of-kin information is only visible to TrustRide administrators and is never shared with drivers or ambassadors.

Build docs developers (and LLMs) love