Screen MapDashboard
Roles and lifecycles
Status, role and lifecycle tables for the dashboard. Red cells are gaps.
Roles and permissions
| Page or action | apps | dashboard | admin | super_admin | Enforced where |
|---|---|---|---|---|---|
| Overview and charts | No | Yes | Yes | Yes | ProtectedRoute + Convex dashboard |
| Profile (own) | No | Yes | Yes | Yes | overview.view + self exemption |
| Orders list, detail, facets | No | No | Yes | Yes | orders.view + Convex admin |
| Update order status | No | No | Yes | Yes | Page gate + orderHistory admin |
| Reprocess order stamps | No | No | Yes | Yes | AdminOnly + Convex admin |
| Link orphan order to user | No | No | API only | API only | No UI; API only |
| Checkout sessions, force expire | No | No | Yes | Yes | orders.view + Convex admin |
| Export (orders, users, reviews, audit) | No | No | Yes | Yes | AdminOnly + exports admin |
| Users list and detail | No | UI blocks, server allows | Yes | Yes | users.view; Convex only dashboard |
| Edit user profile | No | No | Yes | Yes | isAdmin + auth mutations |
| Change user role | No | No | UI hides, server allows apps/dashboard | Yes | UI super_admin; server admin partial |
| Suspend, activate, restore user | No | No | Yes | Yes | isAdmin; admin target needs super |
| Soft delete user | No | No | UI blocks, server allows | Yes | UI super_admin; server admin |
| Hard delete user | No | No | No | Yes | isSuperAdmin + super_admin server |
| Bulk edit users (max 500) | No | No | Yes | Yes | Page gate + auth mutations |
| Create user | No | No | No | Info page only | users.create; page is explainer only |
| Routine step CRUD, reorder | No | No | Yes | Yes | users.update + beauty admin |
| Loyalty reset progress, revoke voucher | No | No | Yes | Yes | Page gate + loyalty admin |
| Support list, detail, reply, status | No | Yes | Yes | Yes | support.view + Convex dashboard |
| Ratings list, approve, reject, feature | No | Yes | Yes | Yes | ratings.view + Convex dashboard |
| Ratings bulk moderate, delete | No | UI allows, server refuses | Yes | Yes | No UI gate; server admin |
| Pending, Flagged, Blocked, Reports pages | No | UI blocks, lists open on server | Yes | Yes | ratings.update; lists dashboard on server |
| Resolve or dismiss report | No | No | Yes | Yes | AdminOnly + Convex admin |
| Notifications: read Messages, Flows, Templates, delivery log | No | Yes | Yes | Yes | requireDashboardAccess (messages.ts, flows.ts queries) |
| Send, schedule, cancel or delete a message | No | No | Yes | Yes | AdminOnly + requireAdminAccess (messages.ts) |
| Create, edit, activate or delete a flow; install a flow template | No | No | Yes | Yes | AdminOnly + requireAdminAccess (flows.ts) |
| Template CRUD, queue cancel/retry/process | No | No | Yes | Yes | AdminOnly + requireAdminAccess (mutations.ts) |
| Webhooks view, deliveries | No | No | Yes | Yes | webhooks.view + Convex admin |
| Webhook create, edit, delete | No | No | Yes, but matrix says super_admin | Yes | hasRole admin; matrix says super_admin |
| Audit log view | No | No | Yes | Yes | audit.view + Convex admin |
Sidebar navigation
| Section | Item | Route | Visible to |
|---|---|---|---|
| Overview | Dashboard | /dashboard/overview | dashboard and up |
| Commerce | Products | /dashboard/products | dashboard and up |
| Commerce | Orders | /dashboard/orders | admin and up |
| Commerce | All Orders | /dashboard/orders | admin and up |
| Commerce | Checkout Sessions | /dashboard/orders/checkout-sessions | admin and up |
| Commerce | Vouchers | /dashboard/vouchers | dashboard and up (Audit child: admin) |
| Customers | Users | /dashboard/users | admin and up |
| Customers | All Users | /dashboard/users | admin and up |
| Customers | Routine Steps | /dashboard/users/routine-steps | admin and up |
| Customers | Loyalty | /dashboard/loyalty | dashboard and up (Members, Audit: admin) |
| Customers | Support Inbox | /dashboard/support | dashboard and up |
| Content & Engagement | Reviews & Moderation | /dashboard/ratings | dashboard and up |
| Content & Engagement | Reviews | /dashboard/ratings | dashboard and up |
| Content & Engagement | Pending Reviews | /dashboard/ratings/pending | admin and up |
| Content & Engagement | Flagged Reviews | /dashboard/ratings/flagged | admin and up |
| Content & Engagement | User Reports | /dashboard/ratings/reports | admin and up |
| Content & Engagement | User Blocks | /dashboard/ratings/blocked | admin and up |
| Content & Engagement | Notifications | /dashboard/notifications | dashboard and up |
| Content & Engagement | Notifications › Messages | /dashboard/notifications/messages | dashboard and up |
| Content & Engagement | Notifications › Flows | /dashboard/notifications/flows | dashboard and up |
| Content & Engagement | Notifications › Templates | /dashboard/notifications/templates | dashboard and up |
| Content & Engagement | Content Studio | /dashboard/content-management | admin and up (all children admin) |
| Platform | Webhooks | /dashboard/webhooks | admin and up |
| Platform | Audit Log | /dashboard/audit-log | admin and up |
| Footer | Documentation | https://docs.theraw.com.my | dashboard and up |
| Footer | Operations Manual | https://docs.theraw.com.my/docs/admin | dashboard and up |
| User card | Account Settings | /dashboard/profile | dashboard and up (apps sees AccessDenied) |
Marketing campaign lifecycle
| State | Entered by | Leaves to | Visible effect | Source |
|---|---|---|---|---|
| Draft | Create or Unpublish | Published, Scheduled | Not served to the app | types/marketing-campaign.ts:73 |
| Scheduled | Published, startsAt in future | Published | Hidden until start | types/marketing-campaign.ts:73 |
| Published | Published, inside window | Expired, Draft | Served when start <= now < end | BE content/mutations.ts:822 |
| Expired | Published, endsAt <= now | Draft, Published | Hidden; endsAt is exclusive | types/marketing-campaign.ts:73 |
| Deleted | Delete confirm | none | Row removed, no soft state | campaign-columns.tsx:60 |
Carousel slide lifecycle
| State | Entered by | Leaves to | Visible effect | Source |
|---|---|---|---|---|
| Inactive | isActive false | Active, Scheduled | Not shown | types/carousel.ts:100 |
| Scheduled | Active, now < startsAt | Active | Hidden until start | types/carousel.ts:100 |
| Active | Active, inside window | Expired, Inactive | Shown in placement | types/carousel.ts:100 |
| Expired | Active, now > endsAt | Inactive, Active | Hidden; endsAt is inclusive | types/carousel.ts:100 |
| Deleted | Delete confirm | none | Hard delete | carousel-listing.tsx:105 |
| Reordered | Drag handle | Same | displayOrder rewritten per placement | carousel-table.tsx:150 |
Product lifecycle
| State | Entered by | Leaves to | Visible effect | Source |
|---|---|---|---|---|
| Mirrored product | Shopify sync | Override exists | Shown from Shopify data | product-listing.tsx:84 |
| Override exists | Save All, bulk Featured or Badge | Override deleted | Marketing fields overlay Shopify | product-view.tsx:336 |
| Override deleted | Delete Override | Override exists | Reverts to Shopify data | product-view.tsx:467 |
| Group draft | Group created | Group published | Not published to app | publishProductGroup |
| Group published | Publish action | Group draft | Visible; republish refused | publishProductGroup |
| Group deleted | Delete group | none | Hard delete, products unassigned | group-delete-dialog.tsx:60 |
| Mirrored group | sourceCollectionHandle set | Unmirrored via edit | Membership edits refused | group-products-manager.tsx:244 |
Voucher template lifecycle
| State | Entered by | Leaves to | Visible effect | Source |
|---|---|---|---|---|
| Active | Created; Activate | Inactive, Deleted | Can be issued from | BE mutations.ts create |
| Inactive | Deactivate; Duplicate copy | Active | Cannot issue or use in pools | voucher-template-table.tsx |
| No Shopify node | Created or duplicated | Node created | Shows No node in table | mutations.ts:1403 |
| Node linked | First voucher issued | Node updated | Shows Synced | checkoutActions.ts:1158 |
| Node updated | Discount edit or Sync | Same | Writes to Shopify | mutations.ts:771 |
| Deleted | Delete with no vouchers | none | Refused once vouchers issued | mutations.ts:1625 |
Issued voucher lifecycle
| State | Entered by | Leaves to | Visible effect | Source |
|---|---|---|---|---|
| Active | Issue, stamp reward, reissue | Used, Expired, Cancelled | Redeemable | BE dashboard/mutations.ts |
| Used | Checkout, webhook, app | none | Terminal; no actions | BE dashboard/mutations.ts |
| Expired | Cron markExpiredVouchers | Active, new voucher | Shopify code removed | BE dashboard/mutations.ts:420 |
| Cancelled | Revoke, Delete, Reissue | none | Terminal; code removed | BE dashboard/mutations.ts |
| Extended | Extend expiry, future date | Active | Expired voucher reactivated | BE dashboard/mutations.ts:420 |
| Reissued | Reissue active or expired | New Active voucher | Source admin_reissue; old code kept | BE dashboard/mutations.ts:461 |
Code pool and Raya campaign lifecycle
| State | Entered by | Leaves to | Visible effect | Source |
|---|---|---|---|---|
| Draft | isActive false | Scheduled, Active | Hidden from claims | use-duit-raya.ts:193 |
| Scheduled | Active, now < start | Active | Not claimable yet | use-duit-raya.ts:193 |
| Active | Active, inside window | Ended, Inactive | Claimable | use-duit-raya.ts:193 |
| Ended | now > end | Inactive | Not claimable | use-duit-raya.ts:193 |
| Provisioning running | provisionPool | Done, Failed | Alert Provisioning codes | BE duitRaya/mutations.ts:546 |
| Provisioning failed | Run stopped | Resumed | Generate remaining (paused) | pool-detail-view.tsx:465 |
| Soft deleted | Delete or Deactivate | Active via Edit | isActive false | BE duitRaya/mutations.ts:1440 |
| Hard deleted | Super admin, pool detail | none | Codes and jobs removed in batches | BE duitRaya/mutations.ts:1440 |
Raya claim code lifecycle
| State | Entered by | Leaves to | Visible effect | Source |
|---|---|---|---|---|
| Unclaimed | Code generated | Claimed | Available | duitRayaClaimCodes |
| Claimed | Mobile or web claim | Unclaimed | claimedBy and Shopify code set | duitRayaClaimCodes |
| Reset | Reset Code | Unclaimed | Voucher deleted; Shopify code freed | duitRaya/mutations.ts:813 |
| Reset refused | Voucher already used | Claimed | Cannot reverse Shopify use | duitRaya/mutations.ts |
| Job pending | Start Generation | Processing | Progress bar | codes-view.tsx |
| Job processing | Worker picks up | Completed, Failed | processed / total live | codes-view.tsx |
| Job completed or failed | Worker ends | none | Failed shows Job failed alert | codes-view.tsx |
Loyalty campaign lifecycle
| State | Entered by | Leaves to | Visible effect | Source |
|---|---|---|---|---|
| Active | Created; Activate | Paused, Deleted | Mobile uses window filter | BE gamificationLoyalty/queries.ts:229 |
| Paused | Pause or bulk Pause | Active | isActive false | campaign-table.tsx |
| Window label | startsAt or endsAt | Same | Nd left, Ends today, Expired (display only) | campaign-columns.tsx:204 |
| Deactivated | Admin delete | Active | Soft deactivate only | BE gamificationLoyalty/mutations.ts |
| Hard deleted | Super admin, no participants | none | Row removed; refused with participants | BE gamificationLoyalty/mutations.ts |
Avatar lifecycle
| State | Entered by | Leaves to | Visible effect | Source |
|---|---|---|---|---|
| Active | Created; seeded | Inactive, Deleted | Offered in app | avatarCatalog.ts:67 |
| Inactive | Edit isActive false | Active | Hidden from app | avatarCatalog.ts:67 |
| Archived | Delete while in use | Active via edit | Shown as Inactive | avatar-catalog-manager.tsx:343 |
| Deleted | Delete while unused | none | Hard delete | avatar-catalog-manager.tsx:343 |