15 - Flutter Implementation Guide (Houses Module)
- 1. Feature folder
- 2. Model (mirror schema exactly)
- 3. Repository (dio)
- 4. Cubits
- 5. Screens
- 6. Validation (client mirror of DTOs)
- 7. Navigation (go_router)
- 8. DI registration (get_it)
- 9. Permissions & auth
- 10. Testing
- 11. Forward-looking hooks
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)→ parsedata+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 forConflictFieldError(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
| Order | Screen | Key widgets | Source |
|---|---|---|---|
| 1 | Houses list | HouseColorCard grid, AppPagination, FAB | 06 §1 |
| 2 | House editor (sheet/dialog) | ColorPickerField, ConflictFieldError | 06 §3 |
| 3 | House detail | HouseHeader, HouseCountBadge, MemberTile | 06 §2 |
6. Validation (client mirror of DTOs)
- Form rules per
08§2: name/code requiredIsString(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 per00-shared/07; JWT viaAppDiointerceptor (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);resolveHouseColorfallback paths (11§3); modelfromJsonfor 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.mdhas no houses items); do NOT scaffold ahead of the schema (house.schema.ts:9-19). - QR member check-in
(forward-looking):mobile_scannerdependency flagged in00-shared/11§1. - Push on house events
(forward-looking): notification channels undefined. - Analytics events
houses.*(proposed)(05Analytics section).