Version 1.0.3
Some checks failed
Gitea/WheresMyMoney/pipeline/head There was a failure building this commit

- Modify planned payment
- minor bug fixes
This commit is contained in:
Michał Leśniak 2025-01-26 14:53:16 +01:00
parent 34098c9757
commit 2d69a4b018
22 changed files with 618 additions and 107 deletions

50
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,50 @@
pipeline {
agent { label 'Kapitan-PC' }
environment {
ANDROID_HOME = 'C:\\Users\\lemi4\\AppData\\Local\\Android\\sdk'
DOTNET_ROOT = 'C:\\Program Files\\dotnet'
PATH = "${env.PATH};${env.ANDROID_HOME}\\tools;${env.ANDROID_HOME}\\platform-tools;${env.DOTNET_ROOT}"
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Restore Dependencies') {
steps {
script {
bat 'dotnet restore WheresMyMoney.sln'
}
}
}
stage('Build Android') {
steps {
script {
bat 'dotnet build WheresMyMoney.Maui\\WheresMyMoney.Maui.csproj -c Release -f net9.0-android'
}
}
}
stage('Build Windows') {
steps {
script {
bat 'dotnet build WheresMyMoney.Maui\\WheresMyMoney.Maui.csproj -c Release -f net9.0-windows10.0.19041.0'
}
}
}
stage('Publish Artifacts') {
steps {
script {
bat 'dotnet publish WheresMyMoney.Maui\\WheresMyMoney.Maui.csproj -c Release -f net9.0-android -o output\\android'
bat 'dotnet publish WheresMyMoney.Maui\\WheresMyMoney.Maui.csproj -c Release -f net9.0-windows10.0.19041.0 -o output\\windows'
}
archiveArtifacts artifacts: 'output/**/*', allowEmptyArchive: true
}
}
}
post {
always {
cleanWs()
}
}
}

View File

@ -81,7 +81,40 @@ public class Repository
reoccurenceType is null ? DBNull.Value : (int)reoccurenceType.Value);
command.ExecuteNonQuery();
DataChanged(this, EventArgs.Empty);
}
public void UpdatePlannedPayment(PlannedPayment plannedPayment)
{
using var command = _connection.CreateCommand();
command.CommandText = """
UPDATE planned_payment
SET amount = @amount,
name = @name,
date_start = @date_start,
date_end = @date_end,
is_subscription = @is_subscription,
reoccurences = @reoccurences,
reoccurence_type = @reoccurence_type
WHERE
id = @id;
""";
command.Parameters.AddWithValue("@id", plannedPayment.Id);
command.Parameters.AddWithValue("@amount", (int)(plannedPayment.Amount * 100));
command.Parameters.AddWithValue("@name", plannedPayment.Name);
command.Parameters.AddWithValue("@date_start", plannedPayment.DateStart);
command.Parameters.AddWithValue("@date_end",
plannedPayment.DateEnd.HasValue ? plannedPayment.DateEnd.Value : DBNull.Value);
command.Parameters.AddWithValue("@is_subscription", plannedPayment.IsSubscription);
command.Parameters.AddWithValue("@reoccurences",
plannedPayment.Reoccurences is null ? DBNull.Value : plannedPayment.Reoccurences.Value);
command.Parameters.AddWithValue("@reoccurence_type",
plannedPayment.ReoccurenceType is null ? DBNull.Value : (int)plannedPayment.ReoccurenceType.Value);
command.ExecuteNonQuery();
DataChanged(this, EventArgs.Empty);
}
@ -97,7 +130,7 @@ public class Repository
command.Parameters.AddWithValue("@date", date);
command.ExecuteNonQuery();
DataChanged(this, EventArgs.Empty);
}
@ -149,7 +182,7 @@ public class Repository
command.Parameters.AddWithValue("@payday", newPayday);
command.ExecuteNonQuery();
DataChanged(this, EventArgs.Empty);
}
@ -248,6 +281,32 @@ public class Repository
command.ExecuteNonQuery();
DataChanged(this, EventArgs.Empty);
}
public event EventHandler DataChanged;
public PlannedPayment? GetPlannedPayment(int id)
{
using var command = _connection.CreateCommand();
command.CommandText = """
SELECT id, amount, name, date_start, date_end, is_subscription, reoccurences, reoccurence_type
FROM planned_payment
WHERE id = @id
""";
command.Parameters.AddWithValue("@id", id);
using var reader = command.ExecuteReader();
if (reader.Read())
{
return new PlannedPayment(reader.GetInt32(0),
reader.GetDecimal(1) / 100m,
reader.GetString(2),
reader.GetDateTime(3),
reader.IsDBNull(4) ? null : reader.GetDateTime(4),
reader.GetBoolean(5),
reader.IsDBNull(6) ? null : reader.GetInt32(6),
reader.IsDBNull(7) ? null : (ReoccurenceType)reader.GetInt32(7));
}
return null;
}
}

