Skip to main content

Overview

The Appointment Scheduling system provides comprehensive tools for managing dental appointments, including creation, modification, status updates, and attendance tracking. The system integrates with patient and treatment management for seamless workflow.

Appointment Data Model

Appointments are defined by the AppointmentData interface in src/app/services/appointment.service.ts:
export interface AppointmentData {
  id: number;
  fecha: string;           // Date in D/M/YYYY format
  hora: string;            // Time in HH:MM format
  paciente: string;        // Patient name
  tratamiento: string;     // Treatment name
  doctor: string;          // Doctor name
  duracion: string;        // Duration (e.g., "30 min")
  estado: 'confirmada' | 'pendiente' | 'completada';
  asistido: 'sí' | 'no' | 'pendiente';
}

Appointment Service

The AppointmentService provides all appointment-related operations:

Location

src/app/services/appointment.service.ts

Available Methods

getAppointments()

Returns all appointments

addAppointment(data)

Creates a new appointment

updateAppointmentStatus(id, status)

Updates appointment status

updateAppointmentTime(id, time)

Reschedules an appointment

updateAppointmentAttendance(id, asistido)

Marks attendance status

deleteAppointment(id)

Removes an appointment

Service Implementation

@Injectable({
  providedIn: 'root'
})
export class AppointmentService {
  private appointments: AppointmentData[] = [...];

  getAppointments(): AppointmentData[] {
    return this.appointments;
  }

  updateAppointmentStatus(
    id: number, 
    status: 'confirmada' | 'pendiente' | 'completada'
  ): void {
    const appointment = this.appointments.find(a => a.id === id);
    if (appointment) {
      appointment.estado = status;
    }
  }

  addAppointment(
    data: Omit<AppointmentData, 'id' | 'estado' | 'asistido' | 'duracion'>
  ): void {
    const newId = this.appointments.length > 0 
      ? Math.max(...this.appointments.map(a => a.id)) + 1 
      : 1;
    const newAppointment: AppointmentData = {
      ...data,
      id: newId,
      estado: 'pendiente',
      asistido: 'pendiente',
      duracion: '30 min'
    };
    this.appointments.push(newAppointment);
  }
}

Appointment Component

The main appointment management interface is in src/app/appointment/appointment.ts:

Component Structure

@Component({
  selector: 'app-appointment',
  standalone: true,
  imports: [CommonModule, FormsModule, NewAppointment],
  templateUrl: './appointment.html',
  styleUrl: './appointment.css',
})
export class Appointment implements OnInit {
  appointments: AppointmentData[] = [];
  searchText: string = '';
  currentFilter: string = 'Todas';
  selectedAppointment: AppointmentData | null = null;
  isPopupOpen: boolean = false;
  isNewAppointmentModalOpen: boolean = false;
  newTime: string = '';
  asistencia: 'sí' | 'no' | 'pendiente' = 'pendiente';

  constructor(private appointmentService: AppointmentService) { }

  ngOnInit(): void {
    this.loadAppointments();
  }
}

Filtering System

The appointment list supports multi-criteria filtering:

Status Filters

Todas

Show all appointments

Confirmadas

Only confirmed appointments

Pendientes

Awaiting confirmation

Completadas

Finished appointments

Filter Implementation

setFilter(filter: string): void {
  this.currentFilter = filter;
}

get filteredAppointments(): AppointmentData[] {
  let filtered = this.appointments;

  // Filter by status
  if (this.currentFilter !== 'Todas') {
    filtered = filtered.filter(a => 
      a.estado.toLowerCase() === this.currentFilter.toLowerCase().slice(0, -1) ||
      (this.currentFilter === 'Confirmadas' && a.estado === 'confirmada') ||
      (this.currentFilter === 'Pendientes' && a.estado === 'pendiente') ||
      (this.currentFilter === 'Completadas' && a.estado === 'completada')
    );
  }

  // Filter by search text
  if (this.searchText) {
    const search = this.searchText.toLowerCase();
    filtered = filtered.filter(a =>
      a.paciente.toLowerCase().includes(search) ||
      a.tratamiento.toLowerCase().includes(search)
    );
  }

  return filtered;
}

Search Functionality

The search feature allows filtering by:
  • Patient name
  • Treatment type
The search is case-insensitive and updates in real-time as you type.

Creating New Appointments

New appointments are created through the NewAppointment component:

Component Location

src/app/new-appointment/new-appointment.ts

Form Structure

@Component({
  selector: 'app-new-appointment',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './new-appointment.html',
  styleUrl: './new-appointment.css',
})
export class NewAppointment implements OnInit {
  @Input() initialDate: string = '';
  @Output() close = new EventEmitter<void>();
  @Output() created = new EventEmitter<void>();

  appointmentData = {
    paciente: '',
    doctor: '',
    fecha: '',
    hora: '',
    tratamiento: ''
  };

  doctors = ['Dr. Rodríguez', 'Dra. Martínez', 'Dr. Sánchez'];
}

Treatment Autocomplete

The component features intelligent treatment suggestions:
allTreatments: Tratamiento[] = [];
filteredTreatments: Tratamiento[] = [];
showSuggestions: boolean = false;

