Skip to main content

Overview

The Appointment module provides a comprehensive scheduling system with calendar views, real-time status management, and filtering capabilities across doctors and branches.

Appointment Calendar

Timeline View

The main appointment page (/appointments) displays a professional timeline view with:
  • 30-minute time slots from 8:00 AM to 6:30 PM
  • Mini calendar for quick date navigation
  • Advanced filters for doctor, branch, and status
  • Real-time statistics showing total, pending, and completed appointments
Appointment timeline showing daily schedule

Calendar Navigation

The sidebar includes a mini calendar with:
  • Month/year navigation with arrow buttons
  • Day selection (Monday-Sunday format)
  • Today indicator with teal border
  • Selected date highlighting
  • Automatic appointment refresh on date change
// Navigate between months
function changeMonth(delta) {
  const newDate = new Date(viewDate);
  newDate.setMonth(newDate.getMonth() + delta);
  viewDate = newDate;
}

Database Schema

CREATE TABLE appointments (
    id INT AUTO_INCREMENT PRIMARY KEY,
    patient_id INT NOT NULL,
    doctor_id INT NOT NULL,
    branch_id INT NOT NULL,
    appointment_date DATE NOT NULL,
    appointment_time TIME NOT NULL,
    duration_minutes INT DEFAULT 30,
    status ENUM('scheduled', 'confirmed', 'waiting', 'completed', 'cancelled') DEFAULT 'scheduled',
    notes TEXT,
    uuid CHAR(36) UNIQUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (patient_id) REFERENCES patients(id) ON DELETE CASCADE,
    FOREIGN KEY (doctor_id) REFERENCES doctors(id) ON DELETE CASCADE,
    FOREIGN KEY (branch_id) REFERENCES branches(id) ON DELETE CASCADE
);

Appointment Status Management

Status Workflow

Appointments follow a lifecycle with 5 distinct statuses:

Scheduled

Initial state when appointment is created. Shows in gray/slate color.

Confirmed

Patient confirmed attendance via phone/WhatsApp. Shows in blue.

Waiting

Patient arrived and is in the waiting room. Shows in amber/yellow.

Completed

Appointment finished successfully. Shows in green/teal.

Cancelled

Appointment was cancelled by patient or clinic. Shows in red/rose.

Status Colors