View File

@ -20,7 +20,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.1" />
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)"/>
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.30" />
</ItemGroup>
</Project>

View File

@ -1,4 +1,4 @@
using System.Diagnostics;
using System.Globalization;
using WheresMyMoney.Maui.Core;
namespace WheresMyMoney.Maui;
@ -13,7 +13,8 @@ public partial class AddPlannedPaymentPage : ContentPage
private async void Add_OnClicked(object? sender, EventArgs e)
{
if (!decimal.TryParse(AmountEntry.Text, out decimal amount)) return;
if (!decimal.TryParse(AmountEntry.Text, NumberStyles.Currency, CultureInfo.CurrentCulture,
out var amount)) return;
var isSubscription = SubscriptionSwitch.IsToggled;
var every = -1;
var reoccurenceType = (ReoccurenceType)RepeatPicker.SelectedIndex;
@ -44,6 +45,6 @@ public partial class AddPlannedPaymentPage : ContentPage
private void EveryEntry_OnCompleted(object? sender, EventArgs e)
{
AmountEntry.Focus();
this.AmountEntry.Focus();
}
}

View File

@ -9,18 +9,19 @@
Title="WheresMyMoney.Maui">
<TabBar>
<Tab Title="Środki" Icon="{FontImageSource Glyph=, FontFamily=FontAwesome, Size=32, Color={AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}} }">
<ShellContent Title="Środki"
<Tab Title="Środki"
Icon="{FontImageSource Glyph=, FontFamily=FontAwesome, Size=32, Color={AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}} }">
<ShellContent Title="Środki"
ContentTemplate="{DataTemplate local:BalancePage}"
Route="BalancePage" />
</Tab>
<Tab Title="Płatności" Icon="{FontImageSource Glyph=&#xf274;, FontFamily=FontAwesome, Size=32, Color={AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}} }">
<ShellContent Title="Płatności"
ContentTemplate="{DataTemplate local:PlannedPaymentsPage}"
Route="PlannedPaymentsPage" />
<Tab Title="Płatności"
Icon="{FontImageSource Glyph=&#xf274;, FontFamily=FontAwesome, Size=32, Color={AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}} }">
<ShellContent x:Name="PlannedPaymentsShellContent" Title="Płatności" />
</Tab>
<Tab Title="Historia" Icon="{FontImageSource Glyph=, FontFamily=FontAwesome, Size=32, Color={AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}} }">
<ShellContent Title="Historia"
<Tab Title="Historia"
Icon="{FontImageSource Glyph=, FontFamily=FontAwesome, Size=32, Color={AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}} }">
<ShellContent Title="Historia"
ContentTemplate="{DataTemplate local:BalanceHistoryPage}"
Route="BalanceHistoryPage" />
</Tab>

View File

@ -5,5 +5,12 @@ public partial class AppShell : Shell
public AppShell()
{
InitializeComponent();
#if ANDROID || IOS
PlannedPaymentsShellContent.ContentTemplate = new DataTemplate(typeof(MobilePlannedPaymentsPage));
PlannedPaymentsShellContent.Route = "MobilePlannedPaymentsPage";
#else
PlannedPaymentsShellContent.ContentTemplate = new DataTemplate(typeof(PlannedPaymentsPage));
PlannedPaymentsShellContent.Route = "PlannedPaymentsPage";
#endif
}
}

View File

