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

The single form of the module (S3 — Room Editor). Field rules derive from create-room.dto.ts (server truth) plus the schema (room.schema.ts); client-side rules are (proposed) where the server imposes none. Markings: (planned) = needs backend change, (forward-looking) = future.


1. Form overview

CreateEdit
Route/rooms/new/rooms/:id/edit
EndpointPOST /api/v1/rooms (rooms.controller.ts:24-28)PATCH /api/v1/rooms/:id (rooms.controller.ts:42-46)
Payload DTOCreateRoomDto (create-room.dto.ts:11-38)same CreateRoomDto — there is no update-room.dto.ts; name+code are required even on PATCH (OQ-6, rooms.controller.ts:44)
GuardJwtAuthGuard; client gates by rooms.create / rooms.update (server RBAC (planned) — OQ-2)same
Prefillnone (empty form)full Room doc from S2 (GET /rooms/:idrooms.controller.ts:36-40)

2. Field matrix

#FieldRequiredServer rule (source)Client rule (proposed)Notes
F1name@IsString (create-room.dto.ts:12-14); trim: true (room.schema.ts:18-19)non-empty; ≤ 120 chars; trimmed
F2code@IsString (create-room.dto.ts:16-18); trim (room.schema.ts:21-22); unique per tenant (create 409 rooms.service.ts:19-21; unique index room.schema.ts:38)non-empty; pattern [A-Z0-9-]{2,24}; uppercase suggestion; async duplicate hint (proposed)edit-path duplicate check (planned) OQ-1
F3capacity@IsNumber only (create-room.dto.ts:20-23) — no bounds (OQ-7)integer ≥ 1; reject < 1 and non-integer input; warn > 10 000server @Min(1) (planned)
F4type❌ (default classroom)@IsEnum(RoomType) (create-room.dto.ts:25-28); default classroom (room.schema.ts:27-28)dropdown of RoomType values (room.schema.ts:7-14)
F5building@IsString (create-room.dto.ts:30-33)free text; suggestions from loaded list (proposed); ≤ 60 chars
F6facilities@IsArray (create-room.dto.ts:35-38) — element type unchecked; stored [String] (room.schema.ts:33-34)chip input; dedupe; max 12; each ≤ 32 chars (proposed)free-text tags; (forward-looking) structured equipment/status fields (OQ-5)

3. Validation behaviour

LayerRuleUX
Required (F1, F2)validate on submit + on blur after first submit attemptinline error under field; focus first invalid
F3 range< 1 blocked on input ((proposed)); 0/negative impossible client-sideinline hint "Capacity must be at least 1"
F2 uniqueness (create)async check (proposed): debounce 300 ms, match against GET /rooms client list; server 409 is authoritativeinline ✓ / ✗ under Code; 409 → scroll-to-field + error box
F2 uniqueness (edit)not checkable client-side reliably (list may be paginated); server check (planned) OQ-1warning copy "Code must be unique"; server 500 today → mapped to generic error + support note (proposed)
Enum (F4)server 400 if out-of-range — impossible via dropdown
Submitfull DTO serialized; unknown keys never sent (whitelist = DTO fields)Save button loading; fields disabled

4. Submit semantics

  • Create: on 201 → pop to S2 (detail) + snackbar "Room created" + cache invalidation.
  • Edit: on 200 → pop to S2 + snackbar "Room updated"; S2 refetches (or reconciles from response doc — updateById returns the updated doc, base.repository.ts:57-66).
  • 409 (create): form kept, inline duplicate error, no reset.
  • 400: map details[] → field errors (envelope convention, 00-shared/07).
  • 404 (edit): pop + snackbar "Room not found".
  • Offline: block submit, banner, draft kept in memory (no autosave).
  • Concurrent edit (proposed): version increments server-side (base.repository.ts:63); client sends baseVersion (planned) for If-Match-style conflict → "Room was updated elsewhere" dialog with reload/discard.

5. Dirty & discard

  • Dirty = any field differs from the initial model (or any chip added/removed).
  • Back/close with dirty → AppDialog "Discard changes?" [Keep editing] [Discard].
  • No autosave; draft lost on discard.

6. Keyboard & a11y

  • Order: F1 → F2 → F4 (dropdown) → F3 (numeric) → F5 → F6 (chip input).
  • F3 keyboard: TextInputType.number; F1/F2/F5: text with autocapitalize words (F2 characters + uppercase transform (proposed)).
  • Labels linked; errors in live regions; scroll-to-first-invalid; keyboard avoidance (00-shared/09).

7. Error-code → copy map (proposed)

CodeCopy
DUPLICATE_RESOURCE (409)"A room with this code already exists." (code field)
VALIDATION_ERROR (400)per-field messages from details[]
RESOURCE_NOT_FOUND (404)"This room no longer exists."
RATE_LIMITED (429)"Too many requests — try again shortly."
5xx"Something went wrong (requestId …)."