diff --git a/CLAUDE.md b/CLAUDE.md index 310153f..90d99b2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -228,19 +228,62 @@ HihaArvio.sln - **Coverage:** 51.28% line (low due to MAUI template), 87.5% branch - **Build:** 0 warnings, 0 errors across all platforms +**Milestone 3: ViewModels Layer (✅ Complete)** +- MainViewModel (18 tests) + - Coordinates shake detection and estimate generation + - Subscribes to ShakeDetectionService.ShakeDataChanged event + - Detects shake stop (transition from shaking → not shaking) + - Mode selection and current estimate display + - Implements IDisposable for cleanup +- HistoryViewModel (15 tests) + - Manages estimate history display with ObservableCollection + - LoadHistoryCommand for async history retrieval + - ClearHistoryCommand for pruning + - IsEmpty property for empty state handling +- SettingsViewModel (13 tests) + - Settings management (SelectedMode, MaxHistorySize) + - SaveSettingsCommand for persistence + - Auto-loads settings on initialization +- All ViewModels use CommunityToolkit.Mvvm source generators + - [ObservableProperty] for property change notifications + - [RelayCommand] for commands +- **Total: 165 tests, all passing (119 services + 46 ViewModels)** +- **Build:** 0 warnings, 0 errors across all platforms + +**Milestone 4: Views/UI Layer (✅ Complete)** +- Dependency Injection configuration in MauiProgram.cs + - All services registered as Singleton + - All ViewModels and Pages registered as Transient + - SQLite database path configured with FileSystem.AppDataDirectory +- MainPage.xaml with data binding + - Mode selector (Work/Generic) + - Current estimate display with conditional visibility + - Shake status indicator + - Uses x:DataType for compile-time binding verification +- HistoryPage.xaml with data binding + - CollectionView with ItemTemplate + - Empty state when no history + - Refresh and Clear All buttons + - Auto-loads history on OnAppearing() +- SettingsPage.xaml with data binding + - Picker for mode selection (Work/Generic only - Humorous is easter egg) + - Stepper for MaxHistorySize (5-100, increment by 5) + - Save Settings button + - About section with easter egg hint +- Value Converters for UI logic + - IsNullConverter / IsNotNullConverter (conditional visibility) + - BoolToShakingConverter (status text) + - BoolToColorConverter (status colors) + - InvertedBoolConverter (boolean inversion) + - All registered in App.xaml resources +- AppShell.xaml navigation + - TabBar with 3 tabs: Estimate, History, Settings + - Each tab uses ContentTemplate for lazy loading +- **Total: 165 tests still passing (no UI tests yet)** +- **Build:** 0 warnings, 0 errors across all platforms (net8.0, iOS, macOS Catalyst) + ### Remaining Work -**Milestone 3: ViewModels Layer** (Not Started) -- MainViewModel (estimate display, settings) -- HistoryViewModel (estimate history) -- SettingsViewModel (mode selection, history management) - -**Milestone 4: Views/UI Layer** (Not Started) -- MainPage (shake screen, estimate display) -- HistoryPage (estimate list) -- SettingsPage (mode toggle, history clear) -- Navigation infrastructure - **Milestone 5: Platform-Specific Implementations** (Not Started) - IAccelerometerService interface - iOS implementation (real accelerometer) diff --git a/src/HihaArvio/App.xaml b/src/HihaArvio/App.xaml index 22179c7..1404f7f 100644 --- a/src/HihaArvio/App.xaml +++ b/src/HihaArvio/App.xaml @@ -2,6 +2,7 @@ @@ -9,6 +10,13 @@ + + + + + + + diff --git a/src/HihaArvio/AppShell.xaml b/src/HihaArvio/AppShell.xaml index 574c217..a8de905 100644 --- a/src/HihaArvio/AppShell.xaml +++ b/src/HihaArvio/AppShell.xaml @@ -4,12 +4,26 @@ xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:HihaArvio" - Shell.FlyoutBehavior="Disabled" - Title="HihaArvio"> + Title="Hiha-Arvio"> - + + + + + + + diff --git a/src/HihaArvio/Converters/BoolToColorConverter.cs b/src/HihaArvio/Converters/BoolToColorConverter.cs new file mode 100644 index 0000000..6478110 --- /dev/null +++ b/src/HihaArvio/Converters/BoolToColorConverter.cs @@ -0,0 +1,20 @@ +using System.Globalization; + +namespace HihaArvio.Converters; + +public class BoolToColorConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (value is bool isShaking) + { + return isShaking ? Colors.Green : Colors.Gray; + } + return Colors.Gray; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } +} diff --git a/src/HihaArvio/Converters/BoolToShakingConverter.cs b/src/HihaArvio/Converters/BoolToShakingConverter.cs new file mode 100644 index 0000000..a5eea65 --- /dev/null +++ b/src/HihaArvio/Converters/BoolToShakingConverter.cs @@ -0,0 +1,20 @@ +using System.Globalization; + +namespace HihaArvio.Converters; + +public class BoolToShakingConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (value is bool isShaking) + { + return isShaking ? "Shaking" : "Idle"; + } + return "Unknown"; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } +} diff --git a/src/HihaArvio/Converters/InvertedBoolConverter.cs b/src/HihaArvio/Converters/InvertedBoolConverter.cs new file mode 100644 index 0000000..1eada0b --- /dev/null +++ b/src/HihaArvio/Converters/InvertedBoolConverter.cs @@ -0,0 +1,16 @@ +using System.Globalization; + +namespace HihaArvio.Converters; + +public class InvertedBoolConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + return value is bool boolValue && !boolValue; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + return value is bool boolValue && !boolValue; + } +} diff --git a/src/HihaArvio/Converters/IsNullConverter.cs b/src/HihaArvio/Converters/IsNullConverter.cs new file mode 100644 index 0000000..0d69e39 --- /dev/null +++ b/src/HihaArvio/Converters/IsNullConverter.cs @@ -0,0 +1,29 @@ +using System.Globalization; + +namespace HihaArvio.Converters; + +public class IsNullConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + return value is null; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } +} + +public class IsNotNullConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + return value is not null; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } +} diff --git a/src/HihaArvio/HistoryPage.xaml b/src/HihaArvio/HistoryPage.xaml new file mode 100644 index 0000000..ea2407f --- /dev/null +++ b/src/HihaArvio/HistoryPage.xaml @@ -0,0 +1,96 @@ + + + + + + + +