fix(01-foundation): revise plans based on checker feedback
This commit is contained in:
@@ -15,6 +15,10 @@ files_modified:
|
|||||||
- lib/core/theme/app_theme.dart
|
- lib/core/theme/app_theme.dart
|
||||||
- lib/core/theme/theme_provider.dart
|
- lib/core/theme/theme_provider.dart
|
||||||
- lib/l10n/app_de.arb
|
- lib/l10n/app_de.arb
|
||||||
|
- test/core/database/database_test.dart
|
||||||
|
- test/core/theme/theme_test.dart
|
||||||
|
- test/core/theme/color_scheme_test.dart
|
||||||
|
- test/l10n/localization_test.dart
|
||||||
autonomous: true
|
autonomous: true
|
||||||
requirements:
|
requirements:
|
||||||
- FOUND-01
|
- FOUND-01
|
||||||
@@ -60,6 +64,18 @@ must_haves:
|
|||||||
- path: "lib/l10n/app_de.arb"
|
- path: "lib/l10n/app_de.arb"
|
||||||
provides: "German localization strings"
|
provides: "German localization strings"
|
||||||
contains: "tabHome"
|
contains: "tabHome"
|
||||||
|
- path: "test/core/database/database_test.dart"
|
||||||
|
provides: "Database unit and smoke tests (FOUND-01)"
|
||||||
|
contains: "schemaVersion"
|
||||||
|
- path: "test/core/theme/theme_test.dart"
|
||||||
|
provides: "Theme switching widget test (THEME-01)"
|
||||||
|
contains: "ThemeMode"
|
||||||
|
- path: "test/core/theme/color_scheme_test.dart"
|
||||||
|
provides: "ColorScheme unit tests (THEME-02)"
|
||||||
|
contains: "ColorScheme"
|
||||||
|
- path: "test/l10n/localization_test.dart"
|
||||||
|
provides: "Localization widget test (FOUND-03)"
|
||||||
|
contains: "AppLocalizations"
|
||||||
key_links:
|
key_links:
|
||||||
- from: "lib/core/theme/theme_provider.dart"
|
- from: "lib/core/theme/theme_provider.dart"
|
||||||
to: "shared_preferences"
|
to: "shared_preferences"
|
||||||
@@ -76,10 +92,10 @@ must_haves:
|
|||||||
---
|
---
|
||||||
|
|
||||||
<objective>
|
<objective>
|
||||||
Scaffold the Flutter project and build all core infrastructure: Drift database with migration workflow, Riverpod providers with code generation, theme definitions (sage & stone palette), and ARB localization strings.
|
Scaffold the Flutter project and build all core infrastructure: Drift database with migration workflow, Riverpod providers with code generation, theme definitions (sage & stone palette), and ARB localization strings. Create Wave 0 test scaffolding for database, theme, and localization.
|
||||||
|
|
||||||
Purpose: Establish every foundational dependency and pattern so Plan 02 can build the UI shell without any infrastructure work.
|
Purpose: Establish every foundational dependency and pattern so Plan 02 can build the UI shell without any infrastructure work. Tests provide fast feedback during execution.
|
||||||
Output: A Flutter project that compiles, has all dependencies resolved, code generation working, database initialized, and theme/localization ready for consumption by UI code.
|
Output: A Flutter project that compiles, has all dependencies resolved, code generation working, database initialized, theme/localization ready for consumption by UI code, and test scaffolding in place.
|
||||||
</objective>
|
</objective>
|
||||||
|
|
||||||
<execution_context>
|
<execution_context>
|
||||||
@@ -164,16 +180,21 @@ Output: A Flutter project that compiles, has all dependencies resolved, code gen
|
|||||||
</task>
|
</task>
|
||||||
|
|
||||||
<task type="auto">
|
<task type="auto">
|
||||||
<name>Task 2: Create core infrastructure — database, providers, theme, and localization strings</name>
|
<name>Task 2: Create core infrastructure, localization strings, and Wave 0 test scaffolding</name>
|
||||||
<files>
|
<files>
|
||||||
lib/core/database/database.dart,
|
lib/core/database/database.dart,
|
||||||
lib/core/providers/database_provider.dart,
|
lib/core/providers/database_provider.dart,
|
||||||
lib/core/theme/app_theme.dart,
|
lib/core/theme/app_theme.dart,
|
||||||
lib/core/theme/theme_provider.dart,
|
lib/core/theme/theme_provider.dart,
|
||||||
lib/l10n/app_de.arb
|
lib/l10n/app_de.arb,
|
||||||
|
lib/main.dart,
|
||||||
|
test/core/database/database_test.dart,
|
||||||
|
test/core/theme/theme_test.dart,
|
||||||
|
test/core/theme/color_scheme_test.dart,
|
||||||
|
test/l10n/localization_test.dart
|
||||||
</files>
|
</files>
|
||||||
<action>
|
<action>
|
||||||
1. Create `lib/core/database/database.dart` — the Drift database class:
|
1. Create `lib/core/database/database.dart` -- the Drift database class:
|
||||||
- Import `package:drift/drift.dart` and `package:drift_flutter/drift_flutter.dart`
|
- Import `package:drift/drift.dart` and `package:drift_flutter/drift_flutter.dart`
|
||||||
- Add `part 'database.g.dart';`
|
- Add `part 'database.g.dart';`
|
||||||
- Define `@DriftDatabase(tables: [])` with empty tables list (tables added in Phase 2)
|
- Define `@DriftDatabase(tables: [])` with empty tables list (tables added in Phase 2)
|
||||||
@@ -183,35 +204,35 @@ Output: A Flutter project that compiles, has all dependencies resolved, code gen
|
|||||||
- Static `_openConnection()` returns `driftDatabase(name: 'household_keeper', native: const DriftNativeOptions(databaseDirectory: getApplicationSupportDirectory))`
|
- Static `_openConnection()` returns `driftDatabase(name: 'household_keeper', native: const DriftNativeOptions(databaseDirectory: getApplicationSupportDirectory))`
|
||||||
- Import `package:path_provider/path_provider.dart` for `getApplicationSupportDirectory`
|
- Import `package:path_provider/path_provider.dart` for `getApplicationSupportDirectory`
|
||||||
|
|
||||||
2. Create `lib/core/providers/database_provider.dart` — Riverpod provider for database:
|
2. Create `lib/core/providers/database_provider.dart` -- Riverpod provider for database:
|
||||||
- Import riverpod_annotation and the database
|
- Import riverpod_annotation and the database
|
||||||
- Add `part 'database_provider.g.dart';`
|
- Add `part 'database_provider.g.dart';`
|
||||||
- Use `@Riverpod(keepAlive: true)` annotation (database must persist)
|
- Use `@Riverpod(keepAlive: true)` annotation (database must persist)
|
||||||
- Function `appDatabase(Ref ref)` returns `AppDatabase()`
|
- Function `appDatabase(Ref ref)` returns `AppDatabase()`
|
||||||
- The provider creates the singleton database instance
|
- The provider creates the singleton database instance
|
||||||
|
|
||||||
3. Create `lib/core/theme/app_theme.dart` — light and dark theme definitions:
|
3. Create `lib/core/theme/app_theme.dart` -- light and dark theme definitions:
|
||||||
- Define `AppTheme` class with static methods `lightTheme()` and `darkTheme()` returning `ThemeData`
|
- Define `AppTheme` class with static methods `lightTheme()` and `darkTheme()` returning `ThemeData`
|
||||||
- Light ColorScheme: `ColorScheme.fromSeed(seedColor: Color(0xFF7A9A6D), brightness: Brightness.light, dynamicSchemeVariant: DynamicSchemeVariant.tonalSpot).copyWith(surface: Color(0xFFF5F0E8), surfaceContainerLowest: Color(0xFFFAF7F2), surfaceContainerLow: Color(0xFFF2EDE4), surfaceContainer: Color(0xFFEDE7DC), surfaceContainerHigh: Color(0xFFE7E0D5), surfaceContainerHighest: Color(0xFFE0D9CE))`
|
- Light ColorScheme: `ColorScheme.fromSeed(seedColor: Color(0xFF7A9A6D), brightness: Brightness.light, dynamicSchemeVariant: DynamicSchemeVariant.tonalSpot).copyWith(surface: Color(0xFFF5F0E8), surfaceContainerLowest: Color(0xFFFAF7F2), surfaceContainerLow: Color(0xFFF2EDE4), surfaceContainer: Color(0xFFEDE7DC), surfaceContainerHigh: Color(0xFFE7E0D5), surfaceContainerHighest: Color(0xFFE0D9CE))`
|
||||||
- Dark ColorScheme: Same seed, `Brightness.dark`, `.copyWith(surface: Color(0xFF2A2520), surfaceContainerLowest: Color(0xFF1E1A16), surfaceContainerLow: Color(0xFF322D27), surfaceContainer: Color(0xFF3A342E), surfaceContainerHigh: Color(0xFF433D36), surfaceContainerHighest: Color(0xFF4D463F))`
|
- Dark ColorScheme: Same seed, `Brightness.dark`, `.copyWith(surface: Color(0xFF2A2520), surfaceContainerLowest: Color(0xFF1E1A16), surfaceContainerLow: Color(0xFF322D27), surfaceContainer: Color(0xFF3A342E), surfaceContainerHigh: Color(0xFF433D36), surfaceContainerHighest: Color(0xFF4D463F))`
|
||||||
- Both ThemeData set `useMaterial3: true` and use the respective ColorScheme
|
- Both ThemeData set `useMaterial3: true` and use the respective ColorScheme
|
||||||
|
|
||||||
4. Create `lib/core/theme/theme_provider.dart` — Riverpod provider for theme mode:
|
4. Create `lib/core/theme/theme_provider.dart` -- Riverpod provider for theme mode:
|
||||||
- Import riverpod_annotation, flutter/material.dart, shared_preferences
|
- Import riverpod_annotation, flutter/material.dart, shared_preferences
|
||||||
- Add `part 'theme_provider.g.dart';`
|
- Add `part 'theme_provider.g.dart';`
|
||||||
- `@riverpod class ThemeNotifier extends _$ThemeNotifier`
|
- `@riverpod class ThemeNotifier extends _$ThemeNotifier`
|
||||||
- `build()` method: read from SharedPreferences key `'theme_mode'`, parse to ThemeMode enum, default to `ThemeMode.system`
|
- `build()` method: read from SharedPreferences key `'theme_mode'`, parse to ThemeMode enum, default to `ThemeMode.system`
|
||||||
- `setThemeMode(ThemeMode mode)` method: update state, persist to SharedPreferences
|
- `setThemeMode(ThemeMode mode)` method: update state, persist to SharedPreferences
|
||||||
- Use `ref.read` pattern for async SharedPreferences access (NOT ref.watch — this is a Notifier, not build())
|
- Use `ref.read` pattern for async SharedPreferences access (NOT ref.watch -- this is a Notifier, not build())
|
||||||
- Helper: `_themeModeFromString(String? value)` and `_themeModeToString(ThemeMode mode)` for serialization
|
- Helper: `_themeModeFromString(String? value)` and `_themeModeToString(ThemeMode mode)` for serialization
|
||||||
|
|
||||||
5. Create `lib/l10n/app_de.arb` — German localization strings for all Phase 1 UI:
|
5. Create `lib/l10n/app_de.arb` -- German localization strings for all Phase 1 UI:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"@@locale": "de",
|
"@@locale": "de",
|
||||||
"appTitle": "HouseHoldKeaper",
|
"appTitle": "HouseHoldKeaper",
|
||||||
"tabHome": "Ubersicht",
|
"tabHome": "\u00dcbersicht",
|
||||||
"tabRooms": "Raume",
|
"tabRooms": "R\u00e4ume",
|
||||||
"tabSettings": "Einstellungen",
|
"tabSettings": "Einstellungen",
|
||||||
"homeEmptyTitle": "Noch nichts zu tun!",
|
"homeEmptyTitle": "Noch nichts zu tun!",
|
||||||
"homeEmptyMessage": "Lege zuerst einen Raum an, um Aufgaben zu planen.",
|
"homeEmptyMessage": "Lege zuerst einen Raum an, um Aufgaben zu planen.",
|
||||||
@@ -224,7 +245,7 @@ Output: A Flutter project that compiles, has all dependencies resolved, code gen
|
|||||||
"themeSystem": "System",
|
"themeSystem": "System",
|
||||||
"themeLight": "Hell",
|
"themeLight": "Hell",
|
||||||
"themeDark": "Dunkel",
|
"themeDark": "Dunkel",
|
||||||
"settingsSectionAbout": "Uber",
|
"settingsSectionAbout": "\u00dcber",
|
||||||
"aboutAppName": "HouseHoldKeaper",
|
"aboutAppName": "HouseHoldKeaper",
|
||||||
"aboutTagline": "Dein Haushalt, entspannt organisiert.",
|
"aboutTagline": "Dein Haushalt, entspannt organisiert.",
|
||||||
"aboutVersion": "Version {version}",
|
"aboutVersion": "Version {version}",
|
||||||
@@ -235,9 +256,9 @@ Output: A Flutter project that compiles, has all dependencies resolved, code gen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Note: Use proper German characters (umlauts) where appropriate. The tab labels "Ubersicht" should be "Ubersicht" and "Raume" should be "Raume" — but check CONTEXT.md which shows them without umlauts. Use umlauts in the ARB file: "Ubersicht", "Raume", "Uber" should actually be with umlauts if the font supports it. Per the CONTEXT.md the user specified "Ubersicht", "Raume", "Einstellungen" — follow exactly as specified there.
|
IMPORTANT: Use proper German umlauts throughout -- "Ubersicht" with umlaut (U+00DC), "Raume" with umlaut (U+00E4), "Uber" with umlaut (U+00DC). Per CONTEXT.md user decision: labels are "Ubersicht", "Raume", "Einstellungen" with umlauts.
|
||||||
|
|
||||||
6. Remove the default `lib/main.dart` content and replace with a minimal placeholder that imports ProviderScope (just enough to verify compilation — full wiring happens in Plan 02):
|
6. Remove the default `lib/main.dart` content and replace with a minimal placeholder that imports ProviderScope (just enough to verify compilation -- full wiring happens in Plan 02):
|
||||||
```dart
|
```dart
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
@@ -253,12 +274,41 @@ Output: A Flutter project that compiles, has all dependencies resolved, code gen
|
|||||||
8. Run Drift migration capture: `dart run drift_dev make-migrations`
|
8. Run Drift migration capture: `dart run drift_dev make-migrations`
|
||||||
This captures schema version 1 in `drift_schemas/` directory.
|
This captures schema version 1 in `drift_schemas/` directory.
|
||||||
|
|
||||||
9. Run `dart analyze` to verify riverpod_lint is active and no analysis issues exist.
|
9. Create Wave 0 test files:
|
||||||
|
|
||||||
|
a. `test/core/database/database_test.dart` (covers FOUND-01):
|
||||||
|
- Test that `AppDatabase(NativeDatabase.memory())` opens successfully
|
||||||
|
- Test that `schemaVersion` equals 1
|
||||||
|
- Test that the database can be closed without error
|
||||||
|
- Use in-memory database (`NativeDatabase.memory()`) for test isolation
|
||||||
|
|
||||||
|
b. `test/core/theme/color_scheme_test.dart` (covers THEME-02):
|
||||||
|
- Test that `AppTheme.lightTheme()` has `Brightness.light`
|
||||||
|
- Test that `AppTheme.darkTheme()` has `Brightness.dark`
|
||||||
|
- Test that both use sage green seed: verify `primary` color is in the green hue range
|
||||||
|
- Test that light surface color is warm (0xFFF5F0E8)
|
||||||
|
- Test that dark surface color is warm charcoal (0xFF2A2520), not cold gray
|
||||||
|
|
||||||
|
c. `test/core/theme/theme_test.dart` (covers THEME-01):
|
||||||
|
- Widget test: wrap a `MaterialApp` with `ProviderScope` and verify that `ThemeNotifier` defaults to `ThemeMode.system`
|
||||||
|
- Test that calling `setThemeMode(ThemeMode.dark)` updates state
|
||||||
|
- Test that calling `setThemeMode(ThemeMode.light)` updates state
|
||||||
|
- Use `SharedPreferences.setMockInitialValues({})` for test isolation
|
||||||
|
|
||||||
|
d. `test/l10n/localization_test.dart` (covers FOUND-03):
|
||||||
|
- Widget test: create a `MaterialApp` with `AppLocalizations.localizationsDelegates`, `supportedLocales: [Locale('de')]`, `locale: Locale('de')`
|
||||||
|
- Pump a widget that reads `AppLocalizations.of(context)` and displays `tabHome`
|
||||||
|
- Verify the rendered text contains the expected German string (with umlaut)
|
||||||
|
- Test that all critical keys are non-empty: `appTitle`, `tabHome`, `tabRooms`, `tabSettings`
|
||||||
|
|
||||||
|
10. Run `dart analyze` to verify riverpod_lint is active and no analysis issues exist.
|
||||||
|
|
||||||
|
11. Run `flutter test` to verify all Wave 0 tests pass.
|
||||||
</action>
|
</action>
|
||||||
<verify>
|
<verify>
|
||||||
<automated>cd /home/jlmak/Projects/jlmak/HouseHoldKeaper && dart run build_runner build --delete-conflicting-outputs 2>&1 | tail -5 && dart analyze 2>&1 | tail -5 && echo "PASS: Codegen and analysis clean"</automated>
|
<automated>cd /home/jlmak/Projects/jlmak/HouseHoldKeaper && dart run build_runner build --delete-conflicting-outputs 2>&1 | tail -5 && dart analyze 2>&1 | tail -5 && flutter test 2>&1 | tail -10 && echo "PASS: Codegen, analysis, and tests clean"</automated>
|
||||||
</verify>
|
</verify>
|
||||||
<done>database.dart defines AppDatabase with schemaVersion 1. database_provider.dart exposes AppDatabase via @riverpod. app_theme.dart provides lightTheme() and darkTheme() with sage green seed and warm surface overrides. theme_provider.dart provides ThemeNotifier with shared_preferences persistence and ThemeMode.system default. app_de.arb contains all German strings for Phase 1 screens. All .g.dart files generated successfully. drift_dev make-migrations has captured schema v1. dart analyze passes cleanly.</done>
|
<done>database.dart defines AppDatabase with schemaVersion 1. database_provider.dart exposes AppDatabase via @riverpod. app_theme.dart provides lightTheme() and darkTheme() with sage green seed and warm surface overrides. theme_provider.dart provides ThemeNotifier with shared_preferences persistence and ThemeMode.system default. app_de.arb contains all German strings for Phase 1 screens with proper umlauts (Ubersicht, Raume, Uber). All .g.dart files generated successfully. drift_dev make-migrations has captured schema v1. dart analyze passes cleanly. All 4 Wave 0 test files created and passing: database_test.dart, color_scheme_test.dart, theme_test.dart, localization_test.dart.</done>
|
||||||
</task>
|
</task>
|
||||||
|
|
||||||
</tasks>
|
</tasks>
|
||||||
@@ -268,6 +318,7 @@ Output: A Flutter project that compiles, has all dependencies resolved, code gen
|
|||||||
- `dart run build_runner build` completes without errors (generates .g.dart files)
|
- `dart run build_runner build` completes without errors (generates .g.dart files)
|
||||||
- `dart run drift_dev make-migrations` completes (schema v1 captured)
|
- `dart run drift_dev make-migrations` completes (schema v1 captured)
|
||||||
- `dart analyze` reports no errors (riverpod_lint active)
|
- `dart analyze` reports no errors (riverpod_lint active)
|
||||||
|
- `flutter test` passes (all Wave 0 tests green)
|
||||||
- `flutter build apk --debug` compiles (project structure valid)
|
- `flutter build apk --debug` compiles (project structure valid)
|
||||||
</verification>
|
</verification>
|
||||||
|
|
||||||
@@ -277,9 +328,10 @@ Output: A Flutter project that compiles, has all dependencies resolved, code gen
|
|||||||
- Riverpod providers created with @riverpod annotation and code generation
|
- Riverpod providers created with @riverpod annotation and code generation
|
||||||
- Light and dark theme definitions with sage & stone ColorScheme palette
|
- Light and dark theme definitions with sage & stone ColorScheme palette
|
||||||
- ThemeMode provider with shared_preferences persistence
|
- ThemeMode provider with shared_preferences persistence
|
||||||
- ARB localization file with all German strings for Phase 1
|
- ARB localization file with all German strings for Phase 1 using proper umlauts
|
||||||
- All code generation (.g.dart files) succeeds
|
- All code generation (.g.dart files) succeeds
|
||||||
- dart analyze passes cleanly with riverpod_lint active
|
- dart analyze passes cleanly with riverpod_lint active
|
||||||
|
- Wave 0 tests pass: database (FOUND-01), localization (FOUND-03), theme switching (THEME-01), color scheme (THEME-02)
|
||||||
</success_criteria>
|
</success_criteria>
|
||||||
|
|
||||||
<output>
|
<output>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ files_modified:
|
|||||||
- lib/features/home/presentation/home_screen.dart
|
- lib/features/home/presentation/home_screen.dart
|
||||||
- lib/features/rooms/presentation/rooms_screen.dart
|
- lib/features/rooms/presentation/rooms_screen.dart
|
||||||
- lib/features/settings/presentation/settings_screen.dart
|
- lib/features/settings/presentation/settings_screen.dart
|
||||||
|
- test/shell/app_shell_test.dart
|
||||||
autonomous: false
|
autonomous: false
|
||||||
requirements:
|
requirements:
|
||||||
- FOUND-03
|
- FOUND-03
|
||||||
@@ -56,6 +57,9 @@ must_haves:
|
|||||||
provides: "Theme switcher (SegmentedButton) + About section with grouped headers"
|
provides: "Theme switcher (SegmentedButton) + About section with grouped headers"
|
||||||
contains: "SegmentedButton"
|
contains: "SegmentedButton"
|
||||||
min_lines: 40
|
min_lines: 40
|
||||||
|
- path: "test/shell/app_shell_test.dart"
|
||||||
|
provides: "Navigation shell widget test (FOUND-04)"
|
||||||
|
contains: "NavigationBar"
|
||||||
key_links:
|
key_links:
|
||||||
- from: "lib/app.dart"
|
- from: "lib/app.dart"
|
||||||
to: "lib/core/router/router.dart"
|
to: "lib/core/router/router.dart"
|
||||||
@@ -84,10 +88,10 @@ must_haves:
|
|||||||
---
|
---
|
||||||
|
|
||||||
<objective>
|
<objective>
|
||||||
Build the navigation shell, all three screens (Home placeholder, Rooms placeholder, Settings with theme switcher), and wire everything into a launchable app with full theme and localization integration.
|
Build the navigation shell, all three screens (Home placeholder, Rooms placeholder, Settings with theme switcher), and wire everything into a launchable app with full theme and localization integration. Create the app shell widget test.
|
||||||
|
|
||||||
Purpose: Deliver a complete, launchable app that demonstrates the architecture established in Plan 01 -- users see the bottom navigation, can switch tabs, change themes, and all text comes from localization.
|
Purpose: Deliver a complete, launchable app that demonstrates the architecture established in Plan 01 -- users see the bottom navigation, can switch tabs, change themes, and all text comes from localization.
|
||||||
Output: An Android app that compiles, launches, and satisfies all Phase 1 success criteria.
|
Output: An Android app that compiles, launches, and satisfies all Phase 1 success criteria, with app shell test passing.
|
||||||
</objective>
|
</objective>
|
||||||
|
|
||||||
<execution_context>
|
<execution_context>
|
||||||
@@ -151,13 +155,14 @@ From lib/l10n/app_de.arb (generated AppLocalizations):
|
|||||||
<tasks>
|
<tasks>
|
||||||
|
|
||||||
<task type="auto">
|
<task type="auto">
|
||||||
<name>Task 1: Create router, navigation shell, and all three screens</name>
|
<name>Task 1: Create router, navigation shell, all three screens, and app shell test</name>
|
||||||
<files>
|
<files>
|
||||||
lib/core/router/router.dart,
|
lib/core/router/router.dart,
|
||||||
lib/shell/app_shell.dart,
|
lib/shell/app_shell.dart,
|
||||||
lib/features/home/presentation/home_screen.dart,
|
lib/features/home/presentation/home_screen.dart,
|
||||||
lib/features/rooms/presentation/rooms_screen.dart,
|
lib/features/rooms/presentation/rooms_screen.dart,
|
||||||
lib/features/settings/presentation/settings_screen.dart
|
lib/features/settings/presentation/settings_screen.dart,
|
||||||
|
test/shell/app_shell_test.dart
|
||||||
</files>
|
</files>
|
||||||
<action>
|
<action>
|
||||||
1. Create `lib/core/router/router.dart` -- GoRouter with StatefulShellRoute:
|
1. Create `lib/core/router/router.dart` -- GoRouter with StatefulShellRoute:
|
||||||
@@ -207,16 +212,24 @@ From lib/l10n/app_de.arb (generated AppLocalizations):
|
|||||||
- `ThemeMode.dark`: label `l10n.themeDark`, icon `Icons.dark_mode_outlined`
|
- `ThemeMode.dark`: label `l10n.themeDark`, icon `Icons.dark_mode_outlined`
|
||||||
- `selected: {ref.watch(themeNotifierProvider)}`
|
- `selected: {ref.watch(themeNotifierProvider)}`
|
||||||
- `onSelectionChanged: (s) => ref.read(themeNotifierProvider.notifier).setThemeMode(s.first)`
|
- `onSelectionChanged: (s) => ref.read(themeNotifierProvider.notifier).setThemeMode(s.first)`
|
||||||
- **Section 2 -- "Uber" (About):**
|
- **Section 2 -- "Über" (About):**
|
||||||
- Section header: same style, text from `l10n.settingsSectionAbout`
|
- Section header: same style, text from `l10n.settingsSectionAbout`
|
||||||
- ListTile: title from `l10n.aboutAppName`, subtitle from `l10n.aboutTagline`
|
- ListTile: title from `l10n.aboutAppName`, subtitle from `l10n.aboutTagline`
|
||||||
- ListTile: title "Version", subtitle from `l10n.aboutVersion` with version string (use package_info_plus or hardcode "0.1.0" for now -- package_info_plus can be added later if needed)
|
- ListTile: title "Version", subtitle from `l10n.aboutVersion` with version string (use package_info_plus or hardcode "0.1.0" for now -- package_info_plus can be added later if needed)
|
||||||
- A `Divider` between sections for visual separation
|
- A `Divider` between sections for visual separation
|
||||||
|
|
||||||
|
6. Create `test/shell/app_shell_test.dart` (covers FOUND-04):
|
||||||
|
- Widget test: wrap `MaterialApp.router(routerConfig: router)` in `ProviderScope` with localization delegates and `locale: Locale('de')`
|
||||||
|
- Pump and settle
|
||||||
|
- Verify that 3 `NavigationDestination` widgets are rendered
|
||||||
|
- Verify that the labels match the expected German strings from ARB (with umlauts): "Übersicht", "Räume", "Einstellungen"
|
||||||
|
- Verify that tapping a different destination changes `selectedIndex`
|
||||||
|
- Use `SharedPreferences.setMockInitialValues({})` for ThemeNotifier isolation
|
||||||
</action>
|
</action>
|
||||||
<verify>
|
<verify>
|
||||||
<automated>cd /home/jlmak/Projects/jlmak/HouseHoldKeaper && dart analyze 2>&1 | tail -10 && echo "PASS: All screens analyze cleanly"</automated>
|
<automated>cd /home/jlmak/Projects/jlmak/HouseHoldKeaper && dart analyze 2>&1 | tail -10 && flutter test test/shell/app_shell_test.dart 2>&1 | tail -10 && echo "PASS: Screens analyze cleanly, shell test passes"</automated>
|
||||||
</verify>
|
</verify>
|
||||||
<done>router.dart defines GoRouter with StatefulShellRoute.indexedStack and 3 branches. app_shell.dart renders NavigationBar with 3 tabs using localized labels and thematic icons (checklist, door, tune). home_screen.dart shows empty state with localized text and a button that navigates to /rooms. rooms_screen.dart shows empty state with localized text and action button. settings_screen.dart shows grouped sections: "Darstellung" with SegmentedButton theme switcher wired to ThemeNotifier, and "Uber" with app name, tagline, and version. All text loaded from AppLocalizations, zero hardcoded German strings in Dart code.</done>
|
<done>router.dart defines GoRouter with StatefulShellRoute.indexedStack and 3 branches. app_shell.dart renders NavigationBar with 3 tabs using localized labels (with proper umlauts) and thematic icons (checklist, door, tune). home_screen.dart shows empty state with localized text and a button that navigates to /rooms. rooms_screen.dart shows empty state with localized text and action button. settings_screen.dart shows grouped sections: "Darstellung" with SegmentedButton theme switcher wired to ThemeNotifier, and "Über" with app name, tagline, and version. All text loaded from AppLocalizations, zero hardcoded German strings in Dart code. app_shell_test.dart passes, verifying 3 navigation destinations with correct labels.</done>
|
||||||
</task>
|
</task>
|
||||||
|
|
||||||
<task type="auto">
|
<task type="auto">
|
||||||
@@ -247,17 +260,14 @@ From lib/l10n/app_de.arb (generated AppLocalizations):
|
|||||||
|
|
||||||
3. Run `dart run build_runner build --delete-conflicting-outputs` one final time to ensure all generated files are current (router may need regeneration if it uses @riverpod).
|
3. Run `dart run build_runner build --delete-conflicting-outputs` one final time to ensure all generated files are current (router may need regeneration if it uses @riverpod).
|
||||||
|
|
||||||
4. Run `flutter build apk --debug` to verify the entire app compiles for Android.
|
4. Verify the complete integration:
|
||||||
|
|
||||||
5. Verify the complete integration:
|
|
||||||
- `dart analyze` passes cleanly
|
- `dart analyze` passes cleanly
|
||||||
- `flutter test` passes (default test or any existing tests)
|
- `flutter test` passes (all tests including Wave 0 tests from Plan 01)
|
||||||
- The app structure matches the architecture from RESEARCH.md
|
|
||||||
</action>
|
</action>
|
||||||
<verify>
|
<verify>
|
||||||
<automated>cd /home/jlmak/Projects/jlmak/HouseHoldKeaper && flutter build apk --debug 2>&1 | tail -5 && echo "PASS: App compiles for Android"</automated>
|
<automated>cd /home/jlmak/Projects/jlmak/HouseHoldKeaper && dart analyze 2>&1 | tail -5 && flutter test 2>&1 | tail -10 && echo "PASS: Analysis clean, all tests pass"</automated>
|
||||||
</verify>
|
</verify>
|
||||||
<done>app.dart wires MaterialApp.router with GoRouter config, light/dark themes from AppTheme, themeMode from ThemeNotifier provider, and German localization delegates. main.dart wraps App in ProviderScope. The app compiles via `flutter build apk --debug` without errors. The complete architecture is in place: Drift database + Riverpod providers + GoRouter navigation + Material 3 theme + ARB localization.</done>
|
<done>app.dart wires MaterialApp.router with GoRouter config, light/dark themes from AppTheme, themeMode from ThemeNotifier provider, and German localization delegates. main.dart wraps App in ProviderScope. `dart analyze` passes cleanly. `flutter test` passes all tests (database, theme, color scheme, localization, app shell). The complete architecture is in place: Drift database + Riverpod providers + GoRouter navigation + Material 3 theme + ARB localization. Final confirmation: `flutter build apk --debug` compiles without errors.</done>
|
||||||
</task>
|
</task>
|
||||||
|
|
||||||
<task type="checkpoint:human-verify" gate="blocking">
|
<task type="checkpoint:human-verify" gate="blocking">
|
||||||
@@ -277,7 +287,7 @@ Verification checklist:
|
|||||||
8. Dark theme shows warm charcoal-brown surfaces (not cold gray)
|
8. Dark theme shows warm charcoal-brown surfaces (not cold gray)
|
||||||
9. System theme follows device setting
|
9. System theme follows device setting
|
||||||
10. Theme preference persists across app restart
|
10. Theme preference persists across app restart
|
||||||
11. "Uber" section shows app name and tagline
|
11. "Über" section shows app name and tagline
|
||||||
12. Overall sage and stone palette feels calm and warm
|
12. Overall sage and stone palette feels calm and warm
|
||||||
</action>
|
</action>
|
||||||
<verify>Human visually confirms all 12 checklist items pass</verify>
|
<verify>Human visually confirms all 12 checklist items pass</verify>
|
||||||
@@ -285,7 +295,7 @@ Verification checklist:
|
|||||||
<what-built>Complete Phase 1 app: bottom navigation with 3 tabs, sage and stone theme (light/dark), playful German placeholder screens, Settings with working theme switcher and About section. All text from ARB localization.</what-built>
|
<what-built>Complete Phase 1 app: bottom navigation with 3 tabs, sage and stone theme (light/dark), playful German placeholder screens, Settings with working theme switcher and About section. All text from ARB localization.</what-built>
|
||||||
<how-to-verify>
|
<how-to-verify>
|
||||||
1. Launch the app on an Android device/emulator: `flutter run`
|
1. Launch the app on an Android device/emulator: `flutter run`
|
||||||
2. Verify bottom navigation bar shows 3 tabs with icons and German labels: "Ubersicht" (checklist icon), "Raume" (door icon), "Einstellungen" (sliders icon)
|
2. Verify bottom navigation bar shows 3 tabs with icons and German labels: "Übersicht" (checklist icon), "Räume" (door icon), "Einstellungen" (sliders icon)
|
||||||
3. Tap each tab -- verify it switches content and the active tab indicator uses sage green
|
3. Tap each tab -- verify it switches content and the active tab indicator uses sage green
|
||||||
4. On the Home tab: verify playful empty state with icon, German text, and "Raum erstellen" button. Tap the button -- verify it navigates to the Rooms tab.
|
4. On the Home tab: verify playful empty state with icon, German text, and "Raum erstellen" button. Tap the button -- verify it navigates to the Rooms tab.
|
||||||
5. On the Rooms tab: verify playful empty state with door icon and German text
|
5. On the Rooms tab: verify playful empty state with door icon and German text
|
||||||
@@ -294,7 +304,7 @@ Verification checklist:
|
|||||||
8. Switch theme to "Dunkel" (dark) -- verify warm charcoal-brown backgrounds (NOT cold gray/black)
|
8. Switch theme to "Dunkel" (dark) -- verify warm charcoal-brown backgrounds (NOT cold gray/black)
|
||||||
9. Switch back to "System" -- verify it follows device setting
|
9. Switch back to "System" -- verify it follows device setting
|
||||||
10. Kill and relaunch the app -- verify theme preference persisted
|
10. Kill and relaunch the app -- verify theme preference persisted
|
||||||
11. Scroll to "Uber" section -- verify app name "HouseHoldKeaper" and tagline "Dein Haushalt, entspannt organisiert."
|
11. Scroll to "Über" section -- verify app name "HouseHoldKeaper" and tagline "Dein Haushalt, entspannt organisiert."
|
||||||
12. Overall: confirm the sage and stone palette feels calm and warm, not clinical
|
12. Overall: confirm the sage and stone palette feels calm and warm, not clinical
|
||||||
</how-to-verify>
|
</how-to-verify>
|
||||||
<resume-signal>Type "approved" to complete Phase 1, or describe any visual/functional issues to fix</resume-signal>
|
<resume-signal>Type "approved" to complete Phase 1, or describe any visual/functional issues to fix</resume-signal>
|
||||||
@@ -303,8 +313,9 @@ Verification checklist:
|
|||||||
</tasks>
|
</tasks>
|
||||||
|
|
||||||
<verification>
|
<verification>
|
||||||
- `flutter build apk --debug` succeeds
|
|
||||||
- `dart analyze` reports zero errors/warnings
|
- `dart analyze` reports zero errors/warnings
|
||||||
|
- `flutter test` passes all tests (Wave 0 + app shell test)
|
||||||
|
- `flutter build apk --debug` succeeds
|
||||||
- App launches and shows 3-tab bottom navigation
|
- App launches and shows 3-tab bottom navigation
|
||||||
- All UI text comes from ARB localization (no hardcoded German in .dart files)
|
- All UI text comes from ARB localization (no hardcoded German in .dart files)
|
||||||
- Theme switching works (System/Hell/Dunkel) and persists across restart
|
- Theme switching works (System/Hell/Dunkel) and persists across restart
|
||||||
@@ -320,6 +331,7 @@ Verification checklist:
|
|||||||
- All UI strings loaded from ARB localization files (zero hardcoded German text in Dart code)
|
- All UI strings loaded from ARB localization files (zero hardcoded German text in Dart code)
|
||||||
- Settings screen has working theme switcher (System/Hell/Dunkel) that persists and About section
|
- Settings screen has working theme switcher (System/Hell/Dunkel) that persists and About section
|
||||||
- Placeholder screens show playful empty states with localized text and action buttons
|
- Placeholder screens show playful empty states with localized text and action buttons
|
||||||
|
- All automated tests pass (Wave 0 tests from Plan 01 + app shell test)
|
||||||
- Human verification approves the visual appearance and interaction
|
- Human verification approves the visual appearance and interaction
|
||||||
</success_criteria>
|
</success_criteria>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user