Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

05 — Screen Inventory (CRM Module)

Every CRM screen, its intent, route, composition, states, permissions, platform behavior and events. Authoritative components in 00-shared/03; this file enumerates which ones each screen uses with module specifics. States = idle / loading / success / empty / error(offline, 409, 400) / disabled / permission. Analytics events follow {module}.{screen}.{action} (proposed).


1. Leads List (/crm/leads)

FieldDetail
PurposeWork the lead pipeline by status; open details; create leads
EntryCRM tab; back from detail
SourceGET /crm/leads?page&limit&status (crm.controller.ts:37-45)
Filtersstatus dropdown (server); source + "my leads" chips (client-side, per 04 §6)
Primary CTAFAB New lead (crm.lead.manage)
Rowavatar initials, name, email/phone, source icon, status chip, next follow-up due
Statesloading skeleton; empty ("No leads — create your first"); error(offline/5xx) + retry; 403 permission-gated tab
Pull-to-refreshRefreshIndicator bypasses cache
Sortserver-fixed createdAt desc; client secondary sort (name) (proposed)
Analyticscrm.leads.list, crm.leads.filter(status), crm.leads.open(id)

2. Lead Detail (/crm/leads/:id)

FieldDetail
PurposeFull lead record: identity, status, placement, notes, follow-up timeline, convert
SourceGET /crm/leads/:id (crm.controller.ts:53-57)
Sectionsidentity card · pipeline card (status chip + timestamps) · placement card · follow-up timeline (chronological, lead.schema.ts:24-39) · notes
ActionsEdit (sheet S3), Add follow-up (sheet), Convert to student (S4, gated by rules crm.service.ts:120-125,145-149)
TimelinefollowUps with completedAt checkmark; conversion entry when converted
Statesloading; 404 ("Lead not found"); permission mode read-only
Analyticscrm.lead.open, crm.lead.followup.added, crm.lead.converted

3. Lead Editor — Create / Edit (/crm/leads/new, sheet on detail)

FieldDetail
PurposeCapture (min fields) or update a lead
Sourcescreate: POST /crm/leads (crm.controller.ts:47-51); edit: PATCH /crm/leads/:id (crm.controller.ts:59-63)
Form08_Form_Specifications.md §2 (13 fields, 3 required)
States409 duplicate-email inline (crm.service.ts:42-47); 400 field errors
Motionmodal sheet; error shake; success → detail refresh
Analyticscrm.lead.create.{submit,success,duplicate}, crm.lead.update.{submit,success}

4. Convert Lead Flow (dialog from detail) — S4

FieldDetail
PurposeOne-action promotion of lead → User + Student
APIPOST /crm/leads/:id/convert (crm.controller.ts:71-75)
Pre-check (client)status not converted/closed; gradeId+academicYearId+classId present (else 400 server-side, crm.service.ts:145-149)
Confirmdialog: "Create student account from this lead?" (irreversible)
Resultsuccess → converted badge + link to student; error 400 → inline rule list
Analyticscrm.lead.convert.{submit,success,failed(rule)}

5. Admissions List (/crm/admissions)

FieldDetail
PurposeManage the application funnel by status; funnel stats header
SourceGET /crm/admissions?page&limit&status (crm.controller.ts:103-111)
Header tilescounts + conversion rate from GET /crm/admissions/stats (crm.controller.ts:97-101; admission.service.ts:227-237)
Rowname, email, status badge, submittedAt, pending-documents hint
CTAFAB New application
Statesas S1; stats tile shows its own loading/skeleton
Analyticscrm.admissions.list, crm.admissions.filter(status), crm.admissions.stats.view

6. Admission Detail (/crm/admissions/:id)

FieldDetail
PurposeApplication record: identity, status, documents, interview, workflow history, decision actions
SourceGET /crm/admissions/:id (crm.controller.ts:113-117)
Sectionsidentity card · status + submittedAt/decidedAt · documents list (type chips + filename) · interview card · workflow timeline (from→to, approver, comment, at — admission.schema.ts:52-67) · conversion card (when converted)
Actions (decidable only, admission.schema.ts:20-25)Add document, Schedule interview, Make decision; Convert only when approved
Read-only modesclosed statuses block edit/decision UI (server also 400s, admission.service.ts:257-269)
Analyticscrm.admission.open, crm.admission.document.added, crm.admission.interview.scheduled, crm.admission.decided, crm.admission.converted

7. Admission Editor — Create (/crm/admissions/new) — S7

FieldDetail
PurposeSubmit an application on behalf of applicant
SourcePOST /crm/admissions (crm.controller.ts:91-95) → status always submitted (admission.service.ts:43)
Form08 §3 (name/email/phone/placement/notes)
Noteno edit route for draft: server sets SUBMITTED directly; updates via PATCH only while open (admission.service.ts:81-93)
Analyticscrm.admission.create.{submit,success}

8. Interview Scheduler (sheet on S6)

FieldDetail
PurposeSet interview slot, panel, mode; optional feedback
SourcePOST /crm/admissions/:id/schedule-interview (crm.controller.ts:134-141) → status interview_scheduled (admission.service.ts:130-132)
InputsscheduledAt*, panel[] (staff multi-pick), mode online/offline, feedback
Analyticscrm.admission.interview.scheduled

9. Decision Dialog (on S6)

FieldDetail
PurposeApprove / Reject / Waitlist with optional comment
SourcePOST /crm/admissions/:id/decision (crm.controller.ts:143-147; admission.service.ts:136-170)
Guardonly from decidable statuses; 400 otherwise (admission.service.ts:141-145)
Confirmreject/waitlist confirm copy ("reversible? no — closed once decided")
Analyticscrm.admission.decided{approve,reject,waitlist}

10. Campaigns List (/crm/campaigns)

FieldDetail
PurposeSee marketing campaigns; create new
SourceGET /crm/campaigns?page&limit (crm.controller.ts:77-81)
Rowname, type icon, status badge, dates, metrics snapshot (leadsGenerated etc.)
CTAFAB New campaign (crm.campaign.manage)
Gapno campaign detail/edit/delete endpoints — row tap is informational-only today
Analyticscrm.campaigns.list, crm.campaign.open

11. Campaign Editor — Create (/crm/campaigns/new) — S11

FieldDetail
PurposeRegister a campaign (name*, description, type, status, start/end date)
SourcePOST /crm/campaigns (crm.controller.ts:83-87; create-campaign.dto.ts:5-34)
Analyticscrm.campaign.create.{submit,success}

Shared components used

AppTextField, AppButton, AppSnackbar, AppCard, AppListTile, AppBottomSheet, AppDialog, AppMenu, AppSkeleton, AppEmptyState, AppOfflineBanner, AppFAB, AppChips, AppBadge, AppAvatar, AppSegmentedButton, AppDatePicker, AppTimeline. Module-specific: LeadStatusChip, LeadSourceIcon, FollowUpCard, StatusBadge, WorkflowTimeline, DocumentCard, InterviewCard, FunnelStatCard, ConvertDialog — defined in 07_Component_Library.md.

Analytics events (proposed)

crm.lead.{list,filter,open,create.*,update.*,followup.added,convert.*}, crm.admission.{list,filter,open,create.*,document.added,interview.scheduled,decided,converted,stats.view}, crm.campaign.{list,open,create.*} (all proposed).

Keyboard, landscape, tablet, desktop

  • Forms: keyboard-avoid + ScrollView; email → .emailAddress; phone → .phone; dates via picker.
  • Tablet/desktop: two-pane list/detail (S1↔S2, S5↔S6); dialogs stay centered cards.
  • Timeline and workflow lists scroll independently on tablet detail pane.