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

The house form (create + edit share one form, 05 §3 / 06 §3). Field rules are a client mirror of CreateHouseDto (create-house.dto.ts:4-22). Form behavior conventions from 00-shared/03 and validation patterns from 00-shared/07.


1. Form map

FieldWidgetRequiredDTO ruleServer behavior
NameAppTextField@IsString() (create-house.dto.ts:5-7)trimmed (house.schema.ts:9-10)
CodeAppTextField@IsString() (create-house.dto.ts:9-11)trimmed (house.schema.ts:12-13); unique per tenant (house.schema.ts:23)
ColorColorPickerField@IsOptional() @IsString() (create-house.dto.ts:13-16)stored verbatim, any string (house.schema.ts:15-16)
MottoAppTextField (multiline)@IsOptional() @IsString() (create-house.dto.ts:18-21)stored verbatim (house.schema.ts:18-19)

2. Client validation (mirror of DTO)

FieldClient ruleError copy
Namenon-empty after trim"Name is required."
Codenon-empty after trim"Code is required."
Color#RRGGBB or preset token"Use a hex color like #BA1A1A."
Motto≤ 120 chars (soft cap, not server-enforced)-
  • Server returns 400 for DTO violations (class-validator) - client mirrors first; any server 400 maps to the field by message/property (00-shared/07 §4).

3. Conflict handling (the critical path)

  • Duplicate code on create → 409 House code "X" already exists. (houses.service.ts:19-21). Rendered by ConflictFieldError under Code (07 §6), verbatim; focus moves to Code.
  • Duplicate code on update → same service path? No: update does not re-check duplicates (houses.service.ts:42-49) - it relies on the unique index {tenantId, code} (house.schema.ts:23). MongoDB E11000 surfaces as a generic server error; client must still render 409-style copy from the API error mapping (00-shared/07 §4) - QA item 14 §2.5.
  • Duplicate name or color → allowed by design (no check, no index); client may warn softly ("Another house uses this color") but must not block.

4. Update-mode quirk (PATCH semantics)

PATCH /houses/:id reuses CreateHouseDto as the body type (houses.controller.ts:44); name + code are required in the request body even for edits. The form therefore:

  • Prefills all four fields from the loaded house.
  • Submits the complete field set on Save (never partial).
  • Documents this in code: // houses: PATCH body = CreateHouseDto (full set), see houses.controller.ts:44.

If the API later gets a true partial DTO this behavior changes - keep it in one submission mapper (HouseFormCubit.toDto()).

5. Submission flow

HouseFormCubit:
  validate() -> fieldErrors
  submit()  -> create: POST /houses           (houses.controller.ts:24-28)
            -> update: PATCH /houses/:id      (houses.controller.ts:42-46)
  409 code  -> conflicts['code'] = server message  (single-flight, keep fields)
  404       -> snackbar "House not found" + close sheet (update race)
  success   -> pop sheet; list/detail refetch (response-driven, 13 §6)

6. Idempotency note

  • Create is not idempotent: double-tap protection via submitting flag (single-flight in HouseFormCubit, 13 §3). A retry after a timed-out 201 would hit 409 - recover by "Go to house" (conflict action navigates to detail if the code now exists).
  • Update is naturally idempotent ($set full DTO).

7. a11y & motion

  • Labels linked to inputs; error live-region announcements (00-shared/09).
  • Submit disabled until required fields non-empty (but keep 409 handling enabled for races).
  • Field error shake m-fast (00-shared/08); focus first invalid field.