From db055fa2057c26e7ca389a676efc355302ba8599 Mon Sep 17 00:00:00 2001
From: gaoyuan <gaoyuan@gaoyuandeMacBook-Air.local>
Date: Wed, 9 Mar 2022 00:54:03 +0800
Subject: [PATCH] add chart

---
 Billing.Shared/Languages/Resource.cs  |  1 +
 Billing.Shared/Languages/en.xml       |  2 +
 Billing.Shared/Languages/zh-CN.xml    |  2 +
 Billing.Shared/MainShell.xaml         |  1 +
 Billing.Shared/Themes/BaseTheme.cs    |  2 +
 Billing.Shared/Views/BillPage.xaml    |  4 +-
 Billing.Shared/Views/RankPage.xaml    | 37 ++++++++++-
 Billing.Shared/Views/RankPage.xaml.cs | 88 +++++++++++++++++++++++++--
 8 files changed, 128 insertions(+), 9 deletions(-)

diff --git a/Billing.Shared/Languages/Resource.cs b/Billing.Shared/Languages/Resource.cs
index d7d4b58..081a3a5 100644
--- a/Billing.Shared/Languages/Resource.cs
+++ b/Billing.Shared/Languages/Resource.cs
@@ -15,6 +15,7 @@ namespace Billing.Languages
         public static string ConfirmDeleteAccount => Text(nameof(ConfirmDeleteAccount));
         public static string ConfirmDeleteBill => Text(nameof(ConfirmDeleteBill));
         public static string TitleDateFormat => Text(nameof(TitleDateFormat));
+        public static string DateRangeFormat => Text(nameof(DateRangeFormat));
         public static string Cash => Text(nameof(Cash));
         public static string CreditCard => Text(nameof(CreditCard));
         public static string DebitCard => Text(nameof(DebitCard));
diff --git a/Billing.Shared/Languages/en.xml b/Billing.Shared/Languages/en.xml
index c987631..7c593c9 100644
--- a/Billing.Shared/Languages/en.xml
+++ b/Billing.Shared/Languages/en.xml
@@ -7,6 +7,7 @@
 	<PrimaryColor>Primary Color</PrimaryColor>
 	<Accounts>Accounts</Accounts>
 	<Bills>Bills</Bills>
+	<Report>Report</Report>
 	<Settings>Settings</Settings>
 	<Sunday>Su</Sunday>
 	<Monday>Mo</Monday>
@@ -18,6 +19,7 @@
 	<NoRecords>Bills not yet generated</NoRecords>
 	<TapToMemo>Click here to record</TapToMemo>
 	<TitleDateFormat>MM/dd/yyyy</TitleDateFormat>
+	<DateRangeFormat>MM/dd</DateRangeFormat>
 	<Balance>Balance</Balance>
 	<Assets>Assets</Assets>
 	<Liability>Liability</Liability>
diff --git a/Billing.Shared/Languages/zh-CN.xml b/Billing.Shared/Languages/zh-CN.xml
index 33a0adf..61f5374 100644
--- a/Billing.Shared/Languages/zh-CN.xml
+++ b/Billing.Shared/Languages/zh-CN.xml
@@ -7,6 +7,7 @@
 	<PrimaryColor>主要配色</PrimaryColor>
 	<Accounts>账户</Accounts>
 	<Bills>账单</Bills>
+	<Report>报表</Report>
 	<Settings>设置</Settings>
 	<Sunday>周日</Sunday>
 	<Monday>周一</Monday>
@@ -18,6 +19,7 @@
 	<NoRecords>还未产生账单</NoRecords>
 	<TapToMemo>点此记录</TapToMemo>
 	<TitleDateFormat>yyyy年MM月dd日</TitleDateFormat>
+	<DateRangeFormat>MM月dd日</DateRangeFormat>
 	<Balance>余额</Balance>
 	<Assets>资产</Assets>
 	<Liability>负债</Liability>
diff --git a/Billing.Shared/MainShell.xaml b/Billing.Shared/MainShell.xaml
index 46bb476..3da6c25 100644
--- a/Billing.Shared/MainShell.xaml
+++ b/Billing.Shared/MainShell.xaml
@@ -12,6 +12,7 @@
     <TabBar>
         <ShellContent ContentTemplate="{DataTemplate v:AccountPage}" Route="Accounts" Title="{r:Text Accounts}" Icon="wallet.png"/>
         <ShellContent ContentTemplate="{DataTemplate v:BillPage}" Route="Bills" Title="{r:Text Bills}" Icon="bill.png"/>
