Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/UI revamp #2

Merged
merged 5 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions MMExNotifier.Tests/MainViewModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,33 @@ public void OnDatabaseError_ShouldShowErrorMessage()

mockNotificationService.Verify();
}


[Test]
public void SavingAppSettings_ShouldReloadExpiringBills()
{
mockDatabaseService.Setup(x => x.ExpiringBills).Returns(
new List<ExpiringBill>
{
new()
{
BillId=1,
CategoryName="testCategory",
PayeeName="TestPayee",
NextOccurrenceDate=new DateTime(2024,6,1)
}
});

mockNotificationService.Setup(
x => x.ShowErrorNotification(It.IsAny<string>())
);

var mainViewModel = new MainViewModel(mockAppConfiguration.Object, mockNotificationService.Object, mockDatabaseService.Object);
mainViewModel.Activate();
mainViewModel.SaveSettingsCommand.Execute(null);

mockNotificationService.Verify();
mockDatabaseService.Verify(x => x.ExpiringBills, Times.Exactly(2));
}
}
}
17 changes: 12 additions & 5 deletions MMExNotifier/App.xaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
<Application x:Class="MMExNotifier.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MMExNotifier">
<Application
x:Class="MMExNotifier.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MMExNotifier"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml">
<Application.Resources>