@ -6,7 +6,8 @@
x:Class="WheresMyMoney.Maui.BalanceHistoryPage">
<CollectionView ItemsSource="{Binding GroupedBalanceChangeViewModels}"
RemainingItemsThreshold="5"
RemainingItemsThresholdReached="ItemsView_OnRemainingItemsThresholdReached">
RemainingItemsThresholdReached="ItemsView_OnRemainingItemsThresholdReached"
x:DataType="local:BalanceHistoryPage">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:GroupedBalanceChangeViewModel">
<VerticalStackLayout>
@ -23,7 +24,7 @@
<!-- Balance Changes List -->
<VerticalStackLayout Grid.Column="1"
BindableLayout.ItemsSource="{Binding BalanceChanges}">
BindableLayout.ItemsSource="{Binding BalanceChanges}">
<BindableLayout.ItemTemplate>
<DataTemplate x:DataType="local:BalanceChangeViewModel">
<VerticalStackLayout>

View File

@ -51,7 +51,7 @@
</Grid>
<BoxView Grid.Row="1" HeightRequest="1" BackgroundColor="Gray" Margin="0,10,0,10" />
<!-- Scrollable List Section -->
<CollectionView Grid.Row="2" ItemsSource="{Binding PlannedPaymentsViewModels}">
<CollectionView Grid.Row="2" ItemsSource="{Binding PlannedPaymentsViewModels}" x:DataType="local:BalancePage">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:PlannedPaymentsViewModel">
<Grid Padding="10" ColumnSpacing="10">

View File

@ -1,4 +1,6 @@
namespace WheresMyMoney.Maui;
using System.Windows.Input;
namespace WheresMyMoney.Maui;
public record FullPlannedPaymentViewModel(
int Id,
@ -9,4 +11,5 @@ public record FullPlannedPaymentViewModel(
bool ShowDateEnd,
bool IsSubscription,
int? Reoccurences,
string? ReoccurenceType);
string? ReoccurenceType,
ICommand? LongPressCommand);

View File

@ -1,4 +1,5 @@
using Microsoft.Extensions.Logging;
using CommunityToolkit.Maui;
using Microsoft.Extensions.Logging;
namespace WheresMyMoney.Maui;
@ -9,6 +10,8 @@ public static class MauiProgram
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
// Initialize the .NET MAUI Community Toolkit by adding the below line of code
.UseMauiCommunityToolkit()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="using:WheresMyMoney.Maui"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:Class="WheresMyMoney.Maui.MobilePlannedPaymentsPage">
<ContentPage.ToolbarItems>
<ToolbarItem
IconImageSource="{FontImageSource Glyph=+, FontFamily=FontAwesome, Size=32, Color={AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}} }"
Order="Primary"
Clicked="InsertPlannedPayment_OnClicked" />
</ContentPage.ToolbarItems>
<CollectionView ItemsSource="{Binding FullPlannedPaymentViewModels}" x:DataType="local:MobilePlannedPaymentsPage">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:FullPlannedPaymentViewModel">
<local:PlannedPaymentContent x:Name="PlannedPaymentContent" Margin="10,15" Padding="10">
<local:PlannedPaymentContent.Behaviors>
<toolkit:TouchBehavior
BindingContext="{Binding Path=BindingContext, Source={x:Reference PlannedPaymentContent}}"
x:DataType="local:FullPlannedPaymentViewModel"
LongPressCommand="{Binding LongPressCommand}" />
</local:PlannedPaymentContent.Behaviors>
</local:PlannedPaymentContent>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage>

View File

