From 4d69bea70ba8531ab0e9238d8ddd95a75826e4c5 Mon Sep 17 00:00:00 2001 From: Tsanie Lily Date: Sat, 26 Feb 2022 12:36:32 +0800 Subject: [PATCH] add account --- Billing.Shared/Languages/Resource.cs | 4 ++ Billing.Shared/Languages/en.xml | 4 ++ Billing.Shared/Languages/zh-CN.xml | 4 ++ Billing.Shared/Models/BaseModel.cs | 2 +- Billing.Shared/UI/Converters.cs | 46 ++++++++++++++++++++- Billing.Shared/UI/Definition.cs | 18 ++++++++ Billing.Shared/UI/OptionsCells.cs | 43 +++++++++++++++++++ Billing.Shared/Views/AccountPage.xaml | 18 ++++++++ Billing.Shared/Views/AccountPage.xaml.cs | 9 ++++ Billing.Shared/Views/AddAccountPage.xaml | 18 +++++--- Billing.Shared/Views/AddAccountPage.xaml.cs | 40 +++++++++++------- Billing.Shared/Views/BillPage.xaml.cs | 9 +++- 12 files changed, 192 insertions(+), 23 deletions(-) diff --git a/Billing.Shared/Languages/Resource.cs b/Billing.Shared/Languages/Resource.cs index 7747641..98fb69d 100644 --- a/Billing.Shared/Languages/Resource.cs +++ b/Billing.Shared/Languages/Resource.cs @@ -10,6 +10,10 @@ namespace Billing.Languages internal class Resource { public static string TitleDateFormat => Text(nameof(TitleDateFormat)); + public static string Cash => Text(nameof(Cash)); + public static string CreditCard => Text(nameof(CreditCard)); + public static string DebitCard => Text(nameof(DebitCard)); + public static string ElecAccount => Text(nameof(ElecAccount)); static readonly Dictionary dict = new(); diff --git a/Billing.Shared/Languages/en.xml b/Billing.Shared/Languages/en.xml index f800353..8d63e7d 100644 --- a/Billing.Shared/Languages/en.xml +++ b/Billing.Shared/Languages/en.xml @@ -27,4 +27,8 @@ Chinese Yuan (CNY) Note Please enter a note + Cash + Credit Card + Debit Card + Electronic Account \ No newline at end of file diff --git a/Billing.Shared/Languages/zh-CN.xml b/Billing.Shared/Languages/zh-CN.xml index dcecf10..f0ce9f2 100644 --- a/Billing.Shared/Languages/zh-CN.xml +++ b/Billing.Shared/Languages/zh-CN.xml @@ -27,4 +27,8 @@ 人民币 (CNY) 备注 请输入备注 + 现金 + 信用卡 + 储蓄卡 + 电子账户 \ No newline at end of file diff --git a/Billing.Shared/Models/BaseModel.cs b/Billing.Shared/Models/BaseModel.cs index 53ed0f9..c5a2d6c 100644 --- a/Billing.Shared/Models/BaseModel.cs +++ b/Billing.Shared/Models/BaseModel.cs @@ -16,7 +16,7 @@ namespace Billing.Models public abstract class BaseModel : IModel, IDisposable { - protected const string ICON_DEFAULT = "ic_default"; + public const string ICON_DEFAULT = "ic_default"; private bool disposed = false; diff --git a/Billing.Shared/UI/Converters.cs b/Billing.Shared/UI/Converters.cs index 766533c..0712086 100644 --- a/Billing.Shared/UI/Converters.cs +++ b/Billing.Shared/UI/Converters.cs @@ -1,4 +1,5 @@ using Billing.Languages; +using Billing.Models; using System; using System.Globalization; using Xamarin.Forms; @@ -24,17 +25,36 @@ namespace Billing.UI public class MoneyConverter : IValueConverter { + public bool MarkVisible { get; set; } = true; + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is decimal d) { - return "¥ " + d.ToString("n2", CultureInfo.InvariantCulture); + var number = d.ToString("n2"); + if (MarkVisible) + { + return "¥ " + number; + } + return number; } return value; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { + if (value is string s) + { + if (s.StartsWith("¥ ")) + { + s = s[2..]; + } + if (decimal.TryParse(s, out decimal d)) + { + return d; + } + return 0m; + } return value; } } @@ -51,4 +71,28 @@ namespace Billing.UI return value; } } + + public class AccountCategoryConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is AccountCategory category) + { + return category switch + { + AccountCategory.Cash => Resource.Cash, + AccountCategory.CreditCard => Resource.CreditCard, + AccountCategory.DebitCard => Resource.DebitCard, + AccountCategory.ElecAccount => Resource.ElecAccount, + _ => category.ToString() + }; + } + return value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return value; + } + } } \ No newline at end of file diff --git a/Billing.Shared/UI/Definition.cs b/Billing.Shared/UI/Definition.cs index b4556fb..9a293e0 100644 --- a/Billing.Shared/UI/Definition.cs +++ b/Billing.Shared/UI/Definition.cs @@ -19,6 +19,24 @@ namespace Billing.UI return obj; } + public static View HorizontalOptions(this View view, LayoutOptions options) + { + if (view != null) + { + view.HorizontalOptions = options; + } + return view; + } + + public static View VerticalOptions(this View view, LayoutOptions options) + { + if (view != null) + { + view.VerticalOptions = options; + } + return view; + } + public static View DynamicResource(this View view, BindableProperty property, string key) { view.SetDynamicResource(property, key); diff --git a/Billing.Shared/UI/OptionsCells.cs b/Billing.Shared/UI/OptionsCells.cs index a3e9efd..e01cd37 100644 --- a/Billing.Shared/UI/OptionsCells.cs +++ b/Billing.Shared/UI/OptionsCells.cs @@ -186,6 +186,49 @@ namespace Billing.UI }; } + public class OptionImageCell : OptionSelectCell + { + public static readonly BindableProperty ImageSourceProperty = BindableProperty.Create(nameof(ImageSource), typeof(ImageSource), typeof(OptionImageCell)); + + [TypeConverter(typeof(ImageSourceConverter))] + public ImageSource ImageSource + { + get => (ImageSource)GetValue(ImageSourceProperty); + set => SetValue(ImageSourceProperty, value); + } + + protected override View Content => new StackLayout + { + Orientation = StackOrientation.Horizontal, + HorizontalOptions = LayoutOptions.End, + Children = + { + new Image + { + HeightRequest = 20, + HorizontalOptions = LayoutOptions.End, + VerticalOptions = LayoutOptions.Center, + Margin = new Thickness(6, 0) + } + .Binding(Image.SourceProperty, nameof(ImageSource)), + + new TintImage + { + HeightRequest = 20, + VerticalOptions = LayoutOptions.Center, + Margin = new Thickness(6, 0), + Source = "right.png" + } + }, + GestureRecognizers = + { + new TapGestureRecognizer() + .Binding(TapGestureRecognizer.CommandProperty, nameof(Command)) + .Binding(TapGestureRecognizer.CommandParameterProperty, nameof(CommandParameter)) + } + }; + } + public class OptionSwitchCell : OptionCell { public static readonly BindableProperty IsToggledProperty = BindableProperty.Create(nameof(IsToggled), typeof(bool), typeof(OptionSwitchCell)); diff --git a/Billing.Shared/Views/AccountPage.xaml b/Billing.Shared/Views/AccountPage.xaml index 6e53c84..598a4f7 100644 --- a/Billing.Shared/Views/AccountPage.xaml +++ b/Billing.Shared/Views/AccountPage.xaml @@ -3,6 +3,7 @@ xmlns:r="clr-namespace:Billing.Languages" xmlns:ui="clr-namespace:Billing.UI" xmlns:v="clr-namespace:Billing.Views" + xmlns:m="clr-namespace:Billing.Models" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Billing.Views.AccountPage" x:Name="accountPage" @@ -12,6 +13,7 @@ + @@ -40,6 +42,22 @@ Text="{Binding Liability, Converter={StaticResource moneyConverter}}"/> + + + + + + + + + \ No newline at end of file diff --git a/Billing.Shared/Views/AccountPage.xaml.cs b/Billing.Shared/Views/AccountPage.xaml.cs index 848a37d..d965a13 100644 --- a/Billing.Shared/Views/AccountPage.xaml.cs +++ b/Billing.Shared/Views/AccountPage.xaml.cs @@ -1,3 +1,5 @@ +using System.Collections.ObjectModel; +using Billing.Models; using Billing.UI; using Xamarin.Forms; @@ -8,16 +10,22 @@ namespace Billing.Views 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(ObservableCollection), typeof(AccountPage)); public decimal Balance => (decimal)GetValue(BalanceProperty); public decimal Asset => (decimal)GetValue(AssetProperty); public decimal Liability => (decimal)GetValue(LiabilityProperty); + public ObservableCollection Accounts => (ObservableCollection)GetValue(AccountsProperty); public Command AddAccount { get; } + private readonly ObservableCollection accounts; + public AccountPage() { AddAccount = new Command(OnAddAccount); + accounts = new ObservableCollection(); + SetValue(AccountsProperty, accounts); InitializeComponent(); } @@ -39,6 +47,7 @@ namespace Billing.Views private void AccountChecked(object sender, AccountEventArgs e) { Helper.Debug(e.Account.ToString()); + accounts.Add(e.Account); } } } \ No newline at end of file diff --git a/Billing.Shared/Views/AddAccountPage.xaml b/Billing.Shared/Views/AddAccountPage.xaml index 0cae955..b16b064 100644 --- a/Billing.Shared/Views/AddAccountPage.xaml +++ b/Billing.Shared/Views/AddAccountPage.xaml @@ -8,7 +8,13 @@ x:Name="addAccountPage" x:DataType="v:AddAccountPage" Title="{r:Text AddAccount}" - BindingContext="{x:Reference addAccountPage}"> + BindingContext="{x:Reference addAccountPage}" + NavigationPage.BackButtonTitle=""> + + + + + @@ -21,17 +27,19 @@ Icon="pencil.png" Text="{Binding AccountName, Mode=TwoWay}" Keyboard="Text" Placeholder="{r:Text AccountNamePlaceholder}"/> - + + Detail="{Binding Category, Converter={StaticResource categoryConverter}}" + Command="{Binding SelectCategory}"/> diff --git a/Billing.Shared/Views/AddAccountPage.xaml.cs b/Billing.Shared/Views/AddAccountPage.xaml.cs index 76c4a6d..e2468f8 100644 --- a/Billing.Shared/Views/AddAccountPage.xaml.cs +++ b/Billing.Shared/Views/AddAccountPage.xaml.cs @@ -9,7 +9,7 @@ namespace Billing.Views { private static readonly BindableProperty AccountNameProperty = BindableProperty.Create(nameof(AccountName), typeof(string), typeof(AddAccountPage)); private static readonly BindableProperty AccountIconProperty = BindableProperty.Create(nameof(AccountIcon), typeof(string), typeof(AddAccountPage)); - private static readonly BindableProperty CategoryProperty = BindableProperty.Create(nameof(Category), typeof(string), typeof(AddAccountPage)); + private static readonly BindableProperty CategoryProperty = BindableProperty.Create(nameof(Category), typeof(AccountCategory), typeof(AddAccountPage)); private static readonly BindableProperty BalanceProperty = BindableProperty.Create(nameof(Balance), typeof(decimal), typeof(AddAccountPage)); private static readonly BindableProperty MemoProperty = BindableProperty.Create(nameof(Memo), typeof(string), typeof(AddAccountPage)); @@ -23,9 +23,9 @@ namespace Billing.Views get => (string)GetValue(AccountIconProperty); set => SetValue(AccountIconProperty, value); } - public string Category + public AccountCategory Category { - get => (string)GetValue(CategoryProperty); + get => (AccountCategory)GetValue(CategoryProperty); set => SetValue(CategoryProperty, value); } public decimal Balance @@ -52,6 +52,8 @@ namespace Billing.Views CheckAccount = new Command(OnCheckAccount); SelectIcon = new Command(OnSelectIcon); SelectCategory = new Command(OnSelectCategory); + AccountIcon = BaseModel.ICON_DEFAULT; + Category = AccountCategory.Cash; InitializeComponent(); } @@ -60,27 +62,35 @@ namespace Billing.Views this.account = account; AccountName = account.Name; AccountIcon = account.Icon; - Category = account.Category.ToString(); + Category = account.Category; Balance = account.Balance; Memo = account.Memo; CheckAccount = new Command(OnCheckAccount); InitializeComponent(); } - private void OnCheckAccount() + private async void OnCheckAccount() { - AccountChecked?.Invoke(this, new AccountEventArgs + if (Tap.IsBusy) { - Account = new Account + return; + } + using (Tap.Start()) + { + await Navigation.PopAsync(); + AccountChecked?.Invoke(this, new AccountEventArgs { - Id = account?.Id ?? -1, - Name = AccountName, - Icon = AccountIcon, - //Category = Category, - Balance = Balance, - Memo = Memo - } - }); + Account = new Account + { + Id = account?.Id ?? -1, + Name = AccountName, + Icon = AccountIcon, + Category = Category, + Balance = Balance, + Memo = Memo + } + }); + } } private void OnSelectIcon() diff --git a/Billing.Shared/Views/BillPage.xaml.cs b/Billing.Shared/Views/BillPage.xaml.cs index ed20a80..2e55c96 100644 --- a/Billing.Shared/Views/BillPage.xaml.cs +++ b/Billing.Shared/Views/BillPage.xaml.cs @@ -39,7 +39,14 @@ namespace Billing.Views private async void OnAddBilling() { - await Navigation.PushAsync(new AddBillPage()); + if (Tap.IsBusy) + { + return; + } + using (Tap.Start()) + { + await Navigation.PushAsync(new AddBillPage()); + } } } } \ No newline at end of file