18 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01-foundation | 02 | execute | 2 |
|
|
false |
|
|
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, with app shell test passing.
<execution_context> @/home/jlmak/.claude/get-shit-done/workflows/execute-plan.md @/home/jlmak/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01-foundation/1-CONTEXT.md @.planning/phases/01-foundation/01-RESEARCH.md @.planning/phases/01-foundation/01-01-SUMMARY.mdFrom lib/core/theme/app_theme.dart:
class AppTheme {
static ThemeData lightTheme();
static ThemeData darkTheme();
}
From lib/core/theme/theme_provider.dart (generated):
// @riverpod class ThemeNotifier extends _$ThemeNotifier
// Access via: ref.watch(themeNotifierProvider) -> ThemeMode
// Mutate via: ref.read(themeNotifierProvider.notifier).setThemeMode(ThemeMode)
From lib/core/database/database.dart:
class AppDatabase extends _$AppDatabase {
// schemaVersion => 1
// Used via database_provider.dart
}
From lib/core/providers/database_provider.dart (generated):
// @riverpod AppDatabase appDatabase(Ref ref)
// Access via: ref.watch(appDatabaseProvider)
From lib/l10n/app_de.arb (generated AppLocalizations):
// Access via: AppLocalizations.of(context)
// Keys: appTitle, tabHome, tabRooms, tabSettings,
// homeEmptyTitle, homeEmptyMessage, homeEmptyAction,
// roomsEmptyTitle, roomsEmptyMessage, roomsEmptyAction,
// settingsSectionAppearance, settingsThemeLabel,
// themeSystem, themeLight, themeDark,
// settingsSectionAbout, aboutAppName, aboutTagline, aboutVersion
-
Create
lib/shell/app_shell.dart-- Scaffold with NavigationBar:AppShellis a StatelessWidget receivingStatefulNavigationShell navigationShell- Build method: get
AppLocalizationsviaAppLocalizations.of(context) - Scaffold body:
navigationShell - bottomNavigationBar:
NavigationBarwith:selectedIndex: navigationShell.currentIndexonDestinationSelected: callsnavigationShell.goBranch(index, initialLocation: index == navigationShell.currentIndex)- Three
NavigationDestinationitems:- Home: icon
Icons.checklist_outlined, selectedIconIcons.checklist, label froml10n.tabHome - Rooms: icon
Icons.door_front_door_outlined, selectedIconIcons.door_front_door, label froml10n.tabRooms - Settings: icon
Icons.tune_outlined, selectedIconIcons.tune, label froml10n.tabSettings
- Home: icon
-
Create
lib/features/home/presentation/home_screen.dart-- Placeholder with empty state:HomeScreenextendsStatelessWidget- Build method: Center column with:
- Large Material icon (e.g.,
Icons.checklist_rounded, size 80, muted color) - Text from
l10n.homeEmptyTitle(styled as headline) - Text from
l10n.homeEmptyMessage(styled as body, muted color) FilledButton.tonalwith text froml10n.homeEmptyAction- Button onPressed:
context.go('/rooms')-- cross-navigates to Rooms tab
- Large Material icon (e.g.,
- All text comes from AppLocalizations, zero hardcoded strings
-
Create
lib/features/rooms/presentation/rooms_screen.dart-- Placeholder with empty state:- Same visual pattern as HomeScreen: icon + title + message + action button
- Icon:
Icons.door_front_door_rounded(size 80) - Text from
l10n.roomsEmptyTitle,l10n.roomsEmptyMessage,l10n.roomsEmptyAction - Action button:
FilledButton.tonal-- for now it can be a no-op (room creation comes in Phase 2) or show a SnackBar. The button should exist but doesn't need to do anything functional yet.
-
Create
lib/features/settings/presentation/settings_screen.dart-- Theme switcher + About:SettingsScreenextendsConsumerWidget(needs ref for theme provider)- Uses
ListViewwith grouped sections: - Section 1 -- "Darstellung" (Appearance):
- Section header: Padding + Text from
l10n.settingsSectionAppearancestyled as titleMedium with primary color - Theme switcher row: ListTile with title from
l10n.settingsThemeLabel, subtitle is aSegmentedButton<ThemeMode>with three segments:ThemeMode.system: labell10n.themeSystem, iconIcons.settings_suggest_outlinedThemeMode.light: labell10n.themeLight, iconIcons.light_mode_outlinedThemeMode.dark: labell10n.themeDark, iconIcons.dark_mode_outlined
selected: {ref.watch(themeNotifierProvider)}onSelectionChanged: (s) => ref.read(themeNotifierProvider.notifier).setThemeMode(s.first)
- Section header: Padding + Text from
- Section 2 -- "Über" (About):
- Section header: same style, text from
l10n.settingsSectionAbout - ListTile: title from
l10n.aboutAppName, subtitle froml10n.aboutTagline - ListTile: title "Version", subtitle from
l10n.aboutVersionwith version string (use package_info_plus or hardcode "0.1.0" for now -- package_info_plus can be added later if needed)
- Section header: same style, text from
- A
Dividerbetween sections for visual separation
-
Create
test/shell/app_shell_test.dart(covers FOUND-04):- Widget test: wrap
MaterialApp.router(routerConfig: router)inProviderScopewith localization delegates andlocale: Locale('de') - Pump and settle
- Verify that 3
NavigationDestinationwidgets 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 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" 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.
- Widget test: wrap
-
Update
lib/main.dart-- entry point:void main()callsrunApp(const ProviderScope(child: App()))- Import the App widget and flutter_riverpod
-
Run
dart run build_runner build --delete-conflicting-outputsone final time to ensure all generated files are current (router may need regeneration if it uses @riverpod). -
Verify the complete integration:
dart analyzepasses cleanlyflutter testpasses (all tests including Wave 0 tests from Plan 01) 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" 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 analyzepasses cleanly.flutter testpasses 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 --debugcompiles without errors.
Verification checklist:
- App launches without errors and shows bottom navigation bar
- Three tabs visible with correct icons and German labels from ARB
- Tab switching works with state preservation
- Home empty state has playful text and cross-navigates to Rooms tab
- Rooms empty state has playful text and action button
- Settings has "Darstellung" section with SegmentedButton theme switcher
- Light theme shows warm stone/beige surfaces
- Dark theme shows warm charcoal-brown surfaces (not cold gray)
- System theme follows device setting
- Theme preference persists across app restart
- "Über" section shows app name and tagline
- Overall sage and stone palette feels calm and warm Human visually confirms all 12 checklist items pass User has approved the visual appearance and functional behavior of the Phase 1 app, or has provided specific feedback for issues to fix. 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.
- Launch the app on an Android device/emulator:
flutter run - Verify bottom navigation bar shows 3 tabs with icons and German labels: "Übersicht" (checklist icon), "Räume" (door icon), "Einstellungen" (sliders icon)
- Tap each tab -- verify it switches content and the active tab indicator uses sage green
- 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.
- On the Rooms tab: verify playful empty state with door icon and German text
- On the Settings tab: verify "Darstellung" section header and SegmentedButton with System/Hell/Dunkel options
- Switch theme to "Hell" (light) -- verify warm stone/beige surface tones
- Switch theme to "Dunkel" (dark) -- verify warm charcoal-brown backgrounds (NOT cold gray/black)
- Switch back to "System" -- verify it follows device setting
- Kill and relaunch the app -- verify theme preference persisted
- Scroll to "Über" section -- verify app name "HouseHoldKeaper" and tagline "Dein Haushalt, entspannt organisiert."
- Overall: confirm the sage and stone palette feels calm and warm, not clinical Type "approved" to complete Phase 1, or describe any visual/functional issues to fix
<success_criteria>
- App launches on Android without errors showing bottom navigation with Home, Rooms, and Settings tabs
- Light and dark themes work correctly following system setting by default using sage and stone palette
- 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
- 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 </success_criteria>