System Overview

Clarity Clinic

Care, booked simply.

A full-stack clinic appointment & booking platform — a patient web app for browsing doctors and booking visits, a staff dashboard for running the clinic day, and a .NET API tying it all together with a race-safe slot engine, payments, and role-based access.

Patient App · React 19 Staff Dashboard · Angular 20 Backend · ASP.NET Core 8 AR / EN + RTL Light / Dark
The system

Three apps, one platform

Two frontends and one backend. Each is independently runnable and talks to the API over HTTPS/JSON.

Patient App :5173

React 19 · Vite · TypeScript

The public-facing booking experience for patients.

  • Browse doctors & services
  • Book and pay online
  • View appointments & prescriptions
  • AR / EN with full RTL
  • Light / dark theming

Staff Dashboard :4321

Angular 20 · Standalone · Signals

The internal control room for running the clinic.

  • Role-based experience
  • Admin — staff, services, reports
  • Receptionist — front desk & calendar
  • Doctor — schedule & visits

Backend API :5180

ASP.NET Core 8 · EF Core · SQL Server

The single source of truth behind both apps.

  • JWT authentication
  • Race-safe slot engine
  • Swagger UI at /swagger
  • 44 REST endpoints
How it fits together

Architecture

Both clients call the same API over HTTPS/JSON with a JWT bearer token. The API layers requests through controllers and services into EF Core, persisting to SQL Server LocalDB.

Patient App
React 19 · Vite
:5173
Staff Dashboard
Angular 20
:4321
Backend API
ASP.NET Core 8
:5180
Controllers → Services → EF Core
SQL Server LocalDB
database
ClinicDb
CORS on the API allows origins :5173 and :4321 — a comma-separated list, so multiple dev origins are supported
Under the hood

Tech stack

A modern TypeScript frontend pairing with a clean .NET backend, with i18n, theming, and auth as cross-cutting concerns across the whole platform.

Frontend UI

React 19 Vite TypeScript TanStack Query Zustand Axios react-i18next Angular 20 RxJS Signals

Backend API

ASP.NET Core 8 EF Core SQL Server JWT BCrypt

Cross-cutting Both

AR / EN i18n RTL support Light / dark theming Role-based auth
Who can do what

Roles & permissions

Four roles. The matrix below maps every core capability to the roles allowed to perform it. Permissions are always enforced on the server.

Capability Patient Receptionist Admin Doctor
Browse doctors & slots (incl. anonymous)
Book & pay online
View own appointments & prescriptions
Day calendar
Walk-in booking
Check-in / no-show / cash-paid / reschedule
Manage services & availability
Add doctors / receptionists & reports
Complete visit + write diagnosis / prescription
View patient history
State machine

Appointment lifecycle

An appointment moves through a small set of states. Online bookings start as PendingPayment; cash / in-clinic bookings land on Confirmed directly.

PendingPayment Confirmed
▲ book cash / in-clinic → Confirmed directly
Confirmed Arrived Completed
Confirmed / Arrived NoShow
Confirmed / PendingPayment Cancelled → slot freed & rebookable
Double-booking is race-safe — a concurrent attempt on a taken slot returns 409 Conflict.
Step by step

End-to-end flows

Four real journeys through the system, from a patient booking online to an admin onboarding a new doctor.

a Patient books online (pays now)

1Register / login 2Browse a doctor 3Pick service + date 4See available slots 5Pick a slot 6Choose Online + Pay online 7Confirm → checkout 8Payment successful + join link 9Appointment Confirmed

b Patient books in-clinic (pays cash)

1Same up to picking a slot 2Choose In clinic + Pay at clinic 3Appointment Confirmed immediately

c Clinic day — reception, doctor, patient

1Reception checks patient in → Arrived 2Doctor opens schedule 3Completes visit + writes diagnosis & prescription 4Patient sees the prescription

d Admin onboards a doctor, reception books a walk-in

1Admin adds a doctor 2Credentials shown 3Reception books a walk-in for a new patient
REST reference

API at a glance

All 44 endpoints, grouped by area. Base path /api, served at :5180. Methods are color-coded; auth shows the access level required.

Auth 5 endpoints

MethodPathAuthPurpose
POST/api/auth/registerAnonymousPatient signup
POST/api/auth/loginAnonymousAuthenticate, receive JWT
GET/api/auth/meAuthedCurrent user profile
PUT/api/auth/profileAuthedUpdate own profile
PUT/api/auth/passwordAuthedChange password