onTreatmentInput(): void {
  if (this.appointmentData.tratamiento) {
    const search = this.appointmentData.tratamiento.toLowerCase();
    this.filteredTreatments = this.allTreatments.filter(t =>
      t.nombre.toLowerCase().includes(search)
    );
    this.showSuggestions = this.filteredTreatments.length > 0;
  } else {
    this.filteredTreatments = [];
    this.showSuggestions = false;
  }
}

selectTreatment(treatment: Tratamiento): void {
  this.appointmentData.tratamiento = treatment.nombre;
  this.showSuggestions = false;
}
1

User Types Treatment

As the user types, the system searches available treatments
2

Display Suggestions

Matching treatments are displayed in a dropdown
3

Select Treatment

User clicks on a suggestion to auto-fill the field
4

Hide Suggestions

Dropdown closes after selection or when field loses focus

Submitting New Appointment

onSubmit(): void {
  if (this.appointmentData.paciente && 
      this.appointmentData.doctor && 
      this.appointmentData.fecha && 
      this.appointmentData.hora) {
    this.appointmentService.addAppointment(this.appointmentData);
    this.created.emit();
    this.close.emit();
  }
}

Managing Existing Appointments

Opening Appointment Details

openPopup(appointment: AppointmentData): void {
  this.selectedAppointment = { ...appointment };
  this.newTime = appointment.hora;
  this.asistencia = appointment.asistido;
  this.isPopupOpen = true;
}

Updating Appointment Status

updateStatus(status: 'confirmada' | 'pendiente' | 'completada'): void {
  if (this.selectedAppointment) {
    this.appointmentService.updateAppointmentStatus(
      this.selectedAppointment.id, 
      status
    );
    this.loadAppointments();
    this.closePopup();
  }
}

Rescheduling Appointments

updateTime(): void {
  if (this.selectedAppointment && this.newTime) {
    this.appointmentService.updateAppointmentTime(
      this.selectedAppointment.id, 
      this.newTime
    );
    this.loadAppointments();
    this.closePopup();
  }
}

Saving Multiple Changes

saveChanges(): void {
  if (this.selectedAppointment) {
    this.appointmentService.updateAppointmentTime(
      this.selectedAppointment.id, 
      this.newTime
    );
    this.appointmentService.updateAppointmentAttendance(
      this.selectedAppointment.id, 
      this.asistencia
    );
    this.loadAppointments();
    this.closePopup();
  }
}

Attendance Tracking

Appointments track patient attendance with three states:
EstadoDescriptionWhen to Use
pendienteDefault stateBefore appointment time
Patient attendedAfter successful appointment
noPatient did not showAfter missed appointment

Marking as Absent

markAsAbsent(): void {
  if (this.selectedAppointment) {
    this.appointmentService.deleteAppointment(
      this.selectedAppointment.id
    );
    this.loadAppointments();
    this.closePopup();
  }
}
Marking as absent will delete the appointment record. Consider implementing a soft delete or archive system for historical tracking.

Sample Appointment Data

{
  id: 1,
  fecha: '4/2/2026',
  hora: '09:00',
  paciente: 'María García',
  tratamiento: 'Limpieza dental',
  doctor: 'Dr. Rodríguez',
  duracion: '30 min',
  estado: 'confirmada',
  asistido: 'pendiente'
}

Routing Configuration

Appointment routes in src/app/app.routes.ts:
{ 
  path: 'citas', 
  component: Appointment, 
  data: { title: 'Citas Médicas' } 
}

Usage Examples

Get All Appointments

const appointments = this.appointmentService.getAppointments();
console.log(`Total appointments: ${appointments.length}`);

Create New Appointment

const newAppointment = {
  paciente: 'Juan Pérez',
  doctor: 'Dr. Rodríguez',
  fecha: '10/03/2026',
  hora: '14:30',
  tratamiento: 'Limpieza dental'
};

this.appointmentService.addAppointment(newAppointment);

Confirm Appointment

this.appointmentService.updateAppointmentStatus(1, 'confirmada');

Reschedule Appointment

this.appointmentService.updateAppointmentTime(1, '16:00');

Mark Attendance

this.appointmentService.updateAppointmentAttendance(1, 'sí');

Integration Points

With Patient Management

  • Appointments are linked to patient names
  • Patient details can be accessed from appointment records
  • Patient appointment history is tracked

With Treatment Tracking

  • Treatment autocomplete pulls from treatment catalog
  • Treatment duration can inform appointment duration
  • Treatment history links to appointments

With Calendar

  • Appointments are displayed on calendar view
  • Calendar allows quick appointment creation with date pre-filled
  • Visual representation of appointment schedule

Best Practices

Confirmation

Always confirm appointments before the scheduled time

Buffer Time

Consider buffer time between appointments for preparation

Reminders

Implement appointment reminders to reduce no-shows

Status Updates

Keep appointment status current for accurate scheduling

Future Enhancements

  • Email/SMS appointment reminders
  • Recurring appointment support
  • Doctor availability checking
  • Conflict detection for double-booking
  • Wait list management
  • Online appointment booking
  • Integration with calendar applications
  • Automated status updates

Build docs developers (and LLMs) love