QMS Ataa
School visits, standards, indicators, evaluations and corrective plans, over a membership matrix that spans stage officers, domain owners, visit teams and central quality management. Comment threads carry photos, video and voice notes.
QMS and OPS ship as separate products on one platform. What a member sees, and what they are allowed to approve, is resolved per membership rather than per screen — so the module map below is not a menu, it is a permission model.
Every screen asks the backend who is looking before it decides what to render. Approval state is the sharpest case: it is computed as a SQL CASE over the viewer’s role, so one plan legitimately reads “approved” to a director and “awaiting” to the officer who filed it.
OPS reuses the QMS widget library, tokens and typography exactly — then ships under its own package id, its own Firebase project and its own name. Sharing the surface without sharing the identity was a deliberate constraint, and the reason the second app took weeks instead of months.
School visits, standards, indicators, evaluations and corrective plans, over a membership matrix that spans stage officers, domain owners, visit teams and central quality management. Comment threads carry photos, video and voice notes.
The full planning chain — strategic goals, sub-goals, work plans, indicators — plus quarterly and annual evaluations with server-derived targets, PDF export, and approval gates that refuse to pass an incomplete plan.
The data field arrives as an object, a list, an integer id, or a plain string carrying a failure message — and sometimes not at all. A request missing a header returns raw text under HTTP 200, and a 401 returns a null body, so the session decision has to come from the status code alone. Every model is parsed defensively rather than through a generic deserializer.
Two users open the same plan and see opposite states. That is the contract, not a defect: the field is derived per requester. Caching it, or trusting a value fetched under a different account, produces bugs that only appear when a second person signs in.
The backend branches on a Set-From header — eight endpoints change shape for the app, one of them renaming its keys outright. Every model had to be built against a real response captured as the app, never as the admin panel.
Cairo is bundled at 400, 500, 600 and 700 as four separate files. With Regular alone, Flutter synthesises the heavier weights by thickening strokes, which closes the counters of ص ض ه ع until they render as solid blobs. On an Arabic-first product that is a legibility bug, not a polish item.