Skip to content

Slice 4 (Module 03): Patient discovery API — list/search doctors + upcoming free slots #23

@mGasiorek998

Description

@mGasiorek998

What to build

Ship the public read endpoints that Module 04's patient-side discovery UI will consume. No UI in this slice — the PRD assigns the patient-facing pages to Module 04, but the API surface belongs in Module 03 alongside the schema it queries.

  • Fill in doctorContract with listDoctors and listUpcomingSlots.
  • GET /doctors?search= behind requireAuth() only: returns a flat array of { userId, firstName, lastName, specialization }. Empty or absent search returns all doctors. With search, applies a case-insensitive substring match (Postgres ILIKE '%term%') against any of first_name, last_name, specialization. No pagination.
  • GET /doctors/{doctorId}/slots?upcoming=true behind requireAuth() only: returns slots with status='free' and starts_at >= now() UTC, sorted ascending by starts_at. The upcoming=true query param is required for this slice; behaviour without it is undefined and may 400.
  • Use case + repository for both, encapsulating the search/filter SQL.

Acceptance criteria

  • GET /doctors (no search) returns all doctors as a flat array { userId, firstName, lastName, specialization }.
  • GET /doctors?search=KOWAL matches a doctor whose last_name is "Kowalski" (case-insensitive substring).
  • GET /doctors?search=cardio matches a doctor whose specialization contains "Cardiology".
  • GET /doctors/{doctorId}/slots?upcoming=true excludes slots with starts_at < now() and excludes slots with status booked.
  • GET /doctors/{doctorId}/slots?upcoming=true returns slots sorted ascending by starts_at.
  • Both endpoints return 401 without a JWT.
  • Both endpoints accept a patient JWT and a doctor JWT (any authenticated role).
  • pnpm verify exits 0.

User stories covered

Blocked by

Metadata

Metadata

Assignees

No one assigned

    Labels

    afkEligible for the main agent looppriority:2Priority 2sliceVertical tracer-bullet slice

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions