using Billing.Models; using Billing.UI; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Xamarin.Essentials; using Xamarin.Forms; using Resource = Billing.Languages.Resource; namespace Billing.Views { public partial class BillPage : BillingPage { private static readonly BindableProperty SelectedDateProperty = Helper.Create(nameof(SelectedDate), propertyChanged: OnSelectedDateChanged); private static readonly BindableProperty BillsProperty = Helper.Create, BillPage>(nameof(Bills)); private static readonly BindableProperty NoBillsProperty = Helper.Create(nameof(NoBills), defaultValue: true); private static readonly BindableProperty IncomeProperty = Helper.Create(nameof(Income)); private static readonly BindableProperty SpendingProperty = Helper.Create(nameof(Spending)); private static readonly BindableProperty BalanceProperty = Helper.Create(nameof(Balance)); private static void OnSelectedDateChanged(BillPage page, DateTime old, DateTime @new) { page.titleDatePicker.Unfocus(); } public DateTime SelectedDate { get => (DateTime)GetValue(SelectedDateProperty); set => SetValue(SelectedDateProperty, value); } public List Bills { get => (List)GetValue(BillsProperty); set => SetValue(BillsProperty, value); } public bool NoBills => (bool)GetValue(NoBillsProperty); public decimal Income => (decimal)GetValue(IncomeProperty); public decimal Spending => (decimal)GetValue(SpendingProperty); public decimal Balance => (decimal)GetValue(BalanceProperty); public Command TitleDateTap { get; } public Command TitleLongPressed { get; } public Command EditBilling { get; } public Command DeleteBilling { get; } public BillPage() { TitleDateTap = new Command(OnTitleDateTapped); TitleLongPressed = new Command(OnTitleDateLongPressed); EditBilling = new Command(OnEditBilling); DeleteBilling = new Command(OnDeleteBilling); InitializeComponent(); } public override void OnLoaded() { billingDate.SetDateTime(DateTime.Today); } private void OnDateSelected(object sender, DateEventArgs e) { SelectedDate = e.Date; Task.Run(() => { var bills = App.Bills.Where(b => Helper.IsSameDay(b.CreateTime, e.Date)); Bills = new List(bills.OrderBy(b => b.CreateTime).Select(b => Helper.WrapBill(b))); RefreshBalance(Bills); MainThread.BeginInvokeOnMainThread(async () => await scrollView.ScrollToAsync(0, 0, true)); }); } private void RefreshBalance(List bills) { SetValue(NoBillsProperty, bills.Count == 0); var income = bills.Where(b => b.Amount > 0).Sum(b => b.Amount); var spending = -bills.Where(b => b.Amount < 0).Sum(b => b.Amount); SetValue(IncomeProperty, income); SetValue(SpendingProperty, spending); SetValue(BalanceProperty, income - spending); } private void UpdateBill(UIBill bill) { bill.Icon = App.Categories.FirstOrDefault(c => c.Id == bill.Bill.CategoryId)?.Icon ?? BaseModel.ICON_DEFAULT; bill.Name = bill.Bill.Name; bill.DateCreation = bill.Bill.CreateTime; bill.Amount = bill.Bill.Amount; bill.Wallet = App.Accounts.FirstOrDefault(a => a.Id == bill.Bill.WalletId)?.Name; } private void OnTitleDateTapped() { titleDatePicker.Focus(); } private void TitlePicker_DateSelected(object sender, DateChangedEventArgs e) { if (e.NewDate.Year > 1900) { billingDate.SetDateTime(e.NewDate); } } private void OnTitleDateLongPressed() { billingDate.SetDateTime(DateTime.Today); } private async void OnEditBilling(object o) { if (Tap.IsBusy) { return; } using (Tap.Start()) { AddBillPage page; if (o is UIBill bill) { page = new AddBillPage(bill.Bill); } else { if (App.Accounts.Count == 0) { await this.ShowMessage(Resource.NeedAccount); await Shell.Current.GoToAsync("//Accounts"); return; } page = new AddBillPage(SelectedDate); } page.BillChecked += OnBillChecked; await Navigation.PushAsync(page); } } private async void OnDeleteBilling(object o) { if (Tap.IsBusy) { return; } using (Tap.Start()) { if (o is UIBill bill) { var result = await this.ShowConfirm(Resource.ConfirmDeleteBill); if (result) { var bills = Bills; bills.Remove(bill); App.Bills.Remove(bill.Bill); billsLayout.Refresh(bills); RefreshBalance(bills); _ = Task.Run(App.WriteBills); } } } } private void OnBillChecked(object sender, Bill e) { if (e.Id < 0) { int maxId; if (App.Bills.Count > 0) { maxId = App.Bills.Max(b => b.Id); } else { maxId = -1; } e.Id = maxId + 1; App.Bills.Add(e); var bills = Bills; bills.Add(Helper.WrapBill(e)); Bills = bills.OrderBy(b => b.DateCreation).ToList(); } else { var bill = Bills.FirstOrDefault(b => b.Bill == e); if (bill != null) { UpdateBill(bill); } } RefreshBalance(Bills); Task.Run(App.WriteBills); } } public class UIBill : BindableObject { public static readonly BindableProperty IconProperty = BindableProperty.Create(nameof(Icon), typeof(string), typeof(UIBill)); public static readonly BindableProperty NameProperty = BindableProperty.Create(nameof(Name), typeof(string), typeof(UIBill)); public static readonly BindableProperty DateCreationProperty = BindableProperty.Create(nameof(DateCreation), typeof(DateTime), typeof(UIBill)); public static readonly BindableProperty AmountProperty = BindableProperty.Create(nameof(Amount), typeof(decimal), typeof(UIBill)); public static readonly BindableProperty WalletProperty = BindableProperty.Create(nameof(Wallet), typeof(string), typeof(UIBill)); public string Icon { get => (string)GetValue(IconProperty); set => SetValue(IconProperty, value); } public string Name { get => (string)GetValue(NameProperty); set => SetValue(NameProperty, value); } public DateTime DateCreation { get => (DateTime)GetValue(DateCreationProperty); set => SetValue(DateCreationProperty, value); } public decimal Amount { get => (decimal)GetValue(AmountProperty); set => SetValue(AmountProperty, value); } public string Wallet { get => (string)GetValue(WalletProperty); set => SetValue(WalletProperty, value); } public Bill Bill { get; } public UIBill(Bill bill) { Bill = bill; } } }