Skip to main content

Overview

Time blocks represent available appointment slots created by doctors. They define specific time periods when a doctor is available to see patients. Patients can reserve these time blocks to create appointments.

Time Block Model

The time block data structure is defined in the Prisma schema:
model TimeBlock {
  id        Int      @id @default(autoincrement())
  doctorId  Int
  startTime DateTime
  endTime   DateTime
  date      DateTime @default(now())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  doctor      User         @relation(fields: [doctorId], references: [id])
  appointment Appointment?

  @@unique([doctorId, startTime, endTime])
}

Field Descriptions

id
integer
Auto-incrementing unique identifier for the time block.
doctorId
integer
required
Reference to the doctor who created this time block. Only users with the DOCTOR role can create time blocks.
startTime
DateTime
required
The beginning of the available time slot. This defines when the appointment can start.
endTime
DateTime
required
The end of the available time slot. This defines when the appointment must conclude.
date
DateTime
default:"now()"
The date when this time block is valid. Defaults to the current date when created.
createdAt
DateTime
Timestamp when the time block was created.
updatedAt
DateTime
Timestamp of the last update to the time block.

How Time Blocks Work

Time blocks serve as the foundation for the appointment scheduling system:
1

Doctor Creates Availability

A doctor creates a time block by specifying a start time and end time. This represents a period when they’re available to see patients.
2

Time Block is Available

The time block appears in the system as an available slot. Patients can browse available time blocks to find suitable appointment times.
3

Patient Reserves Time Block

When a patient books an appointment, they select an available time block. This creates an Appointment record linked to the time block.
4

Time Block is Reserved

Once reserved, the time block cannot be booked by other patients. The one-to-one relationship between time blocks and appointments enforces this.

Relationships

Doctor Relationship

Each time block belongs to exactly one doctor:
doctor User @relation(fields: [doctorId], references: [id], onDelete: Restrict)
The onDelete: Restrict constraint prevents deletion of a doctor who has created time blocks.

Appointment Relationship

Each time block can have zero or one appointment:
appointment Appointment?
The ? indicates this is an optional relationship. A time block without an appointment is available for booking.
To check if a time block is available, query for time blocks where appointment is null.

Creating Time Blocks

Doctors create time blocks through the time block controller. The system validates ownership and prevents conflicts. Example from /home/daytona/workspace/source/src/controllers/timeBlockController.js:6:
const block = await prisma.timeBlock.create({
  data: { doctorId, startTime, endTime },
});

Ownership Enforcement

Doctors can only manage their own time blocks. The system validates ownership before allowing updates or deletions at /home/daytona/workspace/source/src/controllers/timeBlockController.js:28.

Constraints and Validation

Unique Constraint

The schema enforces uniqueness on the combination of doctor, start time, and end time:
@@unique([doctorId, startTime, endTime])
This prevents a doctor from creating duplicate time blocks with identical time ranges.

Business Rules

  1. No Overlapping Slots: While not enforced at the database level, the application should validate that time blocks don’t overlap for the same doctor.
  2. Future Dates: Time blocks should typically be created for future dates to allow patients to book appointments in advance.
  3. Reasonable Duration: The endTime should be after startTime to create a valid time slot.

Managing Time Blocks

Updating Time Blocks

Doctors can update their time blocks if they haven’t been reserved:
const updated = await prisma.timeBlock.update({
  where: { id },
  data: { startTime, endTime },
});
Updating a time block that has an associated appointment may cause scheduling conflicts. Consider the impact on existing appointments before making changes.

Deleting Time Blocks

Doctors can delete their unreserved time blocks:
await prisma.timeBlock.delete({ where: { id } });
From /home/daytona/workspace/source/src/controllers/timeBlockController.js:59, the system validates:
  • The time block exists
  • The requesting doctor owns the time block
  • No appointment is linked to the time block (enforced by onDelete: Restrict)

Querying Available Time Blocks

To find available time blocks for booking:
const availableBlocks = await prisma.timeBlock.findMany({
  where: {
    appointment: null,  // Not yet reserved
    startTime: { gte: new Date() }  // Future time slots
  },
  include: {
    doctor: {
      select: { id: true, name: true }
    }
  },
  orderBy: { startTime: 'asc' }
});
This query returns all unreserved time blocks scheduled for future dates, sorted by start time.

Best Practices

  • Create Blocks in Advance: Doctors should create time blocks well in advance to give patients adequate booking time.
  • Standard Durations: Use consistent time block durations (e.g., 30 minutes, 1 hour) for predictable scheduling.
  • Buffer Time: Consider adding buffer time between appointments by creating time blocks with gaps.
  • Regular Updates: Doctors should regularly review and update their availability to reflect their actual schedule.

Build docs developers (and LLMs) love