Billing/Billing.Shared/Views/AccountPage.xaml.cs
2022-03-03 15:22:19 +08:00

165 lines
5.5 KiB
C#

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Billing.Languages;
using Billing.Models;
using Billing.UI;
using Xamarin.Forms;
namespace Billing.Views
{
public partial class AccountPage : BillingPage
{
private static readonly BindableProperty BalanceProperty = BindableProperty.Create(nameof(Balance), typeof(decimal), typeof(AccountPage));
private static readonly BindableProperty AssetProperty = BindableProperty.Create(nameof(Asset), typeof(decimal), typeof(AccountPage));
private static readonly BindableProperty LiabilityProperty = BindableProperty.Create(nameof(Liability), typeof(decimal), typeof(AccountPage));
private static readonly BindableProperty AccountsProperty = BindableProperty.Create(nameof(Accounts), typeof(List<AccountGrouping>), typeof(AccountPage));
public decimal Balance => (decimal)GetValue(BalanceProperty);
public decimal Asset => (decimal)GetValue(AssetProperty);
public decimal Liability => (decimal)GetValue(LiabilityProperty);
public List<AccountGrouping> Accounts => (List<AccountGrouping>)GetValue(AccountsProperty);
public Command EditAccount { get; }
public Command DeleteAccount { get; }
private readonly List<AccountGrouping> accounts = new();
private bool initialized;
public AccountPage()
{
EditAccount = new Command(OnEditAccount);
DeleteAccount = new Command(OnDeleteAccount);
SetValue(AccountsProperty, accounts);
InitializeComponent();
}
protected override void OnAppearing()
{
if (!initialized || accounts.Count == 0)
{
initialized = true;
accounts.Clear();
foreach (var account in App.Accounts)
{
account.Balance = account.Initial + App.Bills.Where(b => b.WalletId == account.Id).Sum(b => b.Amount);
AddToAccountGroup(account);
}
}
else
{
foreach (var account in App.Accounts)
{
account.Balance = account.Initial + App.Bills.Where(b => b.WalletId == account.Id).Sum(b => b.Amount);
}
}
groupLayout.Refresh(accounts);
RefreshBalance();
}
private void RefreshBalance()
{
SetValue(BalanceProperty, App.Accounts.Sum(a => a.Balance));
}
private void AddToAccountGroup(Account account)
{
int maxId;
if (accounts.Count > 0)
{
maxId = accounts.Max(g => g.Max(a => a.Id));
}
else
{
maxId = -1;
}
account.Id = maxId + 1;
var group = accounts.FirstOrDefault(g => g.Key == account.Category);
if (group == null)
{
group = new AccountGrouping(account.Category, account.Balance) { account };
accounts.Add(group);
}
else
{
group.Add(account);
group.Balance += account.Balance;
}
}
private async void OnEditAccount(object o)
{
if (Tap.IsBusy)
{
return;
}
using (Tap.Start())
{
var page = new AddAccountPage(o as Account);
page.AccountChecked += AccountChecked;
await Navigation.PushAsync(page);
}
}
private async void OnDeleteAccount(object o)
{
if (Tap.IsBusy)
{
return;
}
using (Tap.Start())
{
if (o is Account account)
{
var result = await this.ShowConfirm(Resource.ConfirmDeleteAccount);
if (result)
{
App.Accounts.Remove(account);
var group = accounts.FirstOrDefault(a => a.Key == account.Category);
if (group == null)
{
Helper.Error("account.delete", "unexpected deleting account, cannot find the current category");
return;
}
group.Remove(account);
if (group.Count == 0)
{
accounts.Remove(group);
}
groupLayout.Refresh(accounts);
RefreshBalance();
_ = Task.Run(App.WriteAccounts);
}
}
}
}
private void AccountChecked(object sender, AccountEventArgs e)
{
if (e.Account.Id < 0)
{
App.Accounts.Add(e.Account);
AddToAccountGroup(e.Account);
}
groupLayout.Refresh(accounts);
RefreshBalance();
Task.Run(App.WriteAccounts);
}
}
public class AccountGrouping : List<Account>, IGrouping<AccountCategory, Account>
{
public AccountCategory Key { get; }
public decimal Balance { get; set; }
public AccountGrouping(AccountCategory key, decimal balance) : base()
{
Key = key;
Balance = balance;
}
}
}