Skip to content

Slice 2b (Module 03): Slot creation with overlap detection + add slot form #21

@mGasiorek998

Description

@mGasiorek998

What to build

Add the slot creation endpoint with the central overlap-detection invariant, plus the "Add slot" form on the existing /doctor/slots page. Adjacent slots (new.endsAt == existing.startsAt, no gap) must be accepted; any time-overlap must reject with 409.

  • Fill in doctorContract with createSlot: body { startsAt, endsAt } ISO-8601 UTC, success response 201 with the created slot.
  • POST /doctors/me/slots runs in a single DB transaction using SELECT FOR UPDATE against the calling doctor's existing slots; overlap is new.startsAt < existing.endsAt AND new.endsAt > existing.startsAt; on overlap, transaction rolls back and the endpoint returns 409 { error: "SLOT_OVERLAP" }.
  • endsAt > startsAt is enforced both at the application validation layer (VR-001) and by the existing DB check constraint.
  • Structured INFO log on every successful slot creation (acting doctor id, slot id).
  • "Add slot" form on /doctor/slots: Europe/Warsaw datetime-local pickers, converted to UTC ISO before sending; on success the list refreshes (TanStack Query invalidation); on 409 the form surfaces a "Slot overlaps with an existing slot" message; client validation also blocks endsAt <= startsAt before submit.
  • Concurrency: integration test that fires two identical create requests via Promise.all and asserts exactly one 201 and one 409.

Acceptance criteria

  • POST /doctors/me/slots with a non-overlapping window returns 201 with the created slot in free status.
  • POST /doctors/me/slots with endsAt <= startsAt returns 422 (validation rule VR-001).
  • POST /doctors/me/slots overlapping an existing slot for the same doctor returns 409 SLOT_OVERLAP.
  • An adjacent slot (new.endsAt == existing.startsAt, or new.startsAt == existing.endsAt) is accepted with 201.
  • Two concurrent identical creates (via Promise.all) result in exactly one 201 and one 409.
  • A second doctor can create a slot in the same time window without conflict (overlap is per-doctor).
  • The "Add slot" form on /doctor/slots creates a slot, shows it in the list, and surfaces an inline error on overlap.
  • POST /doctors/me/slots returns 401 without JWT and 403 with a patient JWT.
  • pnpm verify exits 0.

User stories covered

Blocked by

Metadata

Metadata

Assignees

No one assigned

    Labels

    afkEligible for the main agent looppriority:1Priority 1 — bugs default heresliceVertical 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