@ -0,0 +1,98 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Maui.Views;
using WheresMyMoney.Maui.Core;
namespace WheresMyMoney.Maui;
public partial class MobilePlannedPaymentsPage : ContentPage
{
public ObservableCollection<FullPlannedPaymentViewModel> FullPlannedPaymentViewModels { get; } = [];
public MobilePlannedPaymentsPage()
{
InitializeComponent();
BindingContext = this;
UpdateUi();
Repository.Instance.DataChanged += OnDataChanged;
}
private void OnDataChanged(object? sender, EventArgs e)
{
UpdateUi();
}
private void UpdateUi()
{
FullPlannedPaymentViewModels.Clear();
foreach (var plannedPayment in Repository.Instance.GetAllPlannedPayments())
{
FullPlannedPaymentViewModels.Add(new FullPlannedPaymentViewModel(plannedPayment.Id,
plannedPayment.Amount.ToString("C"), plannedPayment.Name,
plannedPayment.DateStart.ToString("yyyy-MM-dd"),
plannedPayment.DateEnd?.ToString("yyyy-MM-dd") ?? string.Empty, plannedPayment.DateEnd is not null,
plannedPayment.IsSubscription,
plannedPayment.Reoccurences,
ReoccurenceTypeToString(plannedPayment.Reoccurences, plannedPayment.ReoccurenceType),
new Command(async () =>
{
var popup = new PlannedPlannedPopup();
var result = await this.ShowPopupAsync(popup, CancellationToken.None);
if (result is not PlannedPlannedPopup.PlannedPaymentPopupChoice choice) return;
switch (choice)
{
case PlannedPlannedPopup.PlannedPaymentPopupChoice.Modify:
await Navigation.PushModalAsync(new ModifyPlannedPaymentPage(plannedPayment.Id));
break;
case PlannedPlannedPopup.PlannedPaymentPopupChoice.Remove:
await RemovePlannedPayment(plannedPayment.Id);
break;
default:
return;
}
})));
}
}
private static string ReoccurenceTypeToString(int? plannedPaymentReoccurences,
ReoccurenceType? plannedPaymentReoccurenceType) =>
plannedPaymentReoccurenceType switch
{
ReoccurenceType.Days => plannedPaymentReoccurences switch
{
1 => "dzień",
_ => "dni"
},
ReoccurenceType.Weeks => (plannedPaymentReoccurences, plannedPaymentReoccurences % 10) switch
{
(1, _) => "tydzień",
(_, > 1 and < 5) => "tygodnie",
_ => "tygodni"
},
ReoccurenceType.Months => (plannedPaymentReoccurences, plannedPaymentReoccurences % 10) switch
{
(1, _) => "miesiąc",
(_, > 1 and < 5) => "miesiące",
_ => "miesięcy"
},
ReoccurenceType.Years => (plannedPaymentReoccurences, plannedPaymentReoccurences % 10) switch
{
(1, _) => "rok",
(_, > 1 and < 5) => "lata",
_ => "lat"
},
ReoccurenceType.EveryLastDayOfMonth => "ostatni dzień miesiąca",
_ => string.Empty
};
private async void InsertPlannedPayment_OnClicked(object? sender, EventArgs e)
{
await Navigation.PushModalAsync(new AddPlannedPaymentPage());
}
private async Task RemovePlannedPayment(int id)
{
var answer = await DisplayAlert("Usunąć?", "Czy na pewno chcesz usunąć tą płatność?", "Tak", "Nie");
if (!answer) return;
Repository.Instance.RemovePlannedPayment(id);
}
}

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WheresMyMoney.Maui.ModifyPlannedPaymentPage">
<ContentPage.Content>
<VerticalStackLayout Padding="10">
<Label Text="Nazwa" Margin="10,10,10,0" />
<Entry x:Name="NameEntry" Placeholder="Wprowadź nazwę" ClearButtonVisibility="WhileEditing"
Margin="10,0,10,0"
ReturnType="Next" Completed="NameEntry_OnCompleted" />
<HorizontalStackLayout IsVisible="False" Margin="10,0,10,0">
<HorizontalStackLayout.Triggers>
<DataTrigger TargetType="HorizontalStackLayout"
Binding="{Binding Source={x:Reference SubscriptionSwitch}, Path=IsToggled}"
Value="True">
<Setter Property="IsVisible" Value="True" />
</DataTrigger>
</HorizontalStackLayout.Triggers>
<Label Text="Powtarzaj co" VerticalOptions="Center" />
<Entry x:Name="EveryEntry" Text="1" Keyboard="Numeric" Margin="10,10,10,0" ReturnType="Next"
Completed="EveryEntry_OnCompleted" />
<Picker x:Name="RepeatPicker" Margin="0,10">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>dzień</x:String>
<x:String>tydzień</x:String>
<x:String>miesiąc</x:String>
<x:String>rok</x:String>
<x:String>każdego ostatniego dnia miesiąca</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
</HorizontalStackLayout>
<Label Text="od" Margin="10,10,10,0" />
<DatePicker x:Name="StartDateEntry" Margin="10,0,10,0" />
<Grid ColumnDefinitions="*,Auto" VerticalOptions="Center" Margin="10,10,10,0">
<Label Grid.Column="0" Text="Subskrybcja?" VerticalOptions="Center" />
<Switch Grid.Column="1" x:Name="SubscriptionSwitch" VerticalOptions="End" IsToggled="False" />
</Grid>
<VerticalStackLayout IsVisible="False">
<VerticalStackLayout.Triggers>
<DataTrigger TargetType="VerticalStackLayout"
Binding="{Binding Source={x:Reference SubscriptionSwitch}, Path=IsToggled}"
Value="True">
<Setter Property="IsVisible" Value="True" />
</DataTrigger>
</VerticalStackLayout.Triggers>
<VerticalStackLayout IsVisible="False">
<VerticalStackLayout.Triggers>
<DataTrigger TargetType="VerticalStackLayout"
Binding="{Binding Source={x:Reference IndefiniteSwitch}, Path=IsToggled}"
Value="False">
<Setter Property="IsVisible" Value="True" />
</DataTrigger>
</VerticalStackLayout.Triggers>
<Label Text="do" Margin="10,10,10,0" />
<DatePicker x:Name="EndDateEntry" Margin="10,0,10,0" />
</VerticalStackLayout>
<Grid ColumnDefinitions="*,Auto" VerticalOptions="Center" Margin="10,10,10,0">
<Label Text="Do odwołania" Grid.Column="0" VerticalOptions="Center" />
<Switch x:Name="IndefiniteSwitch" IsToggled="True" Grid.Column="1" VerticalOptions="Center"
HorizontalOptions="End" />
</Grid>
</VerticalStackLayout>
<Entry x:Name="AmountEntry" Placeholder="Kwota (PLN)" ClearButtonVisibility="WhileEditing"
Margin="10,10,10,0"
Keyboard="Numeric" ReturnType="Done" Completed="Modify_OnClicked" />
<Grid ColumnDefinitions="*,*,*,*,*" Margin="10" HorizontalOptions="Fill">
<Button Grid.Column="1" Grid.ColumnSpan="3" Text="zatwierdź" Clicked="Modify_OnClicked"
VerticalOptions="Center" HorizontalOptions="Fill" />
</Grid>
</VerticalStackLayout>
</ContentPage.Content>
</ContentPage>