<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:ThemesDictionary Theme="Dark" />
<ui:ControlsDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
3 changes: 3 additions & 0 deletions MMExNotifier/DataModel/ExpiringBill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ public class ExpiringBill
public int BillId { get; set; }
public DateTime NextOccurrenceDate { get; set; }
public int DaysToNextOccurrence => (int)NextOccurrenceDate.Subtract(DateTime.Today).TotalDays;
public bool IsExpired => DaysToNextOccurrence < 0;
public string? PayeeName { get; set; }
public string? CategoryName { get; set; }
public string? SubCategoryName { get; set; }
public string? Notes { get; set; }
public int Amount { get; set; }
public bool IsDeposit { get; set; }
}
}
2 changes: 2 additions & 0 deletions MMExNotifier/Database/DatabaseService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@
select new ExpiringBill
{
BillId = b.BDID,
NextOccurrenceDate = b.NEXTOCCURRENCEDATE.Value,

Check warning on line 43 in MMExNotifier/Database/DatabaseService.cs

View workflow job for this annotation

GitHub Actions / build (Debug)

Nullable value type may be null.

Check warning on line 43 in MMExNotifier/Database/DatabaseService.cs

View workflow job for this annotation

GitHub Actions / build (Debug)

Nullable value type may be null.

Check warning on line 43 in MMExNotifier/Database/DatabaseService.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Nullable value type may be null.

Check warning on line 43 in MMExNotifier/Database/DatabaseService.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Nullable value type may be null.

Check warning on line 43 in MMExNotifier/Database/DatabaseService.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Nullable value type may be null.

Check warning on line 43 in MMExNotifier/Database/DatabaseService.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Nullable value type may be null.
PayeeName = p.PAYEENAME!,
Amount = b.TOTRANSAMOUNT,
IsDeposit = b.TRANSCODE == "Deposit" ? true : false,
CategoryName = c.CATEGNAME!,
SubCategoryName = s.CATEGNAME!,
Notes = b.NOTES!
Expand Down
16 changes: 13 additions & 3 deletions MMExNotifier/MMExNotifier.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,33 @@
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<ApplicationManifest>app.manifest</ApplicationManifest>
<ApplicationIcon>Resources\MMExNotifier.ico</ApplicationIcon>
<AssemblyVersion>1.1.0.0</AssemblyVersion>
<FileVersion>1.1.0.0</FileVersion>
<Version>1.1.0</Version>
</PropertyGroup>

<ItemGroup>
<None Remove="Resources\options.png" />
<None Remove="Resources\MMExNotifier.ico" />
<None Remove="Resources\MMExNotifier.png" />
</ItemGroup>

<ItemGroup>
<Content Include="Resources\MMExNotifier.ico" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Hardcodet.NotifyIcon.Wpf" Version="1.1.0" />
<PackageReference Include="linq2db" Version="5.1.1" />
<PackageReference Include="linq2db.SQLite" Version="5.1.1" />
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
<PackageReference Include="System.Data.SQLite" Version="1.0.117" />
<PackageReference Include="TaskScheduler" Version="2.10.1" />
<PackageReference Include="WPF-UI" Version="3.0.4" />
</ItemGroup>

<ItemGroup>
<Resource Include="Resources\options.png" />
<Resource Include="Resources\MMExNotifier.ico" />
<Resource Include="Resources\MMExNotifier.png" />
</ItemGroup>

<ItemGroup>
Expand Down
47 changes: 47 additions & 0 deletions MMExNotifier/MVVM/DaysToTextConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using MMExNotifier.DataModel;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace MMExNotifier.MVVM
{
internal class DaysToTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null || value is not ExpiringBill)
return string.Empty;

var expiringBill = (ExpiringBill)value;

if (expiringBill.DaysToNextOccurrence < -5)
return $"expired on {expiringBill.NextOccurrenceDate:d} ({-expiringBill.DaysToNextOccurrence} days ago)!";

if (expiringBill.DaysToNextOccurrence < -1)
return $"expired {-expiringBill.DaysToNextOccurrence} days ago!";

if (expiringBill.DaysToNextOccurrence == -1)
return "expired yesterday!";

if (expiringBill.DaysToNextOccurrence == 0)
return "expires today.";

if (expiringBill.DaysToNextOccurrence == 1)
return "expires tomorrow.";

if (expiringBill.DaysToNextOccurrence > 1)
return $"will expire on {expiringBill.NextOccurrenceDate:d} (in {expiringBill.DaysToNextOccurrence} days).";

return string.Empty;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
68 changes: 68 additions & 0 deletions MMExNotifier/MVVM/DerivableDynamicStyle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace MMExNotifier.MVVM
{
internal class DerivableDynamicStyle
{
public static Style GetBaseStyle(DependencyObject obj)
{
return (Style)obj.GetValue(BaseStyleProperty);
}

public static void SetBaseStyle(DependencyObject obj, Style value)
{
obj.SetValue(BaseStyleProperty, value);
}

public static readonly DependencyProperty BaseStyleProperty =
DependencyProperty.RegisterAttached("BaseStyle", typeof(Style), typeof(FrameworkElement), new UIPropertyMetadata(StyleChanged));

public static Style GetDerivedStyle(DependencyObject obj)
{
return (Style)obj.GetValue(DerivedStyleProperty);
}

public static void SetDerivedStyle(DependencyObject obj, Style value)
{
obj.SetValue(DerivedStyleProperty, value);
}

public static readonly DependencyProperty DerivedStyleProperty =
DependencyProperty.RegisterAttached("DerivedStyle", typeof(Style), typeof(FrameworkElement), new UIPropertyMetadata(StyleChanged));


private static void StyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Style baseStyle = GetBaseStyle(d);
Style derivedStyle = GetDerivedStyle(d);
Style newStyle;

if (derivedStyle == null)
{
newStyle = baseStyle;
}
else
{
newStyle = new Style { BasedOn = baseStyle, TargetType = derivedStyle.TargetType };

foreach (var setter in derivedStyle.Setters)
{
newStyle.Setters.Add(setter);
}

foreach (var trigger in derivedStyle.Triggers)
{
newStyle.Triggers.Add(trigger);
}
}

var fe = (FrameworkElement)d;
fe.Style = newStyle;
}
}
}
Binary file added MMExNotifier/Resources/MMExNotifier.ico
Binary file not shown.
Binary file added MMExNotifier/Resources/MMExNotifier.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed MMExNotifier/Resources/options.png
Binary file not shown.
37 changes: 37 additions & 0 deletions MMExNotifier/ViewModels/Design/MainViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using MMExNotifier.DataModel;
using MMExNotifier.MVVM;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MMExNotifier.ViewModels.Design
{
internal class MainViewModel : ViewModelBase
{
public RangeObservableCollection<ExpiringBill> ExpiringBills { get; set; } = new RangeObservableCollection<ExpiringBill>();

public MainViewModel()
{
ExpiringBills = new RangeObservableCollection<ExpiringBill>() {
new ()
{
BillId = 1,
CategoryName = "Category Name",
SubCategoryName = "Subcategory Name",
PayeeName = "Payee Name",
NextOccurrenceDate = new DateTime(2024, 10, 30),
Notes = "some notes about this entry.",
}
};

OnPropertyChanged(nameof(ExpiringBills));
}

public override void Activate()
{
throw new NotImplementedException();
}
}
}
2 changes: 1 addition & 1 deletion MMExNotifier/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public override void Activate()
}

const int ConversationId = 9813;
_notificationService.ShowToastNotification("viewTransactions", ConversationId, "MMExNotifier", "One ore more recurring transaction are about to expire.", () => Open());
_notificationService.ShowToastNotification("viewTransactions", ConversationId, "MMExNotifier", "One or more recurring transaction are about to expire.", () => Open());
}

private void LoadExpiringBills()
Expand Down
Loading
Loading