2 roles
student and instructor experiences
~31
unit and bloc tests
AR / EN
bilingual from the first screen
CI
format, analyze, test, build on every push
The brief
A driving school running on phone calls and cash
Lessons were booked by phone, paid in cash on the day, and tracked in nobody’s system. Two students could turn up for the same hour, and a slot could only be held once someone at the school confirmed it by hand.
Qeyadah gives students one place to book, pay a deposit, practise the theory exam, and request their certificate. Instructors get their own app for the week ahead, leave, attendance, and earnings. Both run in Arabic and English from the same codebase.
I was the only Flutter developer, building every feature module on top of the school’s shared platform layer. Each feature is a Cubit over a domain layer that returns typed Either<Failure, T> results, so a failed payment and a dropped connection reach the UI the same way: a clear, localized message with a retry.


The hard part
A deposit that releases the slot on its own
A student holds a slot by sending half the lesson price through Sham Cash and entering the transaction number in the app. The school verifies it, and the booking is confirmed.
If the money never arrives, the hold has to expire without anyone stepping in — otherwise one unpaid booking can block an instructor’s calendar indefinitely. The deposit screen makes the deadline visible with a live countdown, and the amount calculator behind it is covered by unit tests, because a wrong number here is a real money problem.


What I’d change next
When two students race for the same slot, the backend answers with an HTTP 409 and a free-text message, and the app reads that text to choose the Arabic or English explanation. It works, but it breaks silently the day someone rewords the message.
The fix is a stable conflict_code from the API, mapped to copy on the client. Same experience for the student, with no dependency on wording neither side promised to keep.
Stack
Booking and payment logic are unit-tested; the integration test suite is scaffolded but not yet complete.