View File

@ -0,0 +1,77 @@
using System.Globalization;
using WheresMyMoney.Maui.Core;
namespace WheresMyMoney.Maui;
public partial class ModifyPlannedPaymentPage : ContentPage
{
private readonly PlannedPayment? _plannedPayment;
public ModifyPlannedPaymentPage(int id)
{
InitializeComponent();
RepeatPicker.SelectedIndex = 2;
_plannedPayment = Repository.Instance.GetPlannedPayment(id);
}
protected override async void OnAppearing()
{
base.OnAppearing();
if (_plannedPayment is null)
{
await Navigation.PopModalAsync();
}
else
{
NameEntry.Text = _plannedPayment.Name;
AmountEntry.Text = _plannedPayment.Amount.ToString("C");
SubscriptionSwitch.IsToggled = _plannedPayment.IsSubscription;
RepeatPicker.SelectedIndex = (int?)_plannedPayment.ReoccurenceType ?? 2;
EveryEntry.Text = _plannedPayment.Reoccurences?.ToString() ?? "1";
StartDateEntry.Date = _plannedPayment.DateStart.Date;
EndDateEntry.Date = _plannedPayment.DateEnd?.Date ?? DateTime.Today;
IndefiniteSwitch.IsToggled = _plannedPayment.DateEnd is null;
}
}
private async void Modify_OnClicked(object? sender, EventArgs e)
{
if (!decimal.TryParse(AmountEntry.Text, NumberStyles.Currency, CultureInfo.CurrentCulture,
out var amount)) return;
var isSubscription = SubscriptionSwitch.IsToggled;
var every = -1;
var reoccurenceType = (ReoccurenceType)RepeatPicker.SelectedIndex;
if (isSubscription)
{
isSubscription = int.TryParse(EveryEntry.Text, out every) && every > 0;
}
Repository.Instance.UpdatePlannedPayment(_plannedPayment! with
{
Amount = amount, Name = NameEntry.Text, DateStart = StartDateEntry.Date,
DateEnd = !isSubscription || IndefiniteSwitch.IsToggled ? null : EndDateEntry.Date,
IsSubscription = isSubscription, Reoccurences = isSubscription ? every : null,
ReoccurenceType = isSubscription ? reoccurenceType : null
});
await Navigation.PopModalAsync();
}
private void NameEntry_OnCompleted(object? sender, EventArgs e)
{
if (SubscriptionSwitch.IsToggled)
{
EveryEntry.Focus();
}
else
{
EveryEntry_OnCompleted(sender, e);
}
}
private void EveryEntry_OnCompleted(object? sender, EventArgs e)
{
this.AmountEntry.Focus();
}
}

