initial
This commit is contained in:
61
Billing.Shared/App.cs
Normal file
61
Billing.Shared/App.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using Billing.Languages;
|
||||
using Billing.Themes;
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing;
|
||||
|
||||
public class App : Application
|
||||
{
|
||||
public static AppTheme CurrentTheme { get; private set; }
|
||||
public static PlatformCulture CurrentCulture { get; private set; }
|
||||
|
||||
public App()
|
||||
{
|
||||
CurrentCulture = new PlatformCulture();
|
||||
InitResources();
|
||||
|
||||
MainPage = new MainShell();
|
||||
Shell.Current.GoToAsync("//Bills");
|
||||
}
|
||||
|
||||
protected override void OnStart()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnResume()
|
||||
{
|
||||
SetTheme(AppInfo.RequestedTheme);
|
||||
}
|
||||
|
||||
private void InitResources()
|
||||
{
|
||||
var theme = AppInfo.RequestedTheme;
|
||||
SetTheme(theme, true);
|
||||
}
|
||||
|
||||
private void SetTheme(AppTheme theme, bool force = false)
|
||||
{
|
||||
if (force || theme != CurrentTheme)
|
||||
{
|
||||
CurrentTheme = theme;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
Helper.Debug($"application theme: {theme}");
|
||||
|
||||
BaseTheme instance;
|
||||
if (theme == AppTheme.Dark)
|
||||
{
|
||||
instance = Dark.Instance;
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = Light.Instance;
|
||||
}
|
||||
// TODO: status bar
|
||||
Resources = instance;
|
||||
}
|
||||
}
|
3
Billing.Shared/AssemblyInfo.cs
Normal file
3
Billing.Shared/AssemblyInfo.cs
Normal file
@@ -0,0 +1,3 @@
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
|
73
Billing.Shared/Billing.Shared.projitems
Normal file
73
Billing.Shared/Billing.Shared.projitems
Normal file
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' < '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
<HasSharedItems>true</HasSharedItems>
|
||||
<SharedGUID>6ac75d01-70d6-4a07-8685-bc52afd97a7a</SharedGUID>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<Import_RootNamespace>Billing</Import_RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Languages\en.xml" />
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Languages\zh-CN.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)App.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)AssemblyInfo.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Helper.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Languages\PlatformCulture.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Languages\Resource.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)MainShell.xaml.cs">
|
||||
<DependentUpon>MainShell.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Themes\BaseTheme.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Themes\Dark.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Themes\Light.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)UI\BillingDate.xaml.cs">
|
||||
<DependentUpon>BillingDate.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)UI\BillingPage.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)UI\Converters.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)UI\CustomControl.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)UI\Definition.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Views\AccountPage.xaml.cs">
|
||||
<DependentUpon>AccountPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Views\AddBillPage.xaml.cs">
|
||||
<DependentUpon>AddBillPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Views\BillPage.xaml.cs">
|
||||
<DependentUpon>BillPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Views\SettingPage.xaml.cs">
|
||||
<DependentUpon>SettingPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)MainShell.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)UI\BillingDate.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Views\AccountPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Views\AddBillPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Views\BillPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Views\SettingPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
13
Billing.Shared/Billing.Shared.shproj
Normal file
13
Billing.Shared/Billing.Shared.shproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>6ac75d01-70d6-4a07-8685-bc52afd97a7a</ProjectGuid>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
|
||||
<PropertyGroup />
|
||||
<Import Project="Billing.Shared.projitems" Label="Shared" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
|
||||
</Project>
|
23
Billing.Shared/Helper.cs
Normal file
23
Billing.Shared/Helper.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
|
||||
namespace Billing;
|
||||
|
||||
internal static class Helper
|
||||
{
|
||||
public static void Debug(string message)
|
||||
{
|
||||
var time = DateTime.Now.ToString("HH:mm:ss.fff");
|
||||
System.Diagnostics.Debug.WriteLine($"[{time}] - {message}");
|
||||
}
|
||||
|
||||
public static void Error(string category, Exception ex)
|
||||
{
|
||||
Error(category, ex?.Message ?? "unknown error");
|
||||
}
|
||||
|
||||
public static void Error(string category, string message)
|
||||
{
|
||||
var time = DateTime.Now.ToString("HH:mm:ss.fff");
|
||||
System.Diagnostics.Debug.Fail($"[{time}] - {category}", message);
|
||||
}
|
||||
}
|
61
Billing.Shared/Languages/PlatformCulture.cs
Normal file
61
Billing.Shared/Languages/PlatformCulture.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
namespace Billing.Languages
|
||||
{
|
||||
public partial class PlatformCulture
|
||||
{
|
||||
public string PlatformString { get; set; }
|
||||
public string LanguageCode { get; set; }
|
||||
public string LocaleCode { get; set; }
|
||||
|
||||
public string Language => string.IsNullOrEmpty(LocaleCode) ? LanguageCode : LanguageCode + "-" + LocaleCode;
|
||||
|
||||
public partial string GetNamespace();
|
||||
public partial void Init();
|
||||
|
||||
public PlatformCulture()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
private void Init(string cultureString)
|
||||
{
|
||||
if (string.IsNullOrEmpty(cultureString))
|
||||
{
|
||||
cultureString = "zh-CN";
|
||||
}
|
||||
|
||||
PlatformString = cultureString.Replace('_', '-');
|
||||
if (PlatformString.Contains('-'))
|
||||
{
|
||||
var parts = PlatformString.Split('-');
|
||||
LanguageCode = parts[0];
|
||||
LocaleCode = parts[^1];
|
||||
}
|
||||
else
|
||||
{
|
||||
LanguageCode = PlatformString;
|
||||
LocaleCode = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private string ToDotnetFallbackLanguage()
|
||||
{
|
||||
string netLanguage = LanguageCode switch
|
||||
{
|
||||
// fallback to Portuguese (Portugal)
|
||||
"pt" => "pt-PT",
|
||||
// equivalent to German (Switzerland) for this app
|
||||
"gsw" => "de-CH",
|
||||
|
||||
// add more application-specific cases here (if required)
|
||||
// ONLY use cultures that have been tested and known to work
|
||||
|
||||
// use the first part of the identifier (two chars, usually);
|
||||
_ => LanguageCode,
|
||||
};
|
||||
Helper.Debug($".NET Fallback Language/Locale: {LanguageCode} to {netLanguage} (application-specific)");
|
||||
return netLanguage;
|
||||
}
|
||||
|
||||
public override string ToString() => PlatformString;
|
||||
}
|
||||
}
|
95
Billing.Shared/Languages/Resource.cs
Normal file
95
Billing.Shared/Languages/Resource.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace Billing.Languages
|
||||
{
|
||||
internal class Resource
|
||||
{
|
||||
public static string TitleDateFormat => Text(nameof(TitleDateFormat));
|
||||
|
||||
static readonly Dictionary<string, LanguageResource> dict = new();
|
||||
|
||||
public static string Text(string name, params object[] args)
|
||||
{
|
||||
string current = App.CurrentCulture.PlatformString;
|
||||
if (!dict.TryGetValue(current, out LanguageResource lang))
|
||||
{
|
||||
lang = new LanguageResource(App.CurrentCulture);
|
||||
dict.Add(current, lang);
|
||||
}
|
||||
if (args == null || args.Length == 0)
|
||||
{
|
||||
return lang[name];
|
||||
}
|
||||
return string.Format(lang[name], args);
|
||||
}
|
||||
|
||||
private class LanguageResource
|
||||
{
|
||||
private readonly Dictionary<string, string> strings;
|
||||
|
||||
public string this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (strings?.TryGetValue(key, out string val) == true)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
public LanguageResource(PlatformCulture lang)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ns = lang.GetNamespace();
|
||||
var langId = $"{ns}.Languages.{lang.Language}.xml";
|
||||
var langCodeId = $"{ns}.Languages.{lang.LanguageCode}.xml";
|
||||
var assembly = typeof(LanguageResource).Assembly;
|
||||
var name = assembly.GetManifestResourceNames().FirstOrDefault(n =>
|
||||
string.Equals(n, langId, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(n, langCodeId, StringComparison.OrdinalIgnoreCase));
|
||||
if (name == null)
|
||||
{
|
||||
name = $"{ns}.Languages.zh-CN.xml";
|
||||
}
|
||||
var xml = new XmlDocument();
|
||||
using (var stream = assembly.GetManifestResourceStream(name))
|
||||
{
|
||||
xml.Load(stream);
|
||||
}
|
||||
strings = new Dictionary<string, string>();
|
||||
foreach (XmlElement ele in xml.DocumentElement)
|
||||
{
|
||||
strings[ele.Name] = ele.InnerText;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Helper.Error("language.ctor", $"failed to load json resource: {lang}, {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ContentProperty(nameof(Text))]
|
||||
public class TextExtension : IMarkupExtension
|
||||
{
|
||||
public string Text { get; set; }
|
||||
|
||||
public object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
if (Text == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
return Resource.Text(Text);
|
||||
}
|
||||
}
|
||||
}
|
16
Billing.Shared/Languages/en.xml
Normal file
16
Billing.Shared/Languages/en.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<Accounts>Accounts</Accounts>
|
||||
<Bills>Bills</Bills>
|
||||
<Settings>Settings</Settings>
|
||||
<Sunday>Su</Sunday>
|
||||
<Monday>Mo</Monday>
|
||||
<Tuesday>Tu</Tuesday>
|
||||
<Wednesday>We</Wednesday>
|
||||
<Thursday>Th</Thursday>
|
||||
<Friday>Fr</Friday>
|
||||
<Saturday>Sa</Saturday>
|
||||
<NoRecords>Bills not yet generated</NoRecords>
|
||||
<Memo>Click here to record</Memo>
|
||||
<TitleDateFormat>MM/dd/yyyy</TitleDateFormat>
|
||||
</root>
|
16
Billing.Shared/Languages/zh-CN.xml
Normal file
16
Billing.Shared/Languages/zh-CN.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<Accounts>账户</Accounts>
|
||||
<Bills>账单</Bills>
|
||||
<Settings>设置</Settings>
|
||||
<Sunday>周日</Sunday>
|
||||
<Monday>周一</Monday>
|
||||
<Tuesday>周二</Tuesday>
|
||||
<Wednesday>周三</Wednesday>
|
||||
<Thursday>周四</Thursday>
|
||||
<Friday>周五</Friday>
|
||||
<Saturday>周六</Saturday>
|
||||
<NoRecords>还未产生账单</NoRecords>
|
||||
<Memo>点此记录</Memo>
|
||||
<TitleDateFormat>yyyy年MM月dd日</TitleDateFormat>
|
||||
</root>
|
18
Billing.Shared/MainShell.xaml
Normal file
18
Billing.Shared/MainShell.xaml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:v="clr-namespace:Billing.Views"
|
||||
xmlns:r="clr-namespace:Billing.Languages"
|
||||
x:Class="Billing.MainShell"
|
||||
BackgroundColor="{DynamicResource WindowBackgroundColor}"
|
||||
ForegroundColor="{DynamicResource PrimaryColor}"
|
||||
TitleColor="{DynamicResource PrimaryColor}"
|
||||
Shell.NavBarHasShadow="True">
|
||||
|
||||
<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:SettingPage}" Route="Settings" Title="{r:Text Settings}" Icon="settings.png"/>
|
||||
</TabBar>
|
||||
|
||||
</Shell>
|
11
Billing.Shared/MainShell.xaml.cs
Normal file
11
Billing.Shared/MainShell.xaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing;
|
||||
|
||||
public partial class MainShell : Shell
|
||||
{
|
||||
public MainShell()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
65
Billing.Shared/Themes/BaseTheme.cs
Normal file
65
Billing.Shared/Themes/BaseTheme.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using Billing.UI;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.Themes;
|
||||
|
||||
public abstract class BaseTheme : ResourceDictionary
|
||||
{
|
||||
public const string CascadiaFontRegular = nameof(CascadiaFontRegular);
|
||||
public const string CascadiaFontBold = nameof(CascadiaFontBold);
|
||||
public const string RobotoCondensedFontRegular = nameof(RobotoCondensedFontRegular);
|
||||
public const string RobotoCondensedFontBold = nameof(RobotoCondensedFontBold);
|
||||
public const string WindowBackgroundColor = nameof(WindowBackgroundColor);
|
||||
public const string PromptBackgroundColor = nameof(PromptBackgroundColor);
|
||||
public const string PrimaryColor = nameof(PrimaryColor);
|
||||
public const string SecondaryColor = nameof(SecondaryColor);
|
||||
public const string TabBarBackgroundColor = nameof(TabBarBackgroundColor);
|
||||
public const string TabBarTitleColor = nameof(TabBarTitleColor);
|
||||
public const string TabBarUnselectedColor = nameof(TabBarUnselectedColor);
|
||||
public const string OutRangeDayColor = nameof(OutRangeDayColor);
|
||||
public const string TextColor = nameof(TextColor);
|
||||
public const string WeekendColor = nameof(WeekendColor);
|
||||
|
||||
protected abstract Color PrimaryMauiColor { get; }
|
||||
protected abstract Color SecondaryMauiColor { get; }
|
||||
|
||||
protected void InitResources()
|
||||
{
|
||||
var robotoRegularFontFamily = Definition.GetRobotoCondensedRegularFontFamily();
|
||||
Add(CascadiaFontRegular, Definition.GetCascadiaRegularFontFamily());
|
||||
Add(CascadiaFontBold, Definition.GetCascadiaBoldFontFamily());
|
||||
Add(RobotoCondensedFontRegular, Definition.GetRobotoCondensedRegularFontFamily());
|
||||
Add(RobotoCondensedFontBold, Definition.GetRobotoCondensedBoldFontFamily());
|
||||
|
||||
Add(PrimaryColor, PrimaryMauiColor);
|
||||
Add(SecondaryColor, SecondaryMauiColor);
|
||||
Add(TabBarTitleColor, PrimaryMauiColor);
|
||||
|
||||
Add(new Style(typeof(Label))
|
||||
{
|
||||
Setters =
|
||||
{
|
||||
new Setter { Property = Label.FontSizeProperty, Value = Device.GetNamedSize(NamedSize.Small, typeof(Label)) },
|
||||
new Setter { Property = Label.TextColorProperty, Value = PrimaryMauiColor },
|
||||
new Setter { Property = Label.FontFamilyProperty, Value = robotoRegularFontFamily }
|
||||
}
|
||||
});
|
||||
Add(new Style(typeof(Button))
|
||||
{
|
||||
Setters =
|
||||
{
|
||||
new Setter { Property = Button.TextColorProperty, Value = SecondaryMauiColor },
|
||||
new Setter { Property = Button.FontFamilyProperty, Value = robotoRegularFontFamily },
|
||||
new Setter { Property = VisualElement.BackgroundColorProperty, Value = PrimaryMauiColor },
|
||||
new Setter { Property = Button.PaddingProperty, Value = new Thickness(14, 10) }
|
||||
}
|
||||
});
|
||||
Add(new Style(typeof(TintImage))
|
||||
{
|
||||
Setters =
|
||||
{
|
||||
new Setter { Property = TintImage.PrimaryColorProperty, Value = PrimaryMauiColor }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
40
Billing.Shared/Themes/Dark.cs
Normal file
40
Billing.Shared/Themes/Dark.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.Themes;
|
||||
|
||||
public class Dark : BaseTheme
|
||||
{
|
||||
private static Dark _instance;
|
||||
|
||||
public static Dark Instance => _instance ??= new Dark();
|
||||
|
||||
protected override Color PrimaryMauiColor => Color.White;
|
||||
protected override Color SecondaryMauiColor => Color.LightGray;
|
||||
|
||||
public Dark()
|
||||
{
|
||||
InitColors();
|
||||
InitResources();
|
||||
}
|
||||
|
||||
private void InitColors()
|
||||
{
|
||||
Add(WindowBackgroundColor, Color.Black);
|
||||
Add(PromptBackgroundColor, Color.FromRgb(0x1f, 0x1f, 0x1f));
|
||||
Add(TabBarBackgroundColor, Color.Black);
|
||||
Add(TabBarUnselectedColor, Color.FromRgb(0x82, 0x82, 0x82));
|
||||
Add(OutRangeDayColor, Color.DarkGray);
|
||||
Add(TextColor, Color.FromRgb(0xcc, 0xcc, 0xcc));
|
||||
Add(WeekendColor, Color.FromRgb(211, 5, 5));
|
||||
|
||||
Add(new Style(typeof(TabBar))
|
||||
{
|
||||
Setters =
|
||||
{
|
||||
new Setter { Property = Shell.TabBarBackgroundColorProperty, Value = Color.Black },
|
||||
new Setter { Property = Shell.TabBarTitleColorProperty, Value = PrimaryMauiColor },
|
||||
new Setter { Property = Shell.TabBarUnselectedColorProperty, Value = Color.FromRgb(0x82, 0x82, 0x82) }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
40
Billing.Shared/Themes/Light.cs
Normal file
40
Billing.Shared/Themes/Light.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.Themes;
|
||||
|
||||
public class Light : BaseTheme
|
||||
{
|
||||
private static Light _instance;
|
||||
|
||||
public static Light Instance => _instance ??= new Light();
|
||||
|
||||
protected override Color PrimaryMauiColor => Color.FromRgb(0x18, 0x31, 0x53);
|
||||
protected override Color SecondaryMauiColor => Color.White;
|
||||
|
||||
public Light()
|
||||
{
|
||||
InitColors();
|
||||
InitResources();
|
||||
}
|
||||
|
||||
private void InitColors()
|
||||
{
|
||||
Add(WindowBackgroundColor, Color.White);
|
||||
Add(PromptBackgroundColor, Color.FromRgb(0xe0, 0xe0, 0xe0));
|
||||
Add(TabBarBackgroundColor, Color.White);
|
||||
Add(TabBarUnselectedColor, Color.FromRgb(0x82, 0x82, 0x82));
|
||||
Add(OutRangeDayColor, Color.LightGray);
|
||||
Add(TextColor, Color.FromRgb(0x33, 0x33, 0x33));
|
||||
Add(WeekendColor, Color.FromRgb(211, 64, 85));
|
||||
|
||||
Add(new Style(typeof(TabBar))
|
||||
{
|
||||
Setters =
|
||||
{
|
||||
new Setter { Property = Shell.TabBarBackgroundColorProperty, Value = Color.White },
|
||||
new Setter { Property = Shell.TabBarTitleColorProperty, Value = PrimaryMauiColor },
|
||||
new Setter { Property = Shell.TabBarUnselectedColorProperty, Value = Color.FromRgb(0x82, 0x82, 0x82) }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
76
Billing.Shared/UI/BillingDate.xaml
Normal file
76
Billing.Shared/UI/BillingDate.xaml
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:r="clr-namespace:Billing.Languages"
|
||||
xmlns:ui="clr-namespace:Billing.UI"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Billing.UI.BillingDate"
|
||||
x:DataType="ui:BillingDate"
|
||||
x:Name="billingDate"
|
||||
BindingContext="{x:Reference billingDate}">
|
||||
<ContentView.Resources>
|
||||
<Style x:Key="centerLabel" TargetType="Label">
|
||||
<Setter Property="HorizontalOptions" Value="Center"/>
|
||||
<Setter Property="FontSize" Value="Small"/>
|
||||
<Setter Property="TextColor" Value="{DynamicResource TextColor}"/>
|
||||
</Style>
|
||||
<Style x:Key="dateLabel" TargetType="Label">
|
||||
<Setter Property="HorizontalOptions" Value="Center"/>
|
||||
</Style>
|
||||
<ControlTemplate x:Key="weekDay">
|
||||
<Grid Padding="0, 8, 0, 0" RowDefinitions="Auto, 3" RowSpacing="0">
|
||||
<Grid.GestureRecognizers>
|
||||
<TapGestureRecognizer Command="{Binding OnDayTapped, Source={x:Reference billingDate}}" CommandParameter="{TemplateBinding BillingDay}"/>
|
||||
</Grid.GestureRecognizers>
|
||||
<Label Style="{StaticResource dateLabel}" Text="{TemplateBinding BillingDay.Text}"
|
||||
TextColor="{DynamicResource TextColor}"
|
||||
FontFamily="{TemplateBinding BillingDay.FontFamily}"
|
||||
Opacity="{TemplateBinding BillingDay.TextOpacity}"/>
|
||||
<StackLayout Grid.Row="1"
|
||||
IsVisible="{TemplateBinding BillingDay.IsSelected}"
|
||||
BackgroundColor="{DynamicResource PrimaryColor}"
|
||||
Opacity="{TemplateBinding BillingDay.Opacity}"/>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="weekEnd">
|
||||
<Grid Padding="0, 8, 0, 0" RowDefinitions="Auto, 3" RowSpacing="0">
|
||||
<Grid.GestureRecognizers>
|
||||
<TapGestureRecognizer Command="{Binding OnDayTapped, Source={x:Reference billingDate}}" CommandParameter="{TemplateBinding BillingDay}"/>
|
||||
</Grid.GestureRecognizers>
|
||||
<Label Style="{StaticResource dateLabel}" Text="{TemplateBinding BillingDay.Text}"
|
||||
TextColor="{DynamicResource WeekendColor}"
|
||||
FontFamily="{TemplateBinding BillingDay.FontFamily}"
|
||||
Opacity="{TemplateBinding BillingDay.TextOpacity}"/>
|
||||
<StackLayout Grid.Row="1"
|
||||
IsVisible="{TemplateBinding BillingDay.IsSelected}"
|
||||
BackgroundColor="{DynamicResource PrimaryColor}"
|
||||
Opacity="{TemplateBinding BillingDay.Opacity}"/>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
<Style TargetType="ui:BillingDayView">
|
||||
<Setter Property="ControlTemplate" Value="{StaticResource weekDay}"/>
|
||||
</Style>
|
||||
</ContentView.Resources>
|
||||
<ContentView.Content>
|
||||
<Grid Padding="0, 8, 0, 4" ColumnDefinitions="*,*,*,*,*,*,*" RowDefinitions="Auto, Auto">
|
||||
<Grid.GestureRecognizers>
|
||||
<PanGestureRecognizer PanUpdated="OnPanUpdated"/>
|
||||
</Grid.GestureRecognizers>
|
||||
|
||||
<Label Grid.Column="0" Text="{r:Text Sunday}" Style="{StaticResource centerLabel}"/>
|
||||
<Label Grid.Column="1" Text="{r:Text Monday}" Style="{StaticResource centerLabel}"/>
|
||||
<Label Grid.Column="2" Text="{r:Text Tuesday}" Style="{StaticResource centerLabel}"/>
|
||||
<Label Grid.Column="3" Text="{r:Text Wednesday}" Style="{StaticResource centerLabel}"/>
|
||||
<Label Grid.Column="4" Text="{r:Text Thursday}" Style="{StaticResource centerLabel}"/>
|
||||
<Label Grid.Column="5" Text="{r:Text Friday}" Style="{StaticResource centerLabel}"/>
|
||||
<Label Grid.Column="6" Text="{r:Text Saturday}" Style="{StaticResource centerLabel}"/>
|
||||
|
||||
<ui:BillingDayView Grid.Row="1" Grid.Column="0" BillingDay="{Binding Sunday}" ControlTemplate="{StaticResource weekEnd}"/>
|
||||
<ui:BillingDayView Grid.Row="1" Grid.Column="1" BillingDay="{Binding Monday}"/>
|
||||
<ui:BillingDayView Grid.Row="1" Grid.Column="2" BillingDay="{Binding Tuesday}"/>
|
||||
<ui:BillingDayView Grid.Row="1" Grid.Column="3" BillingDay="{Binding Wednesday}"/>
|
||||
<ui:BillingDayView Grid.Row="1" Grid.Column="4" BillingDay="{Binding Thursday}"/>
|
||||
<ui:BillingDayView Grid.Row="1" Grid.Column="5" BillingDay="{Binding Friday}"/>
|
||||
<ui:BillingDayView Grid.Row="1" Grid.Column="6" BillingDay="{Binding Saturday}" ControlTemplate="{StaticResource weekEnd}"/>
|
||||
</Grid>
|
||||
</ContentView.Content>
|
||||
</ContentView>
|
290
Billing.Shared/UI/BillingDate.xaml.cs
Normal file
290
Billing.Shared/UI/BillingDate.xaml.cs
Normal file
@@ -0,0 +1,290 @@
|
||||
using Billing.Themes;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.UI;
|
||||
|
||||
public partial class BillingDate : ContentView
|
||||
{
|
||||
#region UI Properties
|
||||
|
||||
private static readonly BindableProperty SundayProperty = BindableProperty.Create(nameof(Sunday), typeof(BillingDay), typeof(BillingDate));
|
||||
private static readonly BindableProperty MondayProperty = BindableProperty.Create(nameof(Monday), typeof(BillingDay), typeof(BillingDate));
|
||||
private static readonly BindableProperty TuesdayProperty = BindableProperty.Create(nameof(Tuesday), typeof(BillingDay), typeof(BillingDate));
|
||||
private static readonly BindableProperty WednesdayProperty = BindableProperty.Create(nameof(Wednesday), typeof(BillingDay), typeof(BillingDate));
|
||||
private static readonly BindableProperty ThursdayProperty = BindableProperty.Create(nameof(Thursday), typeof(BillingDay), typeof(BillingDate));
|
||||
private static readonly BindableProperty FridayProperty = BindableProperty.Create(nameof(Friday), typeof(BillingDay), typeof(BillingDate));
|
||||
private static readonly BindableProperty SaturdayProperty = BindableProperty.Create(nameof(Saturday), typeof(BillingDay), typeof(BillingDate));
|
||||
|
||||
public BillingDay Sunday => (BillingDay)GetValue(SundayProperty);
|
||||
public BillingDay Monday => (BillingDay)GetValue(MondayProperty);
|
||||
public BillingDay Tuesday => (BillingDay)GetValue(TuesdayProperty);
|
||||
public BillingDay Wednesday => (BillingDay)GetValue(WednesdayProperty);
|
||||
public BillingDay Thursday => (BillingDay)GetValue(ThursdayProperty);
|
||||
public BillingDay Friday => (BillingDay)GetValue(FridayProperty);
|
||||
public BillingDay Saturday => (BillingDay)GetValue(SaturdayProperty);
|
||||
|
||||
#endregion
|
||||
|
||||
private static BindableProperty GetWeekProperty(int week)
|
||||
{
|
||||
return (DayOfWeek)week switch
|
||||
{
|
||||
DayOfWeek.Monday => MondayProperty,
|
||||
DayOfWeek.Tuesday => TuesdayProperty,
|
||||
DayOfWeek.Wednesday => WednesdayProperty,
|
||||
DayOfWeek.Thursday => ThursdayProperty,
|
||||
DayOfWeek.Friday => FridayProperty,
|
||||
DayOfWeek.Saturday => SaturdayProperty,
|
||||
_ => SundayProperty
|
||||
};
|
||||
}
|
||||
|
||||
public static readonly BindableProperty LocatedDateProperty = BindableProperty.Create(nameof(LocatedDate), typeof(DateTime), typeof(BillingDate), propertyChanged: OnLocatedDatePropertyChanged);
|
||||
public static readonly BindableProperty SelectedDateProperty = BindableProperty.Create(nameof(SelectedDate), typeof(DateTime), typeof(BillingDate), propertyChanged: OnSelectedDatePropertyChanged);
|
||||
|
||||
private static void OnLocatedDatePropertyChanged(BindableObject obj, object old, object @new)
|
||||
{
|
||||
if (obj is BillingDate billingDate && @new is DateTime date)
|
||||
{
|
||||
var week = (int)date.DayOfWeek;
|
||||
var tmpDate = date.AddDays(-week);
|
||||
for (var i = 0; i < 7; i++)
|
||||
{
|
||||
var prop = GetWeekProperty(i);
|
||||
var day = new BillingDay(tmpDate);
|
||||
billingDate.SetValue(prop, day);
|
||||
tmpDate = tmpDate.AddDays(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnSelectedDatePropertyChanged(BindableObject obj, object old, object @new)
|
||||
{
|
||||
if (obj is BillingDate billingDate && @new is DateTime selected)
|
||||
{
|
||||
for (var i = 0; i < 7; i++)
|
||||
{
|
||||
var prop = GetWeekProperty(i);
|
||||
var day = (BillingDay)billingDate.GetValue(prop);
|
||||
day.Refresh(selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime LocatedDate
|
||||
{
|
||||
get => (DateTime)GetValue(LocatedDateProperty);
|
||||
set => SetValue(LocatedDateProperty, value);
|
||||
}
|
||||
public DateTime SelectedDate
|
||||
{
|
||||
get => (DateTime)GetValue(SelectedDateProperty);
|
||||
set => SetValue(SelectedDateProperty, value);
|
||||
}
|
||||
|
||||
public Command OnDayTapped { get; }
|
||||
|
||||
public event EventHandler<DateEventArgs> DateSelected;
|
||||
|
||||
private DateTime lastDate;
|
||||
private double? x1;
|
||||
private double x2;
|
||||
|
||||
public BillingDate()
|
||||
{
|
||||
OnDayTapped = new Command(OnDayChanged);
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void SetDateTime(DateTime selectedDate, DateTime? locatedDate = null)
|
||||
{
|
||||
if (locatedDate != null)
|
||||
{
|
||||
LocatedDate = locatedDate.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
LocatedDate = selectedDate;
|
||||
}
|
||||
SelectedDate = selectedDate;
|
||||
DateSelected?.Invoke(this, new DateEventArgs(selectedDate));
|
||||
}
|
||||
|
||||
private void OnDayChanged(object o)
|
||||
{
|
||||
var selected = SelectedDate;
|
||||
if (o is BillingDay day && (selected.Year != day.Date.Year || selected.DayOfYear != day.Date.DayOfYear))
|
||||
{
|
||||
for (var i = 0; i < 7; i++)
|
||||
{
|
||||
var d = (BillingDay)GetValue(GetWeekProperty(i));
|
||||
if (d.IsSelected)
|
||||
{
|
||||
this.AbortAnimation("unselected");
|
||||
this.Animate("unselected", v =>
|
||||
{
|
||||
d.Opacity = v;
|
||||
},
|
||||
start: 1, end: 0,
|
||||
easing: Easing.CubicOut,
|
||||
finished: (v, b) =>
|
||||
{
|
||||
d.Opacity = 0;
|
||||
d.IsSelected = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
SelectedDate = day.Date;
|
||||
this.AbortAnimation("selected");
|
||||
this.Animate("selected", v =>
|
||||
{
|
||||
day.Opacity = v;
|
||||
},
|
||||
start: 0, end: 1,
|
||||
easing: Easing.CubicOut,
|
||||
finished: (v, b) =>
|
||||
{
|
||||
day.Opacity = 1;
|
||||
});
|
||||
DateSelected?.Invoke(this, new DateEventArgs(day.Date));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
|
||||
{
|
||||
if (e.StatusType == GestureStatus.Started)
|
||||
{
|
||||
lastDate = DateTime.Now;
|
||||
x1 = null;
|
||||
}
|
||||
else if (e.StatusType == GestureStatus.Running)
|
||||
{
|
||||
if (x1 == null)
|
||||
{
|
||||
x1 = e.TotalX;
|
||||
}
|
||||
x2 = e.TotalX;
|
||||
}
|
||||
else if (e.StatusType == GestureStatus.Completed)
|
||||
{
|
||||
if (x1 == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var totalX = x2 - x1.Value;
|
||||
x1 = null;
|
||||
var ms = (DateTime.Now - lastDate).TotalMilliseconds;
|
||||
var speed = totalX / ms;
|
||||
Helper.Debug($"completed, speed: {speed}");
|
||||
if (speed < -0.7)
|
||||
{
|
||||
LocatedDate = LocatedDate.AddDays(7);
|
||||
}
|
||||
else if (speed > 0.7)
|
||||
{
|
||||
LocatedDate = LocatedDate.AddDays(-7);
|
||||
}
|
||||
OnSelectedDatePropertyChanged(this, null, SelectedDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DateEventArgs : EventArgs
|
||||
{
|
||||
public DateTime Date { get; }
|
||||
|
||||
public DateEventArgs(DateTime date)
|
||||
{
|
||||
Date = date;
|
||||
}
|
||||
}
|
||||
|
||||
public class BillingDayView : ContentView
|
||||
{
|
||||
public static readonly BindableProperty BillingDayProperty = BindableProperty.Create(nameof(BillingDay), typeof(BillingDay), typeof(BillingDayView));
|
||||
public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(Command), typeof(BillingDayView));
|
||||
|
||||
public BillingDay BillingDay
|
||||
{
|
||||
get => (BillingDay)GetValue(BillingDayProperty);
|
||||
set => SetValue(BillingDayProperty, value);
|
||||
}
|
||||
public Command Command
|
||||
{
|
||||
get => (Command)GetValue(CommandProperty);
|
||||
set => SetValue(CommandProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public class BillingDay : BindableObject
|
||||
{
|
||||
private static readonly BindableProperty DateProperty = BindableProperty.Create(nameof(Date), typeof(DateTime), typeof(BillingDay), propertyChanged: OnDatePropertyChanged);
|
||||
private static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(BillingDay));
|
||||
private static readonly BindableProperty FontFamilyProperty = BindableProperty.Create(nameof(FontFamily), typeof(string), typeof(BillingDay), defaultValue: Definition.GetCascadiaRegularFontFamily());
|
||||
private static readonly BindableProperty IsSelectedProperty = BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(BillingDay));
|
||||
private static readonly BindableProperty OpacityProperty = BindableProperty.Create(nameof(Opacity), typeof(double), typeof(BillingDay), defaultValue: 1.0);
|
||||
private static readonly BindableProperty TextOpacityProperty = BindableProperty.Create(nameof(TextOpacity), typeof(double), typeof(BillingDay), defaultValue: 1.0);
|
||||
|
||||
private static void OnDatePropertyChanged(BindableObject obj, object old, object @new)
|
||||
{
|
||||
if (obj is BillingDay day && @new is DateTime date)
|
||||
{
|
||||
if (date.Day == 1)
|
||||
{
|
||||
day.SetValue(TextProperty, date.ToString("MMM"));
|
||||
}
|
||||
else
|
||||
{
|
||||
day.SetValue(TextProperty, date.Day.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime Date
|
||||
{
|
||||
get => (DateTime)GetValue(DateProperty);
|
||||
set => SetValue(DateProperty, value);
|
||||
}
|
||||
public string Text => (string)GetValue(TextProperty);
|
||||
public string FontFamily => (string)GetValue(FontFamilyProperty);
|
||||
public bool IsSelected
|
||||
{
|
||||
get => (bool)GetValue(IsSelectedProperty);
|
||||
set => SetValue(IsSelectedProperty, value);
|
||||
}
|
||||
public double Opacity
|
||||
{
|
||||
get => (double)GetValue(OpacityProperty);
|
||||
set => SetValue(OpacityProperty, value);
|
||||
}
|
||||
public double TextOpacity => (double)GetValue(TextOpacityProperty);
|
||||
|
||||
public BillingDay(DateTime date)
|
||||
{
|
||||
Date = date;
|
||||
}
|
||||
|
||||
public void Refresh(DateTime selected)
|
||||
{
|
||||
var date = Date;
|
||||
if (date.Year == selected.Year && date.DayOfYear == selected.DayOfYear)
|
||||
{
|
||||
SetValue(IsSelectedProperty, true);
|
||||
SetValue(FontFamilyProperty, Definition.GetCascadiaBoldFontFamily());
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValue(FontFamilyProperty, Definition.GetCascadiaRegularFontFamily());
|
||||
}
|
||||
if (date.Year == selected.Year && date.Month == selected.Month)
|
||||
{
|
||||
SetValue(TextOpacityProperty, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValue(TextOpacityProperty, .4);
|
||||
}
|
||||
}
|
||||
}
|
12
Billing.Shared/UI/BillingPage.cs
Normal file
12
Billing.Shared/UI/BillingPage.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Billing.Themes;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.UI;
|
||||
|
||||
public abstract class BillingPage : ContentPage
|
||||
{
|
||||
public BillingPage()
|
||||
{
|
||||
SetDynamicResource(BackgroundColorProperty, BaseTheme.WindowBackgroundColor);
|
||||
}
|
||||
}
|
23
Billing.Shared/UI/Converters.cs
Normal file
23
Billing.Shared/UI/Converters.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Billing.Languages;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.UI;
|
||||
|
||||
public class TitleDateConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is DateTime date)
|
||||
{
|
||||
return date.ToString(Resource.TitleDateFormat);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
31
Billing.Shared/UI/CustomControl.cs
Normal file
31
Billing.Shared/UI/CustomControl.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.UI;
|
||||
|
||||
public class TintImage : Image
|
||||
{
|
||||
public static readonly BindableProperty PrimaryColorProperty = BindableProperty.Create(nameof(PrimaryColor), typeof(Color?), typeof(TintImage));
|
||||
|
||||
public Color? PrimaryColor
|
||||
{
|
||||
get => (Color?)GetValue(PrimaryColorProperty);
|
||||
set => SetValue(PrimaryColorProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public class LongPressButton : Button
|
||||
{
|
||||
public event EventHandler LongPressed;
|
||||
|
||||
public LongPressButton()
|
||||
{
|
||||
Padding = 0;
|
||||
BackgroundColor = Color.Transparent;
|
||||
}
|
||||
|
||||
public void TriggerLongPress()
|
||||
{
|
||||
LongPressed?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
9
Billing.Shared/UI/Definition.cs
Normal file
9
Billing.Shared/UI/Definition.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Billing.UI;
|
||||
|
||||
public static partial class Definition
|
||||
{
|
||||
public static partial string GetCascadiaRegularFontFamily();
|
||||
public static partial string GetCascadiaBoldFontFamily();
|
||||
public static partial string GetRobotoCondensedRegularFontFamily();
|
||||
public static partial string GetRobotoCondensedBoldFontFamily();
|
||||
}
|
13
Billing.Shared/Views/AccountPage.xaml
Normal file
13
Billing.Shared/Views/AccountPage.xaml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ui:BillingPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:r="clr-namespace:Billing.Languages"
|
||||
xmlns:ui="clr-namespace:Billing.UI"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Billing.Views.AccountPage"
|
||||
Title="{r:Text Accounts}">
|
||||
<StackLayout>
|
||||
<Label Text="Welcome to Account Page!"
|
||||
VerticalOptions="CenterAndExpand"
|
||||
HorizontalOptions="CenterAndExpand" />
|
||||
</StackLayout>
|
||||
</ui:BillingPage>
|
11
Billing.Shared/Views/AccountPage.xaml.cs
Normal file
11
Billing.Shared/Views/AccountPage.xaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Billing.UI;
|
||||
|
||||
namespace Billing.Views;
|
||||
|
||||
public partial class AccountPage : BillingPage
|
||||
{
|
||||
public AccountPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
14
Billing.Shared/Views/AddBillPage.xaml
Normal file
14
Billing.Shared/Views/AddBillPage.xaml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ui:BillingPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:ui="clr-namespace:Billing.UI"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Billing.Views.AddBillPage"
|
||||
x:DataType="v:AddBillPage"
|
||||
Title="Add Billing">
|
||||
|
||||
<StackLayout>
|
||||
<Label Text="Add a billing here..."
|
||||
VerticalOptions="CenterAndExpand"
|
||||
HorizontalOptions="CenterAndExpand" />
|
||||
</StackLayout>
|
||||
</ui:BillingPage>
|
11
Billing.Shared/Views/AddBillPage.xaml.cs
Normal file
11
Billing.Shared/Views/AddBillPage.xaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Billing.UI;
|
||||
|
||||
namespace Billing.Views;
|
||||
|
||||
public partial class AddBillPage : BillingPage
|
||||
{
|
||||
public AddBillPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
56
Billing.Shared/Views/BillPage.xaml
Normal file
56
Billing.Shared/Views/BillPage.xaml
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ui:BillingPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:r="clr-namespace:Billing.Languages"
|
||||
xmlns:ui="clr-namespace:Billing.UI"
|
||||
xmlns:v="clr-namespace:Billing.Views"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Billing.Views.BillPage"
|
||||
x:DataType="v:BillPage"
|
||||
x:Name="billPage"
|
||||
BindingContext="{x:Reference billPage}"
|
||||
Title="{r:Text Bills}">
|
||||
|
||||
<ContentPage.Resources>
|
||||
<ui:TitleDateConverter x:Key="titleDateConverter"/>
|
||||
</ContentPage.Resources>
|
||||
|
||||
<Shell.TitleView>
|
||||
<Grid ColumnSpacing="16" ColumnDefinitions="20,*,20">
|
||||
<ui:TintImage Source="calendar.png" WidthRequest="20" HeightRequest="20" VerticalOptions="Center"/>
|
||||
<ui:LongPressButton Grid.Column="1" Text="{Binding SelectedDate, Converter={StaticResource titleDateConverter}}"
|
||||
TextColor="{DynamicResource PrimaryColor}"
|
||||
HorizontalOptions="{OnPlatform iOS=Center, Android=Start}"
|
||||
FontFamily="{DynamicResource RobotoCondensedFontBold}"
|
||||
FontAttributes="Bold" FontSize="20" VerticalOptions="Center"
|
||||
LongPressed="OnTitleDateLongPressed"/>
|
||||
</Grid>
|
||||
</Shell.TitleView>
|
||||
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<ui:BillingDate x:Name="billingDate" SelectedDate="{Binding SelectedDate}" DateSelected="OnDateSelected"/>
|
||||
<ScrollView Grid.Row="1">
|
||||
<Grid Padding="8" ColumnSpacing="8" ColumnDefinitions="Auto, *, Auto"
|
||||
BackgroundColor="{DynamicResource PromptBackgroundColor}"
|
||||
VerticalOptions="Start">
|
||||
<ui:TintImage Source="bars.png" WidthRequest="23" HeightRequest="23"/>
|
||||
<Label Grid.Column="1" Text="{r:Text NoRecords}" TextColor="{DynamicResource TextColor}"
|
||||
VerticalOptions="Center"/>
|
||||
<StackLayout Grid.Column="2" Orientation="Horizontal" Spacing="6">
|
||||
<StackLayout.GestureRecognizers>
|
||||
<TapGestureRecognizer Command="{Binding AddBilling}"/>
|
||||
</StackLayout.GestureRecognizers>
|
||||
<Label Text="{r:Text Memo}" TextColor="{DynamicResource PrimaryColor}"
|
||||
VerticalOptions="Center"/>
|
||||
<!--<Label Style="{DynamicResource IconLightStyle}"
|
||||
Text="{x:Static local:Definition.IconRight}"
|
||||
TextColor="{DynamicResource TabBarUnselectedColor}"/>-->
|
||||
<ui:TintImage Source="right.png" WidthRequest="24" HeightRequest="24"/>
|
||||
</StackLayout>
|
||||
</Grid>
|
||||
</ScrollView>
|
||||
<!--<ui:CircleButton Grid.Row="1" VerticalOptions="End" HorizontalOptions="End"
|
||||
Margin="20" Padding="0"
|
||||
BackgroundColor="{DynamicResource PrimaryColor}"
|
||||
ImageSource="plus.png" HeightRequest="24" WidthRequest="24"/>-->
|
||||
</Grid>
|
||||
</ui:BillingPage>
|
44
Billing.Shared/Views/BillPage.xaml.cs
Normal file
44
Billing.Shared/Views/BillPage.xaml.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using Billing.UI;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.Views;
|
||||
|
||||
public partial class BillPage : BillingPage
|
||||
{
|
||||
private static readonly BindableProperty SelectedDateProperty = BindableProperty.Create(nameof(SelectedDate), typeof(DateTime), typeof(BillPage));
|
||||
|
||||
public DateTime SelectedDate
|
||||
{
|
||||
get => (DateTime)GetValue(SelectedDateProperty);
|
||||
set => SetValue(SelectedDateProperty, value);
|
||||
}
|
||||
|
||||
public Command AddBilling { get; }
|
||||
|
||||
public BillPage()
|
||||
{
|
||||
AddBilling = new Command(OnAddBilling);
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
billingDate.SetDateTime(DateTime.Now);
|
||||
}
|
||||
|
||||
private void OnDateSelected(object sender, DateEventArgs e)
|
||||
{
|
||||
SelectedDate = e.Date;
|
||||
|
||||
// TODO: while selecting date
|
||||
}
|
||||
|
||||
private void OnTitleDateLongPressed(object sender, EventArgs e)
|
||||
{
|
||||
billingDate.SetDateTime(DateTime.Now);
|
||||
}
|
||||
|
||||
private async void OnAddBilling()
|
||||
{
|
||||
await Navigation.PushAsync(new AddBillPage());
|
||||
}
|
||||
}
|
13
Billing.Shared/Views/SettingPage.xaml
Normal file
13
Billing.Shared/Views/SettingPage.xaml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ui:BillingPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:r="clr-namespace:Billing.Languages"
|
||||
xmlns:ui="clr-namespace:Billing.UI"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Billing.Views.SettingPage"
|
||||
Title="{r:Text Settings}">
|
||||
<StackLayout>
|
||||
<Label Text="Welcome to Settings Page!"
|
||||
VerticalOptions="CenterAndExpand"
|
||||
HorizontalOptions="CenterAndExpand" />
|
||||
</StackLayout>
|
||||
</ui:BillingPage>
|
11
Billing.Shared/Views/SettingPage.xaml.cs
Normal file
11
Billing.Shared/Views/SettingPage.xaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Billing.UI;
|
||||
|
||||
namespace Billing.Views;
|
||||
|
||||
public partial class SettingPage : BillingPage
|
||||
{
|
||||
public SettingPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user