Skip to main content
The client dashboard is the central hub for clients to manage their appointments, view service history, and update their profile information.

Dashboard overview

The ClientPageComponent serves as the main dashboard for clients:
client-page.component.ts:14-30
@Component({
  selector: 'app-client-page',
  imports: [
    SplashComponent,
    UserInformationCardComponent,
    AppointmentsPendingComponent,
    AppointmentsFinishedComponent
],
  templateUrl: './client-page.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ClientPageComponent {
  private readonly authFacade = inject(AuthFacade);
  readonly user: Signal<UserBase | null> = this.authFacade.user;
  readonly isCheckingAuth: Signal<boolean> = this.authFacade.isCheckingAuth;
}

Key features

Book appointments

Request new appointments through the multi-step booking form

View pending appointments

See upcoming appointments with full details

Appointment history

Access completed and canceled appointment records

Profile management

Update personal information and profile picture

Dashboard components

The client dashboard is composed of several key components:

User information card

Displays the client’s profile information including:
  • Name and profile picture
  • Contact information (email, phone)
  • Personal details (DNI, birth date, sex)
  • Health information (height, weight)

Pending appointments

The AppointmentsPendingComponent shows all upcoming appointments:
  • Appointment date and time
  • Specialist name and specialty
  • Appointment status
  • Action buttons (view details, cancel)
Pending appointments are automatically sorted by date, showing the nearest appointments first.

Finished appointments

The AppointmentsFinishedComponent displays completed appointment history:
  • Past appointment details
  • Diagnosis information (if added by specialist)
  • Client rating (if submitted)
  • Option to view full appointment details

Booking appointments

Clients can book new appointments through a streamlined 4-step process:
1

Select service

Choose from available specialties (haircut, beard trim, coloring, etc.)
request-appointment-form.component.ts:53-56
{
  number: 1,
  title: 'Elegir Servicio',
  description: 'Seleccioná el servicio que necesites.',
}
2

Choose specialist

Select a preferred specialist or view all available specialists for the chosen service
request-appointment-form.component.ts:57-61
{
  number: 2,
  title: 'Elegir Especialista',
  description:
    'Podés elegir al especialista en caso de tener alguna preferencia.',
}
3

Pick date and time

Select from available time slots based on specialist availability
request-appointment-form.component.ts:62-66
{
  number: 3,
  title: 'Elegir Fecha y Hora',
  description:
    'Seleccioná la fecha y hora del turno, basado en la disponibilidad actual.',
}
4

Confirm booking

Review all appointment details before final confirmation
request-appointment-form.component.ts:67-71
{
  number: 4,
  title: 'Confirmar Turno',
  description:
    'Revisá la información del turno antes de confirmar la solicitud.',
}

Step validation

Each step is validated before allowing progression:
request-appointment-form.component.ts:82-93
readonly isNextStepDisabled = computed(() => {
  switch (this.currentStep()) {
    case 1:
      return !this.specialtySelected();
    case 2:
      return !this.specialistSelected();
    case 3:
      return !this.dateTimeSelected();
    default:
      return false;
  }
});

Appointment submission

Once all steps are completed, the appointment is submitted:
request-appointment-form.component.ts:136-172
public async onSubmit(): Promise<void> {
  try {
    const specialty = this.specialtySelected();
    const specialist = this.specialistSelected();
    const dateTime = this.dateTimeSelected();

    if (!specialty || !specialist || !dateTime) return;

    this.waitingConfirmation.set(true);

    const newAppointment = await this.appointmentFacade.createAppointment(
      specialty, specialist, dateTime
    );

    if (newAppointment) {
      setTimeout(() => {
        this.dialogService
        .openGeneric<DialogComponent, boolean>(DialogComponent, {
          title: '¡Turno Confirmado!',
          message:
            'Tu turno fue agendado con éxito. Podés ver los detalles y gestionarlo en tu perfil.',
          confirmText: 'Ver mis turnos',
          icon: 'check',
          iconColor: 'text-green-700',
          iconBgColor: 'bg-green-300',
          cancelText: 'Volver al inicio'
          
        })
        .subscribe((result) => {
          if (result) {
            this.router.navigate(['/dashboard/appointments-list']);
          } else {
            this.router.navigate(['/dashboard/client']);
          }
        });
      }, 150);
    }
  }
}
After successful booking, clients can choose to view their appointments list or return to the dashboard.

Managing appointments

Viewing appointment details

Clients can view full details of any appointment by clicking on it in their appointments list:
appointment-list-page.component.ts:8-22
@Component({
  selector: 'app-appointment-list-page',
  imports: [
    SplashComponent,
    TitleDescriptionComponent,
    AppointmentsTableComponent
],
  templateUrl: './appointment-list-page.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppointmentListPageComponent {
  readonly authFacade = inject(AuthFacade);
  readonly appointmentFacade = inject(AppointmentFacade);
  readonly appointments = this.appointmentFacade.appointments();
}

Canceling appointments

Clients can cancel pending appointments:
  1. Navigate to the appointment details
  2. Click the cancel button
  3. Provide a cancellation reason
  4. Confirm cancellation
The system updates the appointment status and records who canceled:
await appointmentFacade.updateAppointment(appointmentId, {
  status: AppointmentStatus.CANCELED,
  canceledBy: UserRoles.CLIENT,
  cancellationReason: reason
});
Canceled appointments cannot be restored. Clients must create a new appointment if they change their mind.

Rating appointments

After an appointment is completed, clients can rate the service:
1

Access completed appointment

Navigate to the finished appointments section
2

Submit rating

Rate the service from 1 to 5 stars and optionally add a comment
rating.model.ts:1-6
export interface Rating {
  score: AllowedScore;
  comment?: string;
}

export type AllowedScore = 1 | 2 | 3 | 4 | 5;
3

Save rating

The rating is permanently saved to the appointment record
Ratings help other clients choose specialists and help specialists improve their services.

Profile management

Clients can update their profile information:

Editable fields

  • First name and last name
  • Phone number
  • Profile picture

Profile picture upload

Clients can upload a profile picture through Cloudinary integration:
  1. Click the profile picture in the user information card
  2. Select an image file from your device
  3. The image is uploaded and automatically resized
  4. The new profile picture is displayed across the application

Client data model

The complete client model includes:
client.model.ts:3-7
export interface Client extends UserBase {
  // medicalRecordId: string;
  height?: number;
  weight?: number;
}
With the base user properties:
user-base.model.ts:3-17
export interface UserBase {
  id: string;
  firstName: string;
  lastName: string;
  dni: string;
  sex: Sex;
  birthDate: Date;
  email: string;
  password?: string;
  phone?: string;
  profilePictureUrl: string;
  registrationDate: Date;
  role: UserRoles;
  status: UserStatus;
}
The client dashboard provides quick navigation to:
  • Home: Return to main dashboard
  • Book Appointment: Start the booking flow
  • My Appointments: View all appointments (pending, completed, canceled)
  • Profile: Edit profile information
  • Logout: Sign out of the application

Reactive state management

The client dashboard uses Angular signals for reactive state:
  • Real-time updates when appointments change
  • Automatic loading states during data fetches
  • Error handling with user-friendly messages
  • Optimistic UI updates for better user experience
All appointment data is synchronized with Firebase Firestore, ensuring data consistency across devices.

Next steps

Appointments

Learn more about the appointment system

User Roles

Understand role-based permissions

Build docs developers (and LLMs) love