Kulcare Docs
DeveloperQueue

CMS Queue Management

Overview

The Queue Management system in the CMS app provides real-time patient queue tracking, appointment status management, and doctor consultation workflow automation. It's designed for healthcare clinics to efficiently manage patient flow throughout the day.

Architecture

Component Structure

apps/cms/src/
├── pages/
│   └── QueuePage.tsx          # Main queue page component
├── components/queue/
│   ├── QueueHeader.tsx        # Header with search and summary
│   ├── QueueFilters.tsx       # Filter controls (doctor, category, date)
│   ├── QueueTable.tsx         # Main patient queue table
│   ├── QueueTableRow.tsx      # Individual patient row
│   ├── QueueStats.tsx         # Summary statistics display
│   ├── QueueEmptyState.tsx    # Empty state component
│   └── QueueErrorState.tsx    # Error state component
├── hooks/
│   ├── useQueue.ts            # Core queue data fetching
│   ├── useQueueData.ts        # Composed hook with filtering
│   ├── useQueueActions.ts     # Queue-related actions
│   ├── useQueueModals.ts      # Modal state management
│   ├── useQueueFilters.ts     # Filter state management
│   └── useRealtimeQueue.ts    # Real-time updates via Ably
├── services/
│   └── queueApi.ts            # API service layer
└── types/
    └── queue.ts               # TypeScript types

Key Features

  1. Real-time Updates: Live patient status changes using Ably WebSockets
  2. Multi-doctor Support: Filter by specific doctors or view all
  3. Status Workflow: Manage patient flow through different statuses
  4. Telemedicine: Support for video consultations
  5. Quick Actions: Notes, billing, prescriptions, follow-up scheduling
  6. Responsive Design: Works across desktop and mobile devices

Data Flow

Queue Data Structure

interface QueuePatient {
  id: string
  tokenNumber: string
  patientId: string
  clinicPatientId: string
  patientName: string
  patientAge: number
  patientGender: "male" | "female" | "other"
  patientPhone: string
  doctorId: string
  doctorName: string
  appointmentTime: string
  appointmentType: "consultation" | "follow-up" | "emergency" | "telemedicine"
  status: "in-queue" | "checked-in" | "with-doc" | "checked-out" | 
          "removed" | "cancelled" | "reassign" | "not-confirmed"
  checkInTime?: string
  waitingTime?: number
  consultationTime?: number
  // ... additional fields
}

Status Workflow

in-queue → checked-in → with-doc → checked-out
                ↓          ↓           ↓
             removed    removed    removed

API Integration

Queue Endpoints

// Get queue for a clinic/date
GET /clinics/{clinicId}/queue?date=YYYY-MM-DD

// Get doctor-specific queue  
GET /clinics/{clinicId}/clinic_doctors/{doctorId}/queue?date=YYYY-MM-DD

// Update appointment status
PUT /appointments/{appointmentId}
Body: {
  clinic_id: number,
  doctor_id: number,
  appointment_status: string
}

// Save patient notes
POST /clinic_patients/{clinicPatientId}/notes
Body: {
  note_text: string,
  appointment_id: number,
  clinic_doctor_id: number
}

// Schedule next visit
PUT /clinic_patients/{clinicPatientId}/next_visit/{appointmentId}
Body: {
  clinic_doctor_id: number,
  next_visit_units: "DAYS" | "WEEKS" | "MONTHS",
  next_visit_value: number
}

Real-time Integration

Ably Configuration

// Environment variables
VITE_ABLY_KEY=your-ably-key
VITE_ABLY_ENVIRONMENT=us  // Optional: 'us' or 'eu'

Real-time Events

// Channel format
`clinic:${clinicId}:queue:${date}`

// Event types
- appointment.updated
- appointment.created
- appointment.deleted
- queue.reordered

Usage Examples

Basic Queue Implementation

import { useQueueData } from "../hooks"

export default function QueuePage() {
  const { filters, setFilters } = useQueueFilters()
  
  const {
    filteredPatients,
    summary,
    isLoading,
    isError,
    refetch,
    isRealTimeConnected
  } = useQueueData({ filters })

  return (
    <div>
      <QueueHeader 
        summary={summary}
        isRealTimeConnected={isRealTimeConnected}
      />
      <QueueTable 
        patients={filteredPatients}
        isLoading={isLoading}
      />
    </div>
  )
}

Custom Hooks Usage

// Queue filters
const { filters, setFilters, resetFilters } = useQueueFilters()

// Queue actions
const {
  handleStatusChange,
  handlePatientClick,
  handleCreatePrescription,
  updateAppointmentStatus
} = useQueueActions()

// Modal management
const {
  showNotesModal,
  setShowNotesModal,
  openNotesModal,
  selectedPatient
} = useQueueModals()

Status Update Flow

// Handle status change with confirmation
const handleStatusChange = async (patientId: string, newStatus: string) => {
  // Show confirmation for critical status changes
  if (needsConfirmation(currentStatus, newStatus)) {
    setStatusConfirmation({ patientId, newStatus })
    return
  }
  
  // Direct update
  await updateAppointmentStatus.mutateAsync({
    appointmentId: patientId,
    status: newStatus,
    doctorId: patient.doctorId
  })
}

Component Details

QueueTable Features

  • Density Control: Compact/Normal/Comfortable view modes
  • Column Visibility: Customizable column display
  • Row Actions: Dropdown menu with patient actions
  • Loading States: Row-level loading during updates
  • Empty States: Contextual messages for no patients

QueueFilters

  • Doctor Filter: Select specific doctor or "All Doctors"
  • Category Filter: Filter by appointment category
  • Date Picker: Select queue date
  • Search: Real-time patient search
  • Reset: Clear all filters

Quick Actions

  1. Start Consultation: Begin patient consultation
  2. Create Prescription: Navigate to care plan
  3. Billing: Open billing panel
  4. Quick Notes: Add patient notes
  5. Next Visit: Schedule follow-up
  6. Remove from Queue: Remove patient with reason

Performance Optimizations

  1. Query Caching: 10-minute staleTime for queue data
  2. Optimistic Updates: Immediate UI feedback
  3. Debounced Search: 300ms debounce on search input
  4. Memoized Filtering: Efficient patient filtering
  5. Lazy Loading: Modals load on demand

Error Handling

// API error handling
if (isError) {
  return <QueueErrorState 
    error={error} 
    onRetry={refetch} 
  />
}

// Network status
if (!isRealTimeConnected) {
  // Show offline indicator
}

Testing Considerations

  1. Mock Data: Use @kulcare/mock-data for development
  2. Real-time Testing: Test with multiple browser tabs
  3. Status Transitions: Verify all status workflows
  4. Error Scenarios: Test network failures
  5. Performance: Test with large patient lists (100+)

Common Patterns

Adding New Actions

// 1. Add to QueueTableRow dropdown
<DropdownMenuItem onClick={() => onCustomAction(patient)}>
  Custom Action
</DropdownMenuItem>

// 2. Handle in QueuePage
const handleCustomAction = (patient: QueuePatient) => {
  // Action logic
}

// 3. Pass to QueueTable
<QueueTable 
  onCustomAction={handleCustomAction}
/>

Custom Status Rendering

// Add to queue constants
export const STATUS_CONFIG = {
  "custom-status": {
    label: "Custom Status",
    color: "bg-purple-500",
    icon: CustomIcon
  }
}

On this page