.badge-scheduled { background: #f1f5f9; color: #475569; }
.badge-confirmed { background: #eff6ff; color: #1e40af; }
.badge-waiting { background: #fffbeb; color: #92400e; }
.badge-completed { background: #f0fdf4; color: #15803d; }
.badge-cancelled { background: #fef2f2; color: #b91c1c; }

Updating Status

Staff can update appointment status directly from the timeline:
  1. Click the status dropdown on any appointment
  2. Select the new status
  3. Status updates immediately via API
API Endpoint:
PATCH /api/appointments/{id}

Body: {
  status: 'scheduled' | 'confirmed' | 'waiting' | 'completed' | 'cancelled'
}

Advanced Filtering

Filter Options

The sidebar provides multiple filters:

Doctor Filter

Filter by specific doctor or view all doctors’ appointments.

Branch Filter

Filter by clinic branch (Central, Norte, Sur).

Status Filter

Filter by appointment status to focus on specific workflows.

Filter Implementation

const filters = {
  doctor_id: 'all',
  branch_id: 'all', 
  status: 'all'
};

// API call with filters
const params = new URLSearchParams({
  date: dateStr,
  doctor_id: filters.doctor_id,
  branch_id: filters.branch_id,
  status: filters.status
});

fetch(`/api/appointments?${params.toString()}`);

Appointment Details

Display Information

Each appointment block shows:
  • Exact time in [HH:MM] format with teal background
  • Patient name as clickable link to patient profile
  • Doctor name with emoji icon (👨‍⚕️)
  • Branch location with emoji icon (📍)
  • Status dropdown for quick updates
  • Notes (if present) in styled box with 📝 icon
Clicking the patient name navigates to /patients/{patient_id} for quick access to full patient details.

Appointment Block Styling

Appointments feature:
  • Left border color matching status
  • Hover animation (slide right with shadow)
  • Rounded corners (18px border-radius)
  • Subtle shadow for depth
.apt-block-premium {
  border-left: 6px solid var(--status-color);
  transition: all 0.2s;
}

.apt-block-premium:hover {
  transform: translateX(4px);
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.05);
}

Statistics Dashboard

Real-time Metrics

The header displays three key statistics:
const stats = {
  total: appointments.length,
  completed: appointments.filter(a => a.status === 'completed').length,
  pending: appointments.filter(a => 
    ['scheduled', 'confirmed', 'waiting'].includes(a.status)
  ).length
};

Total

Total appointments for selected date

Pendientes

Appointments awaiting completion (shown in amber)

Completadas

Successfully completed appointments (shown in teal)

Creating Appointments

From Patient Profile

Appointments are typically created from the patient profile page:
  1. Navigate to patient details
  2. Go to “Appointments” tab
  3. Click “Nueva Cita” button
  4. Fill in appointment details:
    • Doctor selection
    • Date and time
    • Duration (default 30 minutes)
    • Branch selection
    • Optional notes
Required Permissions:
  • CREATE_APPOINTMENTS - Create new appointments
  • VIEW_APPOINTMENTS - View appointment calendar

API Endpoint

POST /api/appointments

Body: {
  patient_id: number,
  doctor_id: number,
  branch_id: number,
  appointment_date: string, // YYYY-MM-DD
  appointment_time: string, // HH:MM:SS
  duration_minutes: number,
  notes?: string
}

Appointment Reminders

UUID System

Each appointment has a unique UUID for secure reminder links:
uuid CHAR(36) UNIQUE -- For reminder URLs and WhatsApp links
This UUID can be used for:
  • WhatsApp reminder messages
  • Email confirmation links
  • Public-facing confirmation pages

Reminder Permissions

Access the reminders dashboard to see upcoming appointments needing confirmation.
Send WhatsApp or email reminders to patients about their appointments.

Time Slot Management

30-Minute Intervals

The timeline is divided into 30-minute slots:
const hours = [
  '08:00', '08:30', '09:00', '09:30', '10:00', '10:30',
  '11:00', '11:30', '12:00', '12:30', '13:00', '13:30',
  '14:00', '14:30', '15:00', '15:30', '16:00', '16:30',
  '17:00', '17:30', '18:00', '18:30'
];

Slot Assignment Logic

Appointments are assigned to slots based on their start time:
const slotApts = appointments.filter(a => {
  const [ah, am] = a.appointment_time.split(':').map(Number);
  const [sh, sm] = h.split(':').map(Number);
  // Match hour and minute range (0-29 or 30-59)
  return ah === sh && (sm === 0 ? am < 30 : am >= 30);
});
Empty slots display a dashed line to indicate availability.

Permissions Reference

Appointment Permissions

VIEW_APPOINTMENTS

Module: CitasAccess the appointment calendar and view scheduled appointments.

CREATE_APPOINTMENTS

Module: CitasSchedule new appointments in the system.

EDIT_APPOINTMENTS

Module: CitasModify existing appointment details (time, doctor, notes).

CANCEL_APPOINTMENTS

Module: CitasCancel appointments when patients reschedule or no-show.

API Reference

List Appointments

GET /api/appointments?date={YYYY-MM-DD}&doctor_id={id}&branch_id={id}&status={status}

Response: {
  success: true,
  appointments: [
    {
      id: number,
      patient_id: number,
      patient_first_name: string,
      patient_last_name: string,
      doctor_id: number,
      doctor_name: string,
      branch_id: number,
      branch_name: string,
      appointment_date: string,
      appointment_time: string,
      duration_minutes: number,
      status: string,
      notes: string | null,
      uuid: string
    }
  ]
}

Update Appointment Status

PATCH /api/appointments/{id}

Body: { status: string }

Response: {
  success: true,
  message: 'Appointment updated'
}

Mobile Responsiveness

On screens below 1024px width, the sidebar stacks above the timeline for better mobile viewing.
@media (max-width: 1024px) {
  .agenda-layout {
    grid-template-columns: 1fr;
  }
}

Best Practices

1

Confirm Appointments

Use the “Confirmed” status after calling patients to verify attendance.
2

Update Status Promptly

Change to “Waiting” when patients arrive, and “Completed” after consultation.
3

Add Detailed Notes

Include reason for visit or special instructions in the notes field.
4

Handle Cancellations

Mark appointments as “Cancelled” rather than deleting them for record-keeping.
5

Use Filters Efficiently

Filter by doctor or branch to manage busy schedules across multiple locations.

Build docs developers (and LLMs) love