Skip to content
Amine Bazi.
Back to projects

Full-stack application — academic project (PFA), EMSI · 2025

AppointmentPro

Appointment booking system with client / professional roles

AppointmentPro professional dashboard with a booked slot

Context and problem

Built as my final-year academic project (PFA) at EMSI. Independent professionals often manage appointments by phone or on paper: missed slots, double bookings, no overview. The goal was a complete web application covering the entire appointment lifecycle, from publishing availability to completion.

Objectives

  • Offer two distinct journeys: professionals publish slots, clients book them.
  • Guarantee that a booked slot can no longer be offered to other clients.
  • Cover the full cycle: booking, completion, cancellation.
  • Secure the data: each user only sees their own appointments.

My role

  • Development of the React / TypeScript interface: client and professional dashboards, forms, slot lists.
  • PostgreSQL database modelling: profiles, time slots, appointments.
  • Supabase authentication setup with role selection at sign-up.
  • Writing the Row Level Security policies controlling access to every table.

Key features

  • Email sign-up and sign-in via Supabase Auth, with client or professional role.
  • Professionals create and delete availability slots (date, start and end time).
  • Clients browse available slots and book in one click.
  • Appointment lifecycle: booked, completed, cancelled.
  • A booked slot automatically becomes unavailable to other clients.
  • Role-specific dashboards: slot management for pros, bookings for clients.

Technical architecture

  • React 18 + TypeScript + Vite frontend, components organised by role (client, professional, auth, shared).
  • Supabase backend-as-a-service: PostgreSQL database, authentication and generated API.
  • Database-level security: Row Level Security policies on the profiles, time_slots and appointments tables — a client can only read or modify their own appointments.
  • Shared TypeScript types (Profile, TimeSlot, Appointment) mirroring the relational schema.
  • Versioned SQL migration defining enums, tables and access policies.

Technologies

  • React 18
  • TypeScript
  • Vite
  • Tailwind CSS
  • Supabase
  • PostgreSQL
  • Row Level Security

Technical decisions and challenges

  • Booking integrity: preventing double-booking of a slot — availability status is enforced by the database, not only by the interface.
  • Data isolation between users: RLS policies guarantee no user can reach another user's appointments by crafting a request.
  • Two distinct experiences in one application: routing and components adapt to the role returned by authentication.

Outcome and limitations

  • Working application tested locally end to end: sign-up, slot creation, booking and cancellation all verified (screenshots below).
  • Known limitation: the app depends on an external Supabase project; environment keys are not included in the project folder.
  • Known limitation: not publicly deployed at this stage; demo accounts only.

Screenshots

AppointmentPro professional dashboard with a booked slot
Professional dashboard: slot creation, a booked slot and a completed appointment.
Client dashboard with available slots
Client side: available slots are listed with one-click booking.
Booked appointment on the client side with management actions
Booked appointment: the client can complete or cancel from their dashboard.
AppointmentPro sign-in page
Email authentication with role selection (client or professional) at sign-up.
Professional dashboard in its initial state
Initial state of the professional dashboard: adding the first availability slot.