category management
This commit is contained in:
247
Billing.Shared/Views/CategoryPage.xaml.cs
Normal file
247
Billing.Shared/Views/CategoryPage.xaml.cs
Normal file
@ -0,0 +1,247 @@
|
||||
using Billing.Languages;
|
||||
using Billing.Models;
|
||||
using Billing.Themes;
|
||||
using Billing.UI;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.Views
|
||||
{
|
||||
public partial class CategoryPage : BillingPage
|
||||
{
|
||||
private static readonly BindableProperty CategoriesProperty = BindableProperty.Create(nameof(Categories), typeof(IList), typeof(CategoryPage));
|
||||
private static readonly BindableProperty IsTopCategoryProperty = BindableProperty.Create(nameof(IsTopCategory), typeof(bool), typeof(CategoryPage));
|
||||
|
||||
public IList Categories
|
||||
{
|
||||
get => (IList)GetValue(CategoriesProperty);
|
||||
set => SetValue(CategoriesProperty, value);
|
||||
}
|
||||
public bool IsTopCategory => (bool)GetValue(IsTopCategoryProperty);
|
||||
|
||||
public Command LongPressed { get; }
|
||||
public Command Tapped { get; }
|
||||
|
||||
private readonly int parentId;
|
||||
|
||||
public CategoryPage(int pid = -1)
|
||||
{
|
||||
parentId = pid;
|
||||
var category = App.Categories.FirstOrDefault(c => c.Id == pid);
|
||||
Title = category?.Name ?? Resource.CategoryManage;
|
||||
|
||||
if (category != null)
|
||||
{
|
||||
SetValue(IsTopCategoryProperty, false);
|
||||
Categories = App.Categories.Where(c => c.ParentId == pid).Select(c => WrapCategory(c)).ToList();
|
||||
ToolbarItems.Add(new ToolbarItem
|
||||
{
|
||||
Order = ToolbarItemOrder.Primary,
|
||||
IconImageSource = "plus.png",
|
||||
Command = new Command(OnAddCategory)
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValue(IsTopCategoryProperty, true);
|
||||
Categories = new List<CategoryGrouping>
|
||||
{
|
||||
new(Resource.Spending, App.Categories.Where(c => c.Type == CategoryType.Spending && c.ParentId == null).Select(c => WrapCategory(c))),
|
||||
new(Resource.Income, App.Categories.Where(c => c.Type == CategoryType.Income && c.ParentId == null).Select(c => WrapCategory(c)))
|
||||
};
|
||||
}
|
||||
|
||||
LongPressed = new Command(OnLongPressed);
|
||||
Tapped = new Command(OnTapped);
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private UICategory WrapCategory(Category category)
|
||||
{
|
||||
return new UICategory(category)
|
||||
{
|
||||
Icon = category.Icon,
|
||||
Name = category.Name,
|
||||
IsTopCategory = IsTopCategory,
|
||||
TintColor = category.TintColor == Color.Transparent || category.TintColor == default ?
|
||||
(Color)Application.Current.Resources[BaseTheme.PrimaryColor] :
|
||||
category.TintColor
|
||||
};
|
||||
}
|
||||
|
||||
private async void OnAddCategory()
|
||||
{
|
||||
if (Tap.IsBusy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
using (Tap.Start())
|
||||
{
|
||||
var page = new AddCategoryPage();
|
||||
page.CategoryChecked += OnCategoryChecked;
|
||||
await Navigation.PushAsync(page);
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnLongPressed(object o)
|
||||
{
|
||||
if (Tap.IsBusy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
using (Tap.Start())
|
||||
{
|
||||
if (o is UICategory c)
|
||||
{
|
||||
if (parentId < 0)
|
||||
{
|
||||
var page = new AddCategoryPage(c.Category.Id);
|
||||
page.CategoryChecked += OnCategoryChecked;
|
||||
await Navigation.PushAsync(page);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await this.ShowConfirm(string.Format(Resource.ConfirmDeleteCategory, c.Category.Name));
|
||||
if (result)
|
||||
{
|
||||
Categories.Remove(c);
|
||||
groupLayout.Refresh(Categories);
|
||||
App.Categories.Remove(c.Category);
|
||||
_ = Task.Run(App.WriteCategories);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnTapped(object o)
|
||||
{
|
||||
if (Tap.IsBusy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
using (Tap.Start())
|
||||
{
|
||||
if (o is UICategory c)
|
||||
{
|
||||
if (parentId < 0)
|
||||
{
|
||||
var page = new CategoryPage(c.Category.Id);
|
||||
await Navigation.PushAsync(page);
|
||||
}
|
||||
else
|
||||
{
|
||||
var page = new AddCategoryPage(c.Category.Id);
|
||||
page.CategoryChecked += OnCategoryChecked;
|
||||
await Navigation.PushAsync(page);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCategoryChecked(object sender, Category category)
|
||||
{
|
||||
if (category.Id < 0)
|
||||
{
|
||||
// add
|
||||
int maxId;
|
||||
if (App.Categories.Count > 0)
|
||||
{
|
||||
maxId = App.Categories.Max(b => b.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
maxId = -1;
|
||||
}
|
||||
category.Id = maxId + 1;
|
||||
App.Categories.Add(category);
|
||||
Categories.Add(WrapCategory(category));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var o in Categories)
|
||||
{
|
||||
if (o is CategoryGrouping grouping)
|
||||
{
|
||||
var c = grouping.FirstOrDefault(c => c.Category == category);
|
||||
if (c != null)
|
||||
{
|
||||
UpdateCategory(c);
|
||||
}
|
||||
}
|
||||
else if (o is UICategory c && c.Category == category)
|
||||
{
|
||||
UpdateCategory(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
groupLayout.Refresh(Categories);
|
||||
|
||||
Task.Run(App.WriteCategories);
|
||||
}
|
||||
|
||||
private void UpdateCategory(UICategory c)
|
||||
{
|
||||
c.Name = c.Category.Name;
|
||||
c.Icon = c.Category.Icon;
|
||||
c.TintColor = c.Category.TintColor;
|
||||
}
|
||||
}
|
||||
|
||||
public class UICategory : BindableObject
|
||||
{
|
||||
public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create(nameof(IsChecked), typeof(bool), typeof(UICategory));
|
||||
public static readonly BindableProperty IconProperty = BindableProperty.Create(nameof(Icon), typeof(string), typeof(UICategory));
|
||||
public static readonly BindableProperty NameProperty = BindableProperty.Create(nameof(Name), typeof(string), typeof(UICategory));
|
||||
public static readonly BindableProperty TintColorProperty = BindableProperty.Create(nameof(TintColor), typeof(Color), typeof(UICategory));
|
||||
public static readonly BindableProperty IsTopCategoryProperty = BindableProperty.Create(nameof(IsTopCategory), typeof(bool), typeof(UICategory));
|
||||
|
||||
public bool IsChecked
|
||||
{
|
||||
get => (bool)GetValue(IsCheckedProperty);
|
||||
set => SetValue(IsCheckedProperty, value);
|
||||
}
|
||||
public string Icon
|
||||
{
|
||||
get => (string)GetValue(IconProperty);
|
||||
set => SetValue(IconProperty, value);
|
||||
}
|
||||
public string Name
|
||||
{
|
||||
get => (string)GetValue(NameProperty);
|
||||
set => SetValue(NameProperty, value);
|
||||
}
|
||||
public Color TintColor
|
||||
{
|
||||
get => (Color)GetValue(TintColorProperty);
|
||||
set => SetValue(TintColorProperty, value);
|
||||
}
|
||||
public bool IsTopCategory
|
||||
{
|
||||
get => (bool)GetValue(IsTopCategoryProperty);
|
||||
set => SetValue(IsTopCategoryProperty, value);
|
||||
}
|
||||
|
||||
public Category Category { get; }
|
||||
|
||||
public UICategory(Category category)
|
||||
{
|
||||
Category = category;
|
||||
}
|
||||
}
|
||||
|
||||
public class CategoryGrouping : List<UICategory>, IGrouping<string, UICategory>
|
||||
{
|
||||
public string Key { get; }
|
||||
|
||||
public CategoryGrouping(string key, IEnumerable<UICategory> categories) : base(categories)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user