View File

@ -0,0 +1,84 @@
<VerticalStackLayout x:Class="WheresMyMoney.Maui.PlannedPaymentContent"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="using:WheresMyMoney.Maui" x:DataType="local:FullPlannedPaymentViewModel">
<!-- Separator -->
<BoxView HeightRequest="1"
BackgroundColor="Gray"
Margin="0,10,0,10" />
<!-- Name -->
<Label Text="{Binding Name}"
FontSize="20"
FontAttributes="None"
Margin="0,5,0,5" />
<VerticalStackLayout>
<!-- Amount -->
<Label Text="{Binding Amount}"
FontSize="20"
FontAttributes="Bold"
Margin="0,5,0,5" HorizontalTextAlignment="End" />
<!-- Subscription Indicator -->
<Label Text="Płatność jednorazowa"
FontSize="20"
FontAttributes="None"
Margin="0,5,0,5">
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding Path=IsSubscription}" Value="True">
<Setter Property="Text" Value="Subskrybcja" />
</DataTrigger>
</Label.Triggers>
</Label>
<!-- Start Date -->
<Grid ColumnDefinitions="*,Auto">
<Label Grid.Column="0" Text="dnia"
FontSize="16"
FontAttributes="None"
TextColor="Gray"
Margin="0,5,0,0">
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding Path=IsSubscription}" Value="True">
<Setter Property="Text" Value="od" />
</DataTrigger>
</Label.Triggers>
</Label>
<Label Grid.Column="1" Text="{Binding DateStart}"
FontSize="20"
FontAttributes="None"
Margin="0,0,0,10" HorizontalTextAlignment="End" />
</Grid>
<!-- End Date -->
<Grid ColumnDefinitions="*,Auto" IsVisible="{Binding ShowDateEnd}">
<Label Grid.Column="0" Text="do"
FontSize="16"
FontAttributes="None"
TextColor="Gray"
Margin="0,5,0,0" />
<Label Grid.Column="1" Text="{Binding DateEnd}"
FontSize="20"
FontAttributes="None"
Margin="0,0,0,10" HorizontalTextAlignment="End" />
</Grid>
<!-- Subscription Details -->
<HorizontalStackLayout IsVisible="False"
Margin="0,10,0,0">
<HorizontalStackLayout.Triggers>
<DataTrigger TargetType="HorizontalStackLayout"
Binding="{Binding Path=IsSubscription}"
Value="True">
<Setter Property="IsVisible" Value="True" />
</DataTrigger>
</HorizontalStackLayout.Triggers>
<Label Text="Powtarzaj co"
Margin="0,0,5,0" />
<Label Text="{Binding Reoccurences}"
Margin="0,0,5,0" />
<Label Text="{Binding ReoccurenceType}" />
</HorizontalStackLayout>
</VerticalStackLayout>
</VerticalStackLayout>

View File

@ -0,0 +1,9 @@
namespace WheresMyMoney.Maui;
public partial class PlannedPaymentContent : VerticalStackLayout
{
public PlannedPaymentContent()
{
InitializeComponent();
}
}

View File

