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 (Parents Module)

Every form field-by-field. Validation mirrors class-validator decorators exactly from src/modules/parents/dto/*.ts; server failures come back as VALIDATION_ERROR (400) with per-field details (http-exception.filter.ts:104-107). Client validates inline first; server 400 shadows client.


1. Create Parent — POST /parents (create-parent.dto.ts)

#FieldTypeRequiredServer decoratorNotes / UX
1userIdObjectId picker@IsMongoId() (create-parent.dto.ts:6-7)hidden behind UserPickerField (07 §6); the only required field
2occupationtextno@IsOptional() @IsString() (:10-12)autofill organization-title
3companytextno@IsOptional() @IsString() (:14-16)autofill organization
4annualIncomenumber (currency)no@IsOptional() no type decorator (:19-21)client NumberFormat parse; display as currency; no Min/Max server-side → client bounds 0–1e9 (propose server bounds)
5relationshipNotestext (multiline)no@IsOptional() @IsString() (:23-26)maxLength 500 (client)
6emergencyContactPrioritynumber (0–99)no@IsOptional() no type decorator (:28-30)default 0 (parent.schema.ts:24-25); client bounds 0–99; hint "lower = called first"
7pickupAuthorizationswitchno@IsOptional() no type decorator (:32-34)default false (parent.schema.ts:28); "Authorized to pick up child"

Submit → loading → server:

  • 201/200 data = parent doc (id, userId, flags, createdAt/updatedAt/version from BaseSchema, base.schema.ts:8-35).
  • 409 DUPLICATE_RESOURCE → banner + "Open existing profile" (parent.service.ts:32-34).
  • 400 details → per-field (http-exception.filter.ts:104-107).

Note on DTO typeless numerics/booleans: annualIncome, emergencyContactPriority, pickupAuthorization in CreateParentDto have no @IsNumber() / @IsBoolean() decorators (create-parent.dto.ts:18-34) — strings pass validation and would be stored. Client must send proper JSON types.

2. Update Parent — PATCH /parents/:id (update-parent.dto.ts)

Same field set as §1 minus userId (not updatable) plus metadata:

#FieldTypeRequiredServer decorator
8occupationtextno@IsOptional() @IsString() (update-parent.dto.ts:6-8)
9companytextno@IsOptional() @IsString() (:10-12)
10annualIncomenumberno@IsOptional() (:14-16)
11relationshipNotestextno@IsOptional() @IsString() (:18-20)
12emergencyContactPrioritynumberno@IsOptional() (:22-24)
13pickupAuthorizationbooleanno@IsOptional() (:26-28)
14metadataobjectno@IsOptional() (:32-34)

PATCH semantics: partial — only sent keys are set ($set, parent.service.ts:76); version incremented by repository (base.repository.ts:62-65). Client sends only changed fields. 404 "Parent not found." (parent.service.ts:77).

3. Link Parent — POST /parents/link/:studentId (link-parent.dto.ts)

#FieldTypeRequiredServer decoratorNotes / UX
15parentIdObjectId@IsMongoId() (link-parent.dto.ts:6-7)fixed by context (from parent detail)
16relationshipdropdown@IsString() (:19-20) — free string, no enummust send exactly one of mother|father|guardian|grandparent|relative|foster_parent (student-parent-link.schema.ts:7-14); client dropdown guarantees; invalid value → schema rejection → 500 (OQ-6)
17isPrimaryGuardianswitchno@IsOptional() (:23-24)default false; warn when another primary exists (OQ-5)
18financialResponsibilityswitchno@IsOptional() (:26-28)default false (student-parent-link.schema.ts:31)
19pickupAllowedswitchno@IsOptional() (:30-32)default true (student-parent-link.schema.ts:33-34) — opposite of profile pickupAuthorization
20emergencyPrioritynumber (0–99)no@IsOptional() (:34-36)default 0 (student-parent-link.schema.ts:36-37)

studentId comes from the route param, never the body (student-parent-link.service.ts:16-32).

Client-side pre-checks before submit:

  • pair (parentId, studentId) already in loaded links → warn duplicate (OQ-2).
  • isPrimaryGuardian true while another link for this student is primary → warn (OQ-5).
  • student picker required when opened from parent detail; parent picker required when opened from student detail.

Errors: 400 validation; 404 student (only if server later enforces — OQ-3); success → link doc in data.

4. Form-level rules (all)

  • Double-submit disabled while pending (00-shared/08 §6).
  • No optimistic writes for any parents mutation (links are consequential; server truth), except none — all server-first (00-shared/06 §3.5).
  • Undo: none for unlink (irreversible server-side); snackbar confirm only.
  • Keyboard: .next sequence, last .done; Enter submits (desktop).
  • Autofill hints on identity-ish fields (occupation/company).
  • Error copy: envelope message for business 4xx (409/404); codes for the rest (07_API_Conventions.md §11).

Client-side error priority (all forms)

  1. 400 VALIDATION_ERROR → field.
  2. 404 RESOURCE_NOT_FOUND → banner + context action.
  3. 409 DUPLICATE_RESOURCE → inline + link to existing.
  4. 422 BUSINESS_RULE_VIOLATION → banner (not produced by this module today).
  5. 429 RATE_LIMITED → countdown.
  6. 5xx → AppErrorState + requestId.