+        <ShellContent ContentTemplate="{DataTemplate v:RankPage}" Route="Ranks" Title="{r:Text Report}" Icon="rank.png"/>
         <ShellContent ContentTemplate="{DataTemplate v:SettingPage}" Route="Settings" Title="{r:Text Settings}" Icon="settings.png"/>
     </TabBar>
 
diff --git a/Billing.Shared/Themes/BaseTheme.cs b/Billing.Shared/Themes/BaseTheme.cs
index b87fde4..26f820e 100644
--- a/Billing.Shared/Themes/BaseTheme.cs
+++ b/Billing.Shared/Themes/BaseTheme.cs
@@ -6,6 +6,8 @@ namespace Billing.Themes
     public abstract class BaseTheme : ResourceDictionary
     {
         public static Color CurrentPrimaryColor => (Color)Application.Current.Resources[PrimaryColor];
+        public static Color CurrentTextColor => (Color)Application.Current.Resources[TextColor];
+        public static Color CurrentSecondaryTextColor => (Color)Application.Current.Resources[SecondaryTextColor];
 
         public const string FontSemiBold = nameof(FontSemiBold);
         public const string FontBold = nameof(FontBold);
diff --git a/Billing.Shared/Views/BillPage.xaml b/Billing.Shared/Views/BillPage.xaml
index 8c3543f..c30a8ec 100644
--- a/Billing.Shared/Views/BillPage.xaml
+++ b/Billing.Shared/Views/BillPage.xaml
@@ -23,7 +23,7 @@
     </ContentPage.Resources>
 
     <Shell.TitleView>
-        <Grid ColumnSpacing="16">
+        <Grid>
             <DatePicker x:Name="titleDatePicker" IsVisible="False" Date="{Binding SelectedDate, Mode=TwoWay}"
                         ios:DatePicker.UpdateMode="WhenFinished"
                         DateSelected="TitlePicker_DateSelected"/>
@@ -46,7 +46,7 @@
     </Shell.TitleView>
 
     <ContentPage.ToolbarItems>
-        <ToolbarItem Order="Primary" Priority="1" IconImageSource="plus.png" Command="{Binding EditBilling}"/>
+        <ToolbarItem Order="Primary" IconImageSource="plus.png" Command="{Binding EditBilling}"/>
     </ContentPage.ToolbarItems>
 
     <Grid RowDefinitions="Auto, Auto, *">
diff --git a/Billing.Shared/Views/RankPage.xaml b/Billing.Shared/Views/RankPage.xaml
index 8827fe7..2ddf03d 100644
--- a/Billing.Shared/Views/RankPage.xaml
+++ b/Billing.Shared/Views/RankPage.xaml
@@ -8,6 +8,39 @@
                 x:Class="Billing.Views.RankPage"
                 x:Name="rankPage"
                 x:DataType="v:RankPage"
-                BindingContext="{x:Reference rankPage}">
-    <chart:ChartView Chart="{Binding Chart}"/>
+                BindingContext="{x:Reference rankPage}"
+                Shell.TabBarIsVisible="True">
+
+    <Shell.TitleView>
+        <Grid>
+            <StackLayout Margin="30, 0, 0, 0" HorizontalOptions="Center" VerticalOptions="Center"
+                         Orientation="Horizontal" Spacing="10">
+                <ui:TintImageButton Source="calendar.png" WidthRequest="20" HeightRequest="20"
+                                    VerticalOptions="Center" HorizontalOptions="Start"
+                                    Command="{Binding LeftCommand}"/>
+                <Label Text="{Binding Title}"
+                       TextColor="{DynamicResource PrimaryColor}"
+                       FontSize="{OnPlatform Android=20, iOS=18}">
+                    <Label.FontFamily>
+                        <OnPlatform x:TypeArguments="x:String"
+                                    Android="OpenSans-SemiBold.ttf#OpenSans-SemiBold"
+                                    iOS="OpenSans-Bold"/>
+                    </Label.FontFamily>
+                </Label>
+                <ui:TintImageButton Source="right.png" WidthRequest="20" HeightRequest="20"
+                                    VerticalOptions="Center" HorizontalOptions="End"
+                                    Command="{Binding RightCommand}"/>
+            </StackLayout>
+        </Grid>
+    </Shell.TitleView>
+
+    <ContentPage.ToolbarItems>
+        <ToolbarItem Order="Primary" IconImageSource="plus.png" Command="{Binding FilterCommand}"/>
+    </ContentPage.ToolbarItems>
+
+    <ScrollView>
+        <StackLayout>
+            <chart:ChartView HeightRequest="240" Chart="{Binding Chart}"/>
+        </StackLayout>
+    </ScrollView>
 </ui:BillingPage>
\ No newline at end of file
diff --git a/Billing.Shared/Views/RankPage.xaml.cs b/Billing.Shared/Views/RankPage.xaml.cs
index 8f8d567..9baa2c2 100644
--- a/Billing.Shared/Views/RankPage.xaml.cs
+++ b/Billing.Shared/Views/RankPage.xaml.cs
@@ -1,29 +1,107 @@
-using Billing.UI;
+using Billing.Languages;
+using Billing.Models;
+using Billing.Themes;
+using Billing.UI;
 using Microcharts;
+using SkiaSharp;
+using SkiaSharp.Views.Forms;
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
 using Xamarin.Forms;
-using Xamarin.Forms.Xaml;
 
 namespace Billing.Views
 {
     public partial class RankPage : BillingPage
     {
         private static readonly BindableProperty ChartProperty = Helper.Create<Chart, RankPage>(nameof(Chart));
+        private static readonly BindableProperty TopBillsProperty = Helper.Create<IList<UIBill>, RankPage>(nameof(TopBills));
 
         public Chart Chart
         {
             get => (Chart)GetValue(ChartProperty);
             set => SetValue(ChartProperty, value);
         }
+        public IList<UIBill> TopBills
+        {
+            get => (IList<UIBill>)GetValue(TopBillsProperty);
+            set => SetValue(TopBillsProperty, value);
+        }
+
+        public Command LeftCommand { get; }
+        public Command RightCommand { get; }
+        public Command FilterCommand { get; }
+
+        private DateTime current;
+        private IEnumerable<Bill> bills;
+        private CategoryType type = CategoryType.Spending;
 
         public RankPage()
         {
+            LeftCommand = new Command(OnLeftCommand);
+            RightCommand = new Command(OnRightCommand);
             InitializeComponent();
         }
+
+        public override void OnLoaded()
+        {
+            SetMonth(DateTime.Today);
+        }
+
+        private void OnLeftCommand()
+        {
+            SetMonth(current.AddMonths(-1));
+        }
+
+        private void OnRightCommand()
+        {
+            SetMonth(current.AddMonths(1));
+        }
+
+        private void SetMonth(DateTime date)
+        {
+            current = date.AddDays(1 - date.Day);
+            var end = current.AddDays(DateTime.DaysInMonth(current.Year, current.Month));
+
+            var format = Resource.DateRangeFormat;
+            Title = current.ToString(format) + " ~ " + end.AddDays(-1).ToString(format);
+
+            bills = App.Bills.Where(b => b.CreateTime >= current && b.CreateTime <= end);
+
+            var entries = new List<ChartEntry>();
+            var primaryColor = BaseTheme.CurrentPrimaryColor.ToSKColor();
+            var textColor = BaseTheme.CurrentSecondaryTextColor.ToSKColor();
+            for (var day = current; day <= end; day = day.AddDays(1))
+            {
+                var daybills = bills.Where(b => Helper.IsSameDay(b.CreateTime, day));
+                decimal amount;
+                if (type == CategoryType.Income)
+                {
+                    amount = daybills.Where(b => b.Amount > 0).Sum(b => b.Amount);
+                }
+                else
+                {
+                    amount = daybills.Where(b => b.Amount < 0).Sum(b => -b.Amount);
+                }
+                if (amount > 0)
+                {
+                    entries.Add(new((float)amount)
+                    {
+                        Label = day.ToString("MM/dd"),
+                        ValueLabel = amount.ToString("#,##0.##"),
+                        Color = primaryColor,
+                        TextColor = textColor,
+                        ValueLabelColor = textColor
+                    });
+                }
+            }
+
+            Chart = new LineChart
+            {
+                BackgroundColor = SKColors.Transparent,
+                LabelTextSize = 20,
+                Entries = entries
+            };
+        }
     }
 }
\ No newline at end of file