Doctors & Slots 8 endpoints

MethodPathAuthPurpose
GET/api/doctorsAnonymousPaged doctor search
GET/api/doctors/{id}AnonymousDoctor detail
GET/api/doctors/{id}/slotsAnonymousAvailable slots (query: date, serviceId)
GET/api/doctors/{id}/availabilityAdmin · RecepRead weekly availability
PUT/api/doctors/{id}/availabilityAdmin · RecepSet weekly availability
GET/api/doctors/{id}/blocked-datesAdmin · RecepList blocked days
POST/api/doctors/{id}/blocked-datesAdmin · RecepBlock a date
DELETE/api/doctors/{id}/blocked-dates/{date}Admin · RecepUnblock a date

Services 4 endpoints

MethodPathAuthPurpose
GET/api/servicesAnonymousList services
POST/api/servicesAdmin · RecepCreate a service
PUT/api/services/{id}Admin · RecepUpdate a service
DELETE/api/services/{id}Admin · RecepDelete a service

Appointments — Patient 5 endpoints

MethodPathAuthPurpose
POST/api/appointmentsPatientBook an appointment
GET/api/me/appointmentsPatientMy appointments
GET/api/me/prescriptionsPatientMy prescriptions
GET/api/appointments/{id}AuthedAppointment detail
PUT/api/appointments/{id}/cancelAuthedCancel (frees the slot)

Appointments — Front desk 6 endpoints

MethodPathAuthPurpose
GET/api/appointmentsAdmin · RecepDay calendar
POST/api/appointments/walk-inAdmin · RecepBook a walk-in
PUT/api/appointments/{id}/rescheduleAdmin · RecepMove to another slot
PUT/api/appointments/{id}/arrivedAdmin · RecepCheck in → Arrived
PUT/api/appointments/{id}/no-showAdmin · RecepMark no-show
PUT/api/appointments/{id}/cash-paidAdmin · RecepRecord cash payment

Doctor — Clinical 5 endpoints

MethodPathAuthPurpose
PUT/api/appointments/{id}/completeDoctorComplete the visit
POST/api/appointments/{id}/visitDoctorRecord visit + prescription
PUT/api/visits/{id}DoctorUpdate a visit
GET/api/doctor/scheduleDoctorMy schedule
GET/api/patients/{id}/historyDoctorPatient history

Patients 2 endpoints

MethodPathAuthPurpose
POST/api/patientsAdmin · RecepCreate a patient record
GET/api/patientsAdmin · RecepList / search patients

Admin 6 endpoints

MethodPathAuthPurpose
GET/api/admin/staffAdminList staff
POST/api/admin/doctorsAdminAdd a doctor
POST/api/admin/receptionistsAdminAdd a receptionist
PUT/api/admin/staff/{id}AdminUpdate staff member
PUT/api/admin/staff/{id}/activeAdminActivate / deactivate
GET/api/admin/reportsAdminClinic reports

Dashboard 1 endpoint

MethodPathAuthPurpose
GET/api/dashboard/statsAdmin · RecepDashboard statistics

Payments 2 endpoints

MethodPathAuthPurpose
POST/api/payments/webhookAnonymousPayment provider webhook
POST/api/payments/mock/payAnonymousMock pay (dev/demo)

Plus GET /health — no auth, not under /api — a liveness/readiness probe (200 healthy / 503 unhealthy).

Run it locally

Getting started

Each app runs independently. Start the API first, then either or both frontends.

Backend API :5180

# from /backend $ dotnet run # Swagger → /swagger

Patient App :5173

# from /patient-app $ npm install $ npm run dev

Staff Dashboard :4321

# from /staff-dashboard $ npm install $ npm start

Seeded credentials

The database seeds one doctor with two services — General Consultation (30 min / 300 EGP) and Follow-up (15 min / 150 EGP) — with working days Sun–Thu. Doctor cards also carry rating, reviewCount, and yearsExperience.

RoleNameEmailPassword
Adminadmin@clinic.localAdmin#123
DoctorDr. Layla Hassandoctor@clinic.localDoc#123
ReceptionistMona Adelreception@clinic.localRecep#123
PatientAhmed Samirpatient@clinic.localPat#123
Postman collection: docs/postman/Clarity-Clinic.postman_collection.json Full API reference (browsable) → /docs/api-reference.html Frontend integration notes: FRONTEND.md