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

08 — Form Specifications (CRM Module)

Exact field-by-field form contracts. Validation mirrors server DTOs (class-validator); field sources are cited. Shared form UX: labels linked, per-field errors under fields (00-shared/06 §5), double-submit guard (00-shared/08 §6), keyboard types per field.


1. Form rules (all forms)

  • Required = server-required (server is authoritative; client pre-validates).
  • MongoId fields render as dropdowns/pickers fed by the owning module (academics grade/section/academicYear/class; staff for assignment/panel) — cross-module reads (planned) where endpoints are missing; fallback: raw-id field hidden in "Advanced".
  • 400 VALIDATION_ERROR details map field → message under the matching field.
  • Optimistic updates: never for create/submit; only for safe toggles (00-shared/06 §3.5).

2. Lead Form (S3) — create POST /crm/leads / edit PATCH /crm/leads/:id

FieldReqControlValidation (server)DefaultSource
firstNametext@IsStringcreate-lead.dto.ts:12-14
middleNametextoptional stringcreate-lead.dto.ts:16-19
lastNametext@IsStringcreate-lead.dto.ts:21-23
emailtext (.emailAddress, autofill email)@IsEmail; stored lowercase (lead.schema.ts:52-53)create-lead.dto.ts:25-27
phonetext (.phone, autofill tel)optional stringcreate-lead.dto.ts:29-32
sourcedropdownenum 6 valueswebsite (lead.schema.ts:58)create-lead.dto.ts:34-37
statusdropdown (Advanced)enum 5 valuesnew (lead.schema.ts:61)create-lead.dto.ts:39-42
gradeIddropdown@IsMongoIdcreate-lead.dto.ts:44-47
sectionIddropdown@IsMongoIdcreate-lead.dto.ts:49-52
academicYearIddropdown@IsMongoIdcreate-lead.dto.ts:54-57
classIddropdown@IsMongoIdcreate-lead.dto.ts:59-62
notesmultilineoptional stringcreate-lead.dto.ts:64-67
assignedTostaff dropdown@IsMongoIdcreate-lead.dto.ts:69-72

Edit-only fields: closedReason (string, update-lead.dto.ts:77-80).

Conditional logic

  • status = closed → reveal closedReason (client); server auto-stamps closedAt when reason absent (crm.service.ts:94-96).
  • status = converted → blocked in form; Convert flow only (S4).
  • Placement warning when editing without grade/year/class: "Set all three to enable conversion" (rule at crm.service.ts:145-149).
  • Submit → 409 duplicate email banner (crm.service.ts:42-47): "A lead with this email already exists" + "Edit details" / "Go back".

3. Admission Form (S7) — create POST /crm/admissions

FieldReqControlValidation (server)Source
firstNametext@IsStringcreate-admission.dto.ts:6-8
middleNametextoptionalcreate-admission.dto.ts:10-12
lastNametext@IsStringcreate-admission.dto.ts:14-16
emailtext .emailAddress@IsEmail; stored lowercase (admission.schema.ts:102-103)create-admission.dto.ts:18-20
phonetext .phoneoptional stringcreate-admission.dto.ts:22-25
gradeIddropdown@IsMongoIdcreate-admission.dto.ts:27-30
academicYearIddropdown@IsMongoIdcreate-admission.dto.ts:32-35
classIddropdown@IsMongoIdcreate-admission.dto.ts:37-40
notesmultilineoptional stringcreate-admission.dto.ts:42-45
  • Update form (PATCH /crm/admissions/:id, update-admission.dto.ts = PartialType) reuses this table; submit blocked client-side when status closed (server 400: admission.service.ts:257-269).
  • Note: no admission status field — server always creates submitted (admission.service.ts:43).

4. Follow-Up Form (S2 sheet) — POST /crm/leads/:id/follow-ups

FieldReqControlValidationSource
notemultiline@IsStringcreate-follow-up.dto.ts:5-7
scheduledAtdatetime picker@IsDateString (ISO)create-follow-up.dto.ts:9-11
completedAttoggle + datetime@IsDateString optionalcreate-follow-up.dto.ts:13-16
  • Display uses followUps[] (lead.schema.ts:24-39); createdBy set server-side from token (crm.service.ts:111).

5. Campaign Form (S11) — POST /crm/campaigns

FieldReqControlValidationDefaultSource
nametext@IsStringcreate-campaign.dto.ts:5-8
descriptionmultilineoptionalcreate-campaign.dto.ts:10-13
typedropdownenum 5email (campaign.schema.ts:30)create-campaign.dto.ts:15-18
statusdropdownenum 4draft (campaign.schema.ts:33)create-campaign.dto.ts:20-23
startDatedate picker@IsDateStringcreate-campaign.dto.ts:25-28
endDatedate picker@IsDateStringcreate-campaign.dto.ts:30-33
  • Client: endDate ≥ startDate (no server check today — flagged).
  • No edit form (no PATCH endpoint) — (planned).

6. Document Upload Form (S6 sheet) — POST /crm/admissions/:id/documents

FieldReqControlValidationSource
typedropdownenum tc/marksheet/certificate/photo/othercreate-admission-document.dto.ts:5-8; admission.schema.ts:27-33
fileIdfile pick → storage upload (storage provider; upload endpoint (planned))@IsStringcreate-admission-document.dto.ts:10-12
filenameauto from fileoptional string, defaults to fileId server-side (admission.service.ts:107)create-admission-document.dto.ts:14-17
  • Server appends doc + auto-transitions submitted → documents_pending (admission.service.ts:112-114).

7. Interview Form (S8 sheet) — POST /crm/admissions/:id/schedule-interview

FieldReqControlValidationDefaultSource
scheduledAtdatetime picker@IsDateStringschedule-interview.dto.ts:11-14
panelstaff multi-pick chipsarray of @IsMongoIdschedule-interview.dto.ts:16-20
modesegmented online/offlineenumoffline (admission.schema.ts:76-78)schedule-interview.dto.ts:22-25
feedbackmultilineoptional stringschedule-interview.dto.ts:27-30

8. Decision Form (S9 dialog) — POST /crm/admissions/:id/decision

FieldReqControlValidationSource
decisionradio/segmentedenum approve/reject/waitlistadmission-decision.dto.ts:4-8,10-13
commentmultilineoptional stringadmission-decision.dto.ts:15-18
  • Offered only from decidable statuses (admission.schema.ts:20-25); server 400 otherwise (admission.service.ts:141-145).
  • Reject/waitlist warnings per 06 §S9.

9. Autofill & accessibility

  • Lead/admission identity fields: given-name, family-name, email, tel autofill hints; labels linked; group headers (Applicant / Contact / Placement / Assignment); first-invalid focus; 409 banner in live region.