@ -10,87 +10,21 @@
Order="Primary"
Clicked="InsertPlannedPayment_OnClicked" />
</ContentPage.ToolbarItems>
<CollectionView ItemsSource="{Binding FullPlannedPaymentViewModels}">
<CollectionView ItemsSource="{Binding FullPlannedPaymentViewModels}" x:DataType="local:PlannedPaymentsPage">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:FullPlannedPaymentViewModel">
<VerticalStackLayout Margin="10,15" Padding="10">
<!-- Separator -->
<BoxView HeightRequest="1"
BackgroundColor="Gray"
Margin="0,10,0,10" />
<Border Margin="10,15" Padding="10" StrokeThickness="0" Background="Transparent">
<FlyoutBase.ContextFlyout>
<MenuFlyout>
<MenuFlyoutItem Text="Modyfikuj" Clicked="ModifyPlannedPayment_OnClicked"
CommandParameter="{Binding Id}" />
<MenuFlyoutItem Text="Usuń" Clicked="RemovePlannedPayment_OnClicked"
CommandParameter="{Binding Id}" />
</MenuFlyout>
</FlyoutBase.ContextFlyout>
<!-- Name -->
<Label Text="{Binding Name}"
FontSize="20"
FontAttributes="None"
Margin="0,5,0,5" />
<Grid ColumnDefinitions="*,Auto">
<VerticalStackLayout Grid.Column="0">
<!-- Amount -->
<Label Text="{Binding Amount}"
FontSize="20"
FontAttributes="Bold"
Margin="0,5,0,10" />
<!-- Subscription Indicator -->
<Label FontSize="20"
FontAttributes="None"
Margin="0,5,0,5">
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding IsSubscription}" Value="True">
<Setter Property="Text" Value="Subskrybcja" />
</DataTrigger>
<DataTrigger TargetType="Label" Binding="{Binding IsSubscription}"
Value="False">
<Setter Property="IsVisible" Value="False" />
</DataTrigger>
</Label.Triggers>
</Label>
<!-- Start Date -->
<Label Text="od"
FontSize="16"
FontAttributes="None"
TextColor="Gray"
Margin="0,5,0,0" />
<Label Text="{Binding DateStart}"
FontSize="20"
FontAttributes="None"
Margin="0,0,0,10" />
<!-- End Date -->
<Label Text="do"
FontSize="16"
FontAttributes="None"
TextColor="Gray"
Margin="0,5,0,0" IsVisible="{Binding ShowDateEnd}" />
<Label Text="{Binding DateEnd}"
FontSize="20"
FontAttributes="None"
Margin="0,0,0,10" IsVisible="{Binding ShowDateEnd}" />
<!-- Subscription Details -->
<HorizontalStackLayout IsVisible="False"
Margin="0,10,0,0">
<HorizontalStackLayout.Triggers>
<DataTrigger TargetType="HorizontalStackLayout"
Binding="{Binding Path=IsSubscription}"
Value="True">
<Setter Property="IsVisible" Value="True" />
</DataTrigger>
</HorizontalStackLayout.Triggers>
<Label Text="Powtarzaj co"
Margin="0,0,5,0" />
<Label Text="{Binding Reoccurences}"
Margin="0,0,5,0" />
<Label Text="{Binding ReoccurenceType}" />
</HorizontalStackLayout>
</VerticalStackLayout>
<Button Grid.Column="1" Text="" FontFamily="FontAwesome" FontSize="32"
Clicked="RemovePlannedPayment_OnClicked"
CommandParameter="{Binding Id}" HorizontalOptions="End" VerticalOptions="Center" />
</Grid>
</VerticalStackLayout>
<local:PlannedPaymentContent />
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>

View File

