292 lines
10 KiB
C#
292 lines
10 KiB
C#
using System;
|
|
using Xamarin.Forms;
|
|
|
|
namespace Billing.UI
|
|
{
|
|
public partial class BillingDate : ContentView
|
|
{
|
|
#region UI Properties
|
|
|
|
public static readonly BindableProperty SundayProperty = Helper.Create<BillingDay, BillingDate>(nameof(Sunday));
|
|
public static readonly BindableProperty MondayProperty = Helper.Create<BillingDay, BillingDate>(nameof(Monday));
|
|
public static readonly BindableProperty TuesdayProperty = Helper.Create<BillingDay, BillingDate>(nameof(Tuesday));
|
|
public static readonly BindableProperty WednesdayProperty = Helper.Create<BillingDay, BillingDate>(nameof(Wednesday));
|
|
public static readonly BindableProperty ThursdayProperty = Helper.Create<BillingDay, BillingDate>(nameof(Thursday));
|
|
public static readonly BindableProperty FridayProperty = Helper.Create<BillingDay, BillingDate>(nameof(Friday));
|
|
public static readonly BindableProperty SaturdayProperty = Helper.Create<BillingDay, BillingDate>(nameof(Saturday));
|
|
|
|
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 = Helper.Create<DateTime, BillingDate>(nameof(LocatedDate), propertyChanged: OnLocatedDatePropertyChanged);
|
|
public static readonly BindableProperty SelectedDateProperty = Helper.Create<DateTime, BillingDate>(nameof(SelectedDate), propertyChanged: OnSelectedDatePropertyChanged);
|
|
|
|
private static void OnLocatedDatePropertyChanged(BillingDate billingDate, DateTime old, DateTime date)
|
|
{
|
|
var week = (int)date.DayOfWeek;
|
|
var tmpDate = date.AddDays(-week);
|
|
for (var i = 0; i < 7; i++)
|
|
{
|
|
var day = new BillingDay(tmpDate);
|
|
billingDate[i] = day;
|
|
tmpDate = tmpDate.AddDays(1);
|
|
}
|
|
}
|
|
|
|
private static void OnSelectedDatePropertyChanged(BillingDate billingDate, DateTime old, DateTime selected)
|
|
{
|
|
for (var i = 0; i < 7; i++)
|
|
{
|
|
var day = billingDate[i];
|
|
day.Refresh(selected);
|
|
}
|
|
}
|
|
|
|
public BillingDay this[int index]
|
|
{
|
|
get => (BillingDay)GetValue(GetWeekProperty(index));
|
|
set => SetValue(GetWeekProperty(index), value);
|
|
}
|
|
|
|
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 (Helper.IsSameDay(selectedDate, SelectedDate))
|
|
{
|
|
return;
|
|
}
|
|
DateTime located;
|
|
if (locatedDate != null)
|
|
{
|
|
located = Helper.FirstDay(locatedDate.Value);
|
|
}
|
|
else
|
|
{
|
|
located = Helper.FirstDay(selectedDate);
|
|
}
|
|
if (LocatedDate != located)
|
|
{
|
|
LocatedDate = located;
|
|
}
|
|
else
|
|
{
|
|
RestoreState(this[(int)selectedDate.DayOfWeek]);
|
|
}
|
|
SelectedDate = selectedDate;
|
|
DateSelected?.Invoke(this, new DateEventArgs(selectedDate));
|
|
}
|
|
|
|
private void OnDayChanged(object o)
|
|
{
|
|
var selected = SelectedDate;
|
|
if (o is BillingDay day && !Helper.IsSameDay(selected, day.Date))
|
|
{
|
|
RestoreState(day);
|
|
SelectedDate = day.Date;
|
|
DateSelected?.Invoke(this, new DateEventArgs(day.Date));
|
|
}
|
|
}
|
|
|
|
private void RestoreState(BillingDay day)
|
|
{
|
|
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;
|
|
});
|
|
}
|
|
}
|
|
this.AbortAnimation("selected");
|
|
this.Animate("selected", v =>
|
|
{
|
|
day.Opacity = v;
|
|
},
|
|
start: 0, end: 1,
|
|
easing: Easing.CubicOut,
|
|
finished: (v, b) =>
|
|
{
|
|
day.Opacity = 1;
|
|
});
|
|
}
|
|
|
|
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;
|
|
if (speed < -0.7)
|
|
{
|
|
LocatedDate = LocatedDate.AddDays(7);
|
|
}
|
|
else if (speed > 0.7)
|
|
{
|
|
LocatedDate = LocatedDate.AddDays(-7);
|
|
}
|
|
OnSelectedDatePropertyChanged(this, default, SelectedDate);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class DateEventArgs : EventArgs
|
|
{
|
|
public DateTime Date { get; }
|
|
|
|
public DateEventArgs(DateTime date)
|
|
{
|
|
Date = date;
|
|
}
|
|
}
|
|
|
|
public class BillingDayView : ContentView
|
|
{
|
|
public static readonly BindableProperty BillingDayProperty = Helper.Create<BillingDay, BillingDayView>(nameof(BillingDay));
|
|
|
|
public BillingDay BillingDay
|
|
{
|
|
get => (BillingDay)GetValue(BillingDayProperty);
|
|
set => SetValue(BillingDayProperty, value);
|
|
}
|
|
}
|
|
|
|
public class BillingDay : BindableObject
|
|
{
|
|
public static readonly BindableProperty DateProperty = Helper.Create<DateTime, BillingDay>(nameof(Date), propertyChanged: OnDatePropertyChanged);
|
|
public static readonly BindableProperty TextProperty = Helper.Create<string, BillingDay>(nameof(Text));
|
|
public static readonly BindableProperty FontFamilyProperty = Helper.Create<string, BillingDay>(nameof(FontFamily), defaultValue: Definition.RegularFontFamily);
|
|
public static readonly BindableProperty IsSelectedProperty = Helper.Create<bool, BillingDay>(nameof(IsSelected), defaultValue: false);
|
|
public static readonly BindableProperty OpacityProperty = Helper.Create<double, BillingDay>(nameof(Opacity), defaultValue: 1.0);
|
|
public static readonly BindableProperty TextOpacityProperty = Helper.Create<double, BillingDay>(nameof(TextOpacity), defaultValue: 1.0);
|
|
|
|
private static void OnDatePropertyChanged(BillingDay day, DateTime old, DateTime date)
|
|
{
|
|
if (date.Day == 1)
|
|
{
|
|
day.SetValue(TextProperty, date.ToString("MMM"));
|
|
}
|
|
else
|
|
{
|
|
day.SetValue(TextProperty, date.Day.ToString());
|
|
}
|
|
}
|
|
|
|
public DateTime Date => (DateTime)GetValue(DateProperty);
|
|
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)
|
|
{
|
|
SetValue(DateProperty, date);
|
|
}
|
|
|
|
public void Refresh(DateTime selected)
|
|
{
|
|
var date = Date;
|
|
if (Helper.IsSameDay(date, selected))
|
|
{
|
|
IsSelected = true;
|
|
SetValue(FontFamilyProperty, Definition.BoldFontFamily);
|
|
}
|
|
else
|
|
{
|
|
SetValue(FontFamilyProperty, Definition.RegularFontFamily);
|
|
}
|
|
if (date.Year == selected.Year && date.Month == selected.Month)
|
|
{
|
|
SetValue(TextOpacityProperty, 1.0);
|
|
}
|
|
else
|
|
{
|
|
SetValue(TextOpacityProperty, .4);
|
|
}
|
|
}
|
|
}
|
|
} |