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).
Field Detail
Purpose Work the lead pipeline by status; open details; create leads
Entry CRM tab; back from detail
Source GET /crm/leads?page&limit&status (crm.controller.ts:37-45)
Filters status dropdown (server); source + "my leads" chips (client-side, per 04 §6 )
Primary CTA FAB New lead (crm.lead.manage)
Row avatar initials, name, email/phone, source icon, status chip, next follow-up due
States loading skeleton; empty ("No leads — create your first"); error(offline/5xx) + retry; 403 permission-gated tab
Pull-to-refresh RefreshIndicator bypasses cache
Sort server-fixed createdAt desc; client secondary sort (name) (proposed)
Analytics crm.leads.list, crm.leads.filter(status), crm.leads.open(id)
Field Detail
Purpose Full lead record: identity, status, placement, notes, follow-up timeline, convert
Source GET /crm/leads/:id (crm.controller.ts:53-57)
Sections identity card · pipeline card (status chip + timestamps) · placement card · follow-up timeline (chronological, lead.schema.ts:24-39) · notes
Actions Edit (sheet S3), Add follow-up (sheet), Convert to student (S4, gated by rules crm.service.ts:120-125,145-149)
Timeline followUps with completedAt checkmark; conversion entry when converted
States loading; 404 ("Lead not found"); permission mode read-only
Analytics crm.lead.open, crm.lead.followup.added, crm.lead.converted
Field Detail
Purpose Capture (min fields) or update a lead
Sources create: POST /crm/leads (crm.controller.ts:47-51); edit: PATCH /crm/leads/:id (crm.controller.ts:59-63)
Form 08_Form_Specifications.md §2 (13 fields, 3 required)
States 409 duplicate-email inline (crm.service.ts:42-47); 400 field errors
Motion modal sheet; error shake; success → detail refresh
Analytics crm.lead.create.{submit,success,duplicate}, crm.lead.update.{submit,success}
Field Detail
Purpose One-action promotion of lead → User + Student
API POST /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)
Confirm dialog: "Create student account from this lead?" (irreversible)
Result success → converted badge + link to student; error 400 → inline rule list
Analytics crm.lead.convert.{submit,success,failed(rule)}
Field Detail
Purpose Manage the application funnel by status; funnel stats header
Source GET /crm/admissions?page&limit&status (crm.controller.ts:103-111)
Header tiles counts + conversion rate from GET /crm/admissions/stats (crm.controller.ts:97-101; admission.service.ts:227-237)
Row name, email, status badge, submittedAt, pending-documents hint
CTA FAB New application
States as S1; stats tile shows its own loading/skeleton
Analytics crm.admissions.list, crm.admissions.filter(status), crm.admissions.stats.view
Field Detail
Purpose Application record: identity, status, documents, interview, workflow history, decision actions
Source GET /crm/admissions/:id (crm.controller.ts:113-117)
Sections identity 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 modes closed statuses block edit/decision UI (server also 400s, admission.service.ts:257-269)
Analytics crm.admission.open, crm.admission.document.added, crm.admission.interview.scheduled, crm.admission.decided, crm.admission.converted
Field Detail
Purpose Submit an application on behalf of applicant
Source POST /crm/admissions (crm.controller.ts:91-95) → status always submitted (admission.service.ts:43)
Form 08 §3 (name/email/phone/placement/notes)
Note no edit route for draft: server sets SUBMITTED directly; updates via PATCH only while open (admission.service.ts:81-93)
Analytics crm.admission.create.{submit,success}
Field Detail
Purpose Set interview slot, panel, mode; optional feedback
Source POST /crm/admissions/:id/schedule-interview (crm.controller.ts:134-141) → status interview_scheduled (admission.service.ts:130-132)
Inputs scheduledAt*, panel[] (staff multi-pick), mode online/offline, feedback
Analytics crm.admission.interview.scheduled
Field Detail
Purpose Approve / Reject / Waitlist with optional comment
Source POST /crm/admissions/:id/decision (crm.controller.ts:143-147; admission.service.ts:136-170)
Guard only from decidable statuses; 400 otherwise (admission.service.ts:141-145)
Confirm reject/waitlist confirm copy ("reversible? no — closed once decided")
Analytics crm.admission.decided{approve,reject,waitlist}
Field Detail
Purpose See marketing campaigns; create new
Source GET /crm/campaigns?page&limit (crm.controller.ts:77-81)
Row name, type icon, status badge, dates, metrics snapshot (leadsGenerated etc.)
CTA FAB New campaign (crm.campaign.manage)
Gap no campaign detail/edit/delete endpoints — row tap is informational-only today
Analytics crm.campaigns.list, crm.campaign.open
Field Detail
Purpose Register a campaign (name*, description, type, status, start/end date)
Source POST /crm/campaigns (crm.controller.ts:83-87; create-campaign.dto.ts:5-34)
Analytics crm.campaign.create.{submit,success}
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 .
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).
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.