@ -5,7 +5,7 @@ namespace WheresMyMoney.Maui;
public partial class PlannedPaymentsPage : ContentPage
{
public ObservableCollection<FullPlannedPaymentViewModel> FullPlannedPaymentViewModels { get; set; } = [];
public ObservableCollection<FullPlannedPaymentViewModel> FullPlannedPaymentViewModels { get; } = [];
public PlannedPaymentsPage()
{
@ -31,7 +31,7 @@ public partial class PlannedPaymentsPage : ContentPage
plannedPayment.DateEnd?.ToString("yyyy-MM-dd") ?? string.Empty, plannedPayment.DateEnd is not null,
plannedPayment.IsSubscription,
plannedPayment.Reoccurences,
ReoccurenceTypeToString(plannedPayment.Reoccurences, plannedPayment.ReoccurenceType)));
ReoccurenceTypeToString(plannedPayment.Reoccurences, plannedPayment.ReoccurenceType), null));
}
}
@ -71,9 +71,16 @@ public partial class PlannedPaymentsPage : ContentPage
await Navigation.PushModalAsync(new AddPlannedPaymentPage());
}
private async void ModifyPlannedPayment_OnClicked(object? sender, EventArgs e)
{
if (sender is not MenuFlyoutItem menuItem) return;
var id = (int)menuItem.CommandParameter;
await Navigation.PushModalAsync(new ModifyPlannedPaymentPage(id));
}
private async void RemovePlannedPayment_OnClicked(object? sender, EventArgs e)
{
if (sender is not Button button) return;
if (sender is not MenuFlyoutItem button) return;
var answer = await DisplayAlert("Usunąć?", "Czy na pewno chcesz usunąć tą płatność?", "Tak", "Nie");
if (!answer) return;
var id = (int)button.CommandParameter;

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<toolkit:Popup
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:Class="WheresMyMoney.Maui.PlannedPlannedPopup">
<VerticalStackLayout>
<Button Text="Modyfikuj" Clicked="ModifyPlannedPayment_OnClicked"
BackgroundColor="Transparent"
TextColor="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}}" />
<Button Text="Usuń" Clicked="RemovePlannedPayment_OnClicked"
BackgroundColor="Transparent"
TextColor="{AppThemeBinding Light={StaticResource Error}, Dark={StaticResource ErrorDark}}" />
</VerticalStackLayout>
</toolkit:Popup>

View File

@ -0,0 +1,29 @@
using CommunityToolkit.Maui.Views;
namespace WheresMyMoney.Maui;
public partial class PlannedPlannedPopup : Popup
{
public PlannedPlannedPopup()
{
InitializeComponent();
}
private async void ModifyPlannedPayment_OnClicked(object? sender, EventArgs e)
{
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
await CloseAsync(PlannedPaymentPopupChoice.Modify, cts.Token);
}
private async void RemovePlannedPayment_OnClicked(object? sender, EventArgs e)
{
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
await CloseAsync(PlannedPaymentPopupChoice.Remove, cts.Token);
}
public enum PlannedPaymentPopupChoice
{
Modify,
Remove
}
}

View File

@ -27,6 +27,11 @@
<Color x:Key="Gray600">#404040</Color>
<Color x:Key="Gray900">#212121</Color>
<Color x:Key="Gray950">#141414</Color>
<Color x:Key="Error">#D32F2F</Color>
<Color x:Key="ErrorDark">#FF6659</Color>
<SolidColorBrush x:Key="ErrorBrush" Color="{StaticResource Error}"/>
<SolidColorBrush x:Key="ErrorDarkBrush" Color="{StaticResource ErrorDark}"/>
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/>
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/>

View File

@ -27,8 +27,8 @@
<ApplicationId>pl.mlesniak.wheresmymoney</ApplicationId>
<!-- Versions -->
<ApplicationDisplayVersion>1.0.2</ApplicationDisplayVersion>
<ApplicationVersion>3</ApplicationVersion>
<ApplicationDisplayVersion>1.0.3</ApplicationDisplayVersion>
<ApplicationVersion>4</ApplicationVersion>
<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged -->
<WindowsPackageType>None</WindowsPackageType>
@ -61,12 +61,33 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)"/>
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.0"/>
<PackageReference Include="CommunityToolkit.Maui" Version="11.0.0" />
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.30" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WheresMyMoney.Maui.Core\WheresMyMoney.Maui.Core.csproj" />
</ItemGroup>
<ItemGroup>
<MauiXaml Update="ModifyPlannedPaymentPage.xaml">
<SubType>Designer</SubType>
</MauiXaml>
<MauiXaml Update="MobilePlannedPaymentsPage.xaml">
<SubType>Designer</SubType>
</MauiXaml>
</ItemGroup>
<ItemGroup>
<Compile Update="ModifyPlannedPaymentPage.xaml.cs">
<DependentUpon>ModifyPlannedPaymentPage.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="MobilePlannedPaymentsPage.xaml.cs">
<DependentUpon>MobilePlannedPaymentsPage.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
</Project>