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

15 - Flutter Implementation Guide (Houses Module)

Module-specific build guide on top of 00-shared/11 (Flutter architecture, get_it DI, dio, go_router, flutter_bloc) and 00-shared/06 (state patterns). Order = recommended implementation sequence; each step maps to source files.


1. Feature folder

lib/features/houses/
  data/
    dto/house_dto.dart                     # envelope-payload mapper
    repositories/house_repository.dart     # houses API only
  domain/
    models.dart                            # House (immutable)
  presentation/
    cubits/house_list_cubit.dart, house_detail_cubit.dart,
        house_form_cubit.dart, house_members_cubit.dart
    screens/houses_list_screen.dart, house_detail_screen.dart
    widgets/house_color_card.dart, house_header.dart, member_tile.dart,
        color_picker_field.dart, house_count_badge.dart,
        delete_house_dialog.dart, conflict_field_error.dart

Widgets per 07_Component_Library.md; screens per 05/06. Students data lives in lib/features/students/ - houses imports its repository for the member join (13 §4) but owns no student model copy.

2. Model (mirror schema exactly)

House - house.schema.ts:8-19 + base.schema.ts:8-34: id (String ObjectId), name, code, color?, motto?, plus createdAt/updatedAt (DateTime, server sends strings - parse defensively) and version (int, read-only).

Immutable class + fromJson/toJson (repository maps envelope data). Never send tenantId/isDeleted/version (base.schema.ts:10-11, 20-21, 30-31).

3. Repository (dio)

  • Endpoints per 12_API_Mapping.md; base /api/v1 + ApiBearerAuth (houses.controller.ts:17-20).
  • fetch(page, limit) → parse data + meta {page, limit, totalItems, totalPages, hasNext, hasPrevious} (pagination-query.dto.ts:41-55).
  • create(dto) / update(id, dto) / getById(id) / remove(id).
  • Typed errors: ApiException(409, message) - message verbatim for ConflictFieldError (houses.service.ts:19-21); ApiException(404) for detail.
  • Update sends the full DTO body (PATCH = CreateHouseDto, houses.controller.ts:44).
  • Member join: separate students repository call (cross-module), single-flight per 00-shared/11 "AppDio".

4. Cubits

Per 13_State_Management.md: implement HouseListCubit first (pagination pattern), then HouseFormCubit (with conflicts map), then HouseDetailCubit + HouseMembersCubit. Use shared LoadState sealed class and pagination mixin (00-shared/06 §3.1-3.2).

5. Screens

OrderScreenKey widgetsSource
1Houses listHouseColorCard grid, AppPagination, FAB06 §1
2House editor (sheet/dialog)ColorPickerField, ConflictFieldError06 §3
3House detailHouseHeader, HouseCountBadge, MemberTile06 §2

6. Validation (client mirror of DTOs)

  • Form rules per 08 §2: name/code required IsString (create-house.dto.ts:5-11); color optional string, client enforces #RRGGBB (create-house.dto.ts:13-16); motto optional (:18-21).
  • Conflict messages: render server text verbatim (07 §6).
  • Color resolver before any paint: 11 §3 (resolveHouseColor).

7. Navigation (go_router)

/houses                      list   (auth + houses.read)
/houses/:id                  detail | deep-linkable

Create/edit forms = bottom sheets (phone) / dialogs (tablet), not routes (00-shared/03). Member rows deep-link to /students/:id (students module). Planned: /houses/:id/members standalone (planned) when server endpoint lands.

8. DI registration (get_it)

getIt.registerLazySingleton<HouseRepository>(() => HouseRepository(getIt()));
// students repository already registered by the students feature (imported for join)
// cubits factory-registered per screen (pass params via constructor args)

9. Permissions & auth

  • Gate FAB/menu on RBAC (permissions.constants.ts:46-49); 403 handling per 00-shared/07; JWT via AppDio interceptor (00-shared/11).
  • Note: RBAC guards on endpoints are not yet wired in the backend (AGENTS.md "Not yet implemented") - client still gates UI.

10. Testing

  • Unit: cubit state transitions incl. 409 → Conflict, 404 → NotFound + pop, members section failure isolation (13 §2-4); resolveHouseColor fallback paths (11 §3); model fromJson for absent color/motto.
  • Widget: golden per screen (00-shared/10 §6); color contrast matrix (14 §6.5); delete dialog copy.
  • Integration: mock dio with fixture envelopes; pagination boundary tests.
  • E2E seeds per 14 §7.

11. Forward-looking hooks

  • Points / leaderboard / events screens (planned) - no backend contract (IMPLEMENTATION_PLAN.md has no houses items); do NOT scaffold ahead of the schema (house.schema.ts:9-19).
  • QR member check-in (forward-looking): mobile_scanner dependency flagged in 00-shared/11 §1.
  • Push on house events (forward-looking): notification channels undefined.
  • Analytics events houses.* (proposed) (05 Analytics section).