Bläddra i källkod

PRS MOBILE - enhancements to Assignments (mainly the edit screen)

Nick-PRSDigital@bitbucket.org 2 år sedan
förälder
incheckning
31c16df19b

+ 66 - 17
prs.mobile/comal.timesheets/Assignments/AssignmentDetails.xaml

@@ -8,7 +8,7 @@
         <Grid Margin="5">
         
             <Grid.ColumnDefinitions>
-                <ColumnDefinition Width="Auto" />
+                <ColumnDefinition Width="60" />
                 <ColumnDefinition Width="*"/>
             </Grid.ColumnDefinitions>
             
@@ -19,32 +19,81 @@
                 <RowDefinition Height="Auto"/>
                 <RowDefinition Height="Auto"/>
                 <RowDefinition Height="Auto"/>
+                <RowDefinition Height="Auto"/>
                 <RowDefinition Height="*"/>
                 <RowDefinition Height="Auto"/>
             </Grid.RowDefinitions>
             
             <Label Grid.Row="0" Grid.Column="0" Text="Subject" VerticalOptions="Fill" VerticalTextAlignment="Center"/>
             <Entry Grid.Row="0" Grid.Column="1" x:Name="Subject" Text="{Binding Item.Subject}" TextChanged="Subject_OnTextChanged"/>
-        
-            <Label Grid.Row="1" Grid.Column="0" Text="From" VerticalOptions="Fill" VerticalTextAlignment="Center"/>
-            <TimePicker Grid.Row="1" Grid.Column="1" x:Name="Start" Time="{Binding Item.Start}" Unfocused="Start_OnUnfocused"/>
-            
-            <Label Grid.Row="2" Grid.Column="0" Text="To" VerticalOptions="Fill" VerticalTextAlignment="Center"/>
-            <TimePicker Grid.Row="2" Grid.Column="1" x:Name="Finish" Time="{Binding Item.Finish}" Unfocused="Finish_OnUnfocused" />
-            
-            <Label Grid.Row="3" Grid.Column="0" Text="Job" VerticalOptions="Fill" VerticalTextAlignment="Center"/>
-            <ui:MaterialButton Grid.Row="3" Grid.Column="1" x:Name="Job" Text="{Binding Item.JobDisplay}" Clicked="Job_Clicked" Margin="-5"/>
+
+            <Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" RowSpacing="0" ColumnSpacing="0">
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="60"/>
+                    <ColumnDefinition Width="*"/>
+                    <ColumnDefinition Width="1.7*"/>
+                </Grid.ColumnDefinitions>
+
+                <Grid Grid.Row="0" Grid.Column="0" RowSpacing="0" ColumnSpacing="0">
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="40"/>
+                        <RowDefinition Height="40"/>
+                        <RowDefinition Height="40"/>
+                    </Grid.RowDefinitions>
+                    <Label Grid.Row="1" Text="From" VerticalOptions="Center" VerticalTextAlignment="Center"/>
+                    <Label Grid.Row="2"  Text="To" VerticalOptions="Center" VerticalTextAlignment="Center"/>
+                </Grid>
+
+                <Frame Grid.Row="0" Grid.Column="1" Margin="3,1,1.5,1" Padding="3">
+                    <Grid RowSpacing="0" ColumnSpacing="0">
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="40"/>
+                            <RowDefinition Height="40"/>
+                            <RowDefinition Height="40"/>
+                        </Grid.RowDefinitions>
+                        <Label Grid.Row="0" Margin="5, 0, 0, 0"
+                               Text="Booked" VerticalTextAlignment="Center" FontAttributes="Bold" FontSize="Medium" HorizontalOptions="Start" HorizontalTextAlignment="Center"/>
+                        <TimePicker Grid.Row="1" x:Name="BookedStart" Time="{Binding Item.BookedStart}" Unfocused="BookedStart_OnUnfocused"/>
+                        <TimePicker Grid.Row="2" x:Name="BookedFinish" Time="{Binding Item.BookedFinish}" Unfocused="BookedFinish_OnUnfocused"/>
+                    </Grid>
+                </Frame>
+
+                <Frame Grid.Row="0" Grid.Column="2" Margin="1.5,1,3,1" Padding="3">
+                    <Grid RowSpacing="0" ColumnSpacing="0">
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="40"/>
+                            <RowDefinition Height="40"/>
+                            <RowDefinition Height="40"/>
+                        </Grid.RowDefinitions>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="auto"/>
+                        </Grid.ColumnDefinitions>
+                        <Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="5, 0, 0, 0"
+                               Text="Actual" VerticalTextAlignment="Center" FontAttributes="Bold" FontSize="Medium" HorizontalOptions="Start" HorizontalTextAlignment="Center"/>
+                        <ui:MaterialButton Grid.Row="0" Grid.Column="1" Text="As Booked" x:Name="AsBookedBtn" Clicked="AsBookedBtn_Clicked" Padding="7, 0, 7, 0"/>
+                        
+                        <TimePicker Grid.Row="1" Grid.Column="0" x:Name="ActualStart" Time="{Binding Item.ActualStart}" Unfocused="ActualStart_OnUnfocused"/>
+                        <TimePicker Grid.Row="2" Grid.Column="0" x:Name="ActualFinish" Time="{Binding Item.ActualFinish}" Unfocused="ActualFinish_OnUnfocused"/>
+                        <ui:MaterialButton Grid.Row="1" Grid.Column="1" Text="Now" x:Name="ActualStartNowBtn" Clicked="ActualStartNowBtn_Clicked"/>
+                        <ui:MaterialButton Grid.Row="2" Grid.Column="1" Text="Now" x:Name="ActualFinishNowBtn" Clicked="ActualFinishNowBtn_Clicked" Padding="1"/>
+                    </Grid>
+                </Frame>
+            </Grid>
+
+            <Label Grid.Row="4" Grid.Column="0" Text="Job" VerticalOptions="Fill" VerticalTextAlignment="Center"/>
+            <ui:MaterialButton Grid.Row="4" Grid.Column="1" x:Name="Job" Text="{Binding Item.JobDisplay}" Clicked="Job_Clicked" Margin="-5"/>
             
-            <Label Grid.Row="4" Grid.Column="0" Text="Task" VerticalOptions="Fill" VerticalTextAlignment="Center"/>
-            <ui:MaterialButton Grid.Row="4" Grid.Column="1" x:Name="Task" Text="{Binding Item.TaskDisplay}" Clicked="Task_Clicked" Margin="-5"/>
+            <Label Grid.Row="5" Grid.Column="0" Text="Task" VerticalOptions="Fill" VerticalTextAlignment="Center"/>
+            <ui:MaterialButton Grid.Row="5" Grid.Column="1" x:Name="Task" Text="{Binding Item.TaskDisplay}" Clicked="Task_Clicked" Margin="-5"/>
 
-            <Label Grid.Row="5" Grid.Column="0" Text="Activity" VerticalOptions="Fill" VerticalTextAlignment="Center"/>
-            <ui:MaterialButton Grid.Row="5" Grid.Column="1" x:Name="Activity" Text="{Binding Item.ActivityDisplay}" Clicked="Activity_Clicked" Margin="-5"/>  
+            <Label Grid.Row="6" Grid.Column="0" Text="Activity" VerticalOptions="Fill" VerticalTextAlignment="Center"/>
+            <ui:MaterialButton Grid.Row="6" Grid.Column="1" x:Name="Activity" Text="{Binding Item.ActivityDisplay}" Clicked="Activity_Clicked" Margin="-5"/>  
 
-            <Label Grid.Row="6" Grid.Column="0" Text="Notes"/>
-            <Editor Grid.Row="6" Grid.Column="1" x:Name="Description" Text="{Binding Item.Description}" TextChanged="Description_OnTextChanged"/>
+            <Label Grid.Row="7" Grid.Column="0" Text="Notes"/>
+            <Editor Grid.Row="7" Grid.Column="1" x:Name="Description" Text="{Binding Item.Description}" TextChanged="Description_OnTextChanged"/>
             
-            <ui:MaterialButton Grid.Row="7" Grid.Column="1" x:Name="Completed" Text="Complete" Clicked="Complete_Clicked" Margin="-5"/>  
+            <ui:MaterialButton Grid.Row="8" Grid.Column="0" Grid.ColumnSpan="2" x:Name="Completed" Text="Complete" Clicked="Complete_Clicked" Margin="-5"/>  
         </Grid>
     </ScrollView>
 

+ 43 - 8
prs.mobile/comal.timesheets/Assignments/AssignmentDetails.xaml.cs

@@ -48,8 +48,12 @@ namespace comal.timesheets
                 : InABox.Core.Security.CanEdit<Assignment>() ? "Re-Open" : $"Completed {DataModel.Item.Completed:dd/MM/yy}";
             
             Subject.IsEnabled = open && InABox.Core.Security.CanEdit<Assignment>();
-            Start.IsEnabled = open && InABox.Core.Security.CanEdit<Assignment>();
-            Finish.IsEnabled = open && InABox.Core.Security.CanEdit<Assignment>();
+            ActualStart.IsEnabled = open && InABox.Core.Security.CanEdit<Assignment>();
+            ActualFinish.IsEnabled = open && InABox.Core.Security.CanEdit<Assignment>();
+            BookedStart.IsEnabled = open && InABox.Core.Security.CanEdit<Assignment>();
+            BookedFinish.IsEnabled = open && InABox.Core.Security.CanEdit<Assignment>();
+            ActualStartNowBtn.IsEnabled = open && InABox.Core.Security.CanEdit<Assignment>();
+            ActualFinishNowBtn.IsEnabled = open && InABox.Core.Security.CanEdit<Assignment>();
             Job.IsEnabled = open && InABox.Core.Security.CanEdit<Assignment>();
             Task.IsEnabled = open && InABox.Core.Security.CanEdit<Assignment>();
             Activity.IsEnabled = open && InABox.Core.Security.CanEdit<Assignment>();
@@ -186,18 +190,49 @@ namespace comal.timesheets
                 Navigation.PopAsync();
             }
         }
-        
-        
-        private void Start_OnUnfocused(object sender, FocusEventArgs e)
+
+        private void ActualStartNowBtn_Clicked(object sender, EventArgs e)
+        {
+            ActualStart.Time = DateTime.Now.TimeOfDay;
+            OnDetailsChanged?.Invoke(this, new AssignmentDetailsChangedArgs("ActualStart"));
+        }
+
+        private void ActualFinishNowBtn_Clicked(object sender, EventArgs e)
+        {
+            ActualFinish.Time = DateTime.Now.TimeOfDay;
+            OnDetailsChanged?.Invoke(this, new AssignmentDetailsChangedArgs("ActualFinish"));
+        }
+
+        private void AsBookedBtn_Clicked(object sender, EventArgs e)
+        {
+            ActualStart.Time = BookedStart.Time;
+            ActualFinish.Time = BookedFinish.Time;
+            OnDetailsChanged?.Invoke(this, new AssignmentDetailsChangedArgs("ActualStart"));
+            OnDetailsChanged?.Invoke(this, new AssignmentDetailsChangedArgs("ActualFinish"));
+        }
+
+
+        private void BookedStart_OnUnfocused(object sender, FocusEventArgs e)
+        {
+            OnDetailsChanged?.Invoke(this,new AssignmentDetailsChangedArgs("BookedStart"));
+        }
+
+        private void BookedFinish_OnUnfocused(object sender, FocusEventArgs e)
         {
-            OnDetailsChanged?.Invoke(this,new AssignmentDetailsChangedArgs("Start"));
+            OnDetailsChanged?.Invoke(this, new AssignmentDetailsChangedArgs("BookedFinish"));
         }
 
-        private void Finish_OnUnfocused(object sender, FocusEventArgs e)
+        private void ActualStart_OnUnfocused(object sender, FocusEventArgs e)
         {
-            OnDetailsChanged?.Invoke(this,new AssignmentDetailsChangedArgs("Finish"));
+            OnDetailsChanged?.Invoke(this, new AssignmentDetailsChangedArgs("ActualStart"));
         }
 
+        private void ActualFinish_OnUnfocused(object sender, FocusEventArgs e)
+        {
+            OnDetailsChanged?.Invoke(this, new AssignmentDetailsChangedArgs("ActualFinish"));
+        }
+
+
         private void Description_OnTextChanged(object sender, TextChangedEventArgs e)
         {
             if (Description.IsFocused)

+ 1 - 1
prs.mobile/comal.timesheets/Assignments/AssignmentList.xaml

@@ -155,7 +155,7 @@
                 ScheduleView="DayView" 
                 HeaderHeight="0"
                 ViewHeaderHeight="0"
-                TimeInterval="60"
+                TimeInterval="30"
                 Background="White"
                 EnableNavigation="False"
                 VerticalOptions="Fill"

+ 56 - 46
prs.mobile/comal.timesheets/Assignments/AssignmentList.xaml.cs

@@ -30,14 +30,14 @@ namespace comal.timesheets
         UnbookedJobs,
         Tasks
     }
-    
+
     public partial class AssignmentList : ContentPage
     {
 
         private AssignmentEdit _editor = null;
 
         private Guid[] _employeeids = new Guid[] { };
-        
+
         private AssignmentModuleSettings _settings = null;
 
         private AssignmentView _view = AssignmentView.Day;
@@ -56,11 +56,11 @@ namespace comal.timesheets
 
             _jobs = new AssignmentJobDataModel();
             _kanbans = new AssignmentKanbanDataModel();
-            
+
             DatePicker.Date = _settings.Date.IsEmpty() ? DateTime.Today : _settings.Date;
-            
+
             _view = _settings.View;
-            
+
             _employeeids = (_settings.Employees != null)
                 ? _settings.Employees
                 : new Guid[] { App.Data.Employee.ID };
@@ -71,20 +71,20 @@ namespace comal.timesheets
             _teamname = _settings.TeamName;
 
         }
-        
+
         protected override void OnAppearing()
         {
             base.OnAppearing();
             RefreshLookups();
             Reload();
         }
-        
+
         private void RefreshLookups()
         {
             if (_lookuptype == AssignmentLookupType.Tasks)
             {
                 _kanbans.Load(
-                    new Filter<Kanban>(x=>x.Completed).IsEqualTo(DateTime.MinValue),
+                    new Filter<Kanban>(x => x.Completed).IsEqualTo(DateTime.MinValue),
                     () => Dispatcher.BeginInvokeOnMainThread(() =>
                     {
                         Lookups.ItemsSource = new ObservableCollection<AssignmentKanbanItem>(_kanbans.Items);
@@ -93,32 +93,32 @@ namespace comal.timesheets
             else if (_lookuptype == AssignmentLookupType.ActiveJobs)
             {
                 _jobs.Load(
-                    new Filter<Job>(x=>x.JobStatus.Active).IsEqualTo(true),
+                    new Filter<Job>(x => x.JobStatus.Active).IsEqualTo(true),
                     () => Dispatcher.BeginInvokeOnMainThread(() =>
                     {
                         Lookups.ItemsSource = new ObservableCollection<AssignmentJobItem>(_jobs.Items);
-                    }));               
+                    }));
             }
             else if (_lookuptype == AssignmentLookupType.UnbookedJobs)
             {
                 _jobs.Load(
-                    new Filter<Job>(x=>x.JobStatus.Active).IsEqualTo(true)
-                        .And(x=>x.OpenAssignments).IsEqualTo(0),
+                    new Filter<Job>(x => x.JobStatus.Active).IsEqualTo(true)
+                        .And(x => x.OpenAssignments).IsEqualTo(0),
                     () => Dispatcher.BeginInvokeOnMainThread(() =>
                     {
                         Lookups.ItemsSource = new ObservableCollection<AssignmentJobItem>(_jobs.Items);
-                    }));                 
-            }            
+                    }));
+            }
         }
-        
+
         private void Reload()
         {
 
-            DayView.DataSource = null;         
-            TimeLineView.DataSource = null;    
-            
+            DayView.DataSource = null;
+            TimeLineView.DataSource = null;
+
             ScheduleType.Text = _teamname;
-            
+
             if (_view == AssignmentView.Day)
             {
                 DayViewColumn.Width = new GridLength(1, GridUnitType.Star);
@@ -130,10 +130,10 @@ namespace comal.timesheets
                 DayViewColumn.Width = new GridLength(0, GridUnitType.Absolute);
                 TimeLineViewColumn.Width = new GridLength(1, GridUnitType.Star);
 
-                TimeLineView.ResourceViewSettings.VisibleResourceCount = Math.Max(1,Math.Min(16, _employeeids.Length));
+                TimeLineView.ResourceViewSettings.VisibleResourceCount = Math.Max(1, Math.Min(16, _employeeids.Length));
                 TimeLineView.TimelineViewSettings.AppointmentHeight =
                     (this.Height / TimeLineView.ResourceViewSettings.VisibleResourceCount) + 100;
-                
+
                 var resources = new ObservableCollection<object>();
                 foreach (var empid in _employeeids)
                 {
@@ -158,33 +158,43 @@ namespace comal.timesheets
                 }
                 TimeLineView.ScheduleResources = resources;
                 TimeLineView.ShowResourceView = true;
-                
+
 
 
             }
             Refresh();
         }
-        
+
         private void Refresh()
         {
             Title.Text = $"{DatePicker.Date:dd MMMM yyyy}";
-            
+
             DataModel.Load(
                 new Filter<Assignment>(x => x.Date).IsEqualTo(DatePicker.Date).And(x => x.EmployeeLink.ID).InList(_employeeids),
                 () =>
                 {
-                    Dispatcher.BeginInvokeOnMainThread(() =>{
+                    Dispatcher.BeginInvokeOnMainThread(() =>
+                    {
                         if (_view == AssignmentView.Day)
+                        {
                             DayView.DataSource = new ObservableCollection<AssignmentListDataModelItem>(DataModel.Items);
+                            DayView.MoveToDate = ShowRelevantTime();
+                        }
                         else
+                        {
                             TimeLineView.DataSource = new ObservableCollection<AssignmentListDataModelItem>(DataModel.Items);
+                            TimeLineView.MoveToDate = ShowRelevantTime();
+                        }
                     });
-
                 }
             );
+        }
+
+        private DateTime ShowRelevantTime()
+        {
+            return (DataModel.Items.Count > 0 ? (DataModel.Items.First() as AssignmentListDataModelItem).StartTime : DateTime.Now).AddMinutes(-30);
+        }
 
-       }
-        
         private void SelectedDate_Tapped(object sender, EventArgs e)
         {
             DatePicker.Focus();
@@ -199,7 +209,7 @@ namespace comal.timesheets
             }
             DayView.MoveToDate = DatePicker.Date;
             TimeLineView.MoveToDate = DatePicker.Date;
-            Dispatcher.BeginInvokeOnMainThread(()=>
+            Dispatcher.BeginInvokeOnMainThread(() =>
             {
                 Refresh();
             });
@@ -210,9 +220,9 @@ namespace comal.timesheets
 
             var actions = new List<string>() { "Only Me" };
             //actions.AddRange(GlobalVariables.TeamEmployeeShells.Where(x=>x.ID == App.Data.Employee.ID).Select(x=>x.TeamName).Distinct());
-            actions.AddRange(GlobalVariables.TeamEmployeeShells.Select(x=>x.TeamName).Distinct());
+            actions.AddRange(GlobalVariables.TeamEmployeeShells.Select(x => x.TeamName).Distinct());
 
-            var result = await MaterialDialog.Instance.SelectActionAsync(title: "Select a Team", 
+            var result = await MaterialDialog.Instance.SelectActionAsync(title: "Select a Team",
                 actions: actions);
 
             if (result == 0)
@@ -233,13 +243,13 @@ namespace comal.timesheets
             _settings.View = _view;
             _settings.TeamName = _teamname;
             new LocalConfiguration<AssignmentModuleSettings>().Save(_settings);
-            
-            Dispatcher.BeginInvokeOnMainThread(()=>
+
+            Dispatcher.BeginInvokeOnMainThread(() =>
             {
                 Reload();
             });
         }
-        
+
         private void Lookups_OnItemTapped(object sender, ItemTappedEventArgs e)
         {
             if (e.Item is AssignmentLookupItem lookup)
@@ -269,10 +279,10 @@ namespace comal.timesheets
                     : AssignmentLookupType.Tasks;
             _settings.LookupType = _lookuptype;
             LookupType.Text = CoreUtils.Neatify(_lookuptype.ToString());
-            new LocalConfiguration<AssignmentModuleSettings>().Save(_settings);  
+            new LocalConfiguration<AssignmentModuleSettings>().Save(_settings);
             RefreshLookups();
         }
-        
+
         private async void Schedule_OnCellTapped(object sender, CellTappedEventArgs e)
         {
             if (e.Appointment is AssignmentListDataModelItem item)
@@ -281,7 +291,7 @@ namespace comal.timesheets
                 Navigation.PushAsync(editor);
             }
         }
-        
+
         private async void Schedule_OnCellLongPressed(object sender, CellTappedEventArgs e)
         {
             if (e.Appointment == null)
@@ -295,7 +305,7 @@ namespace comal.timesheets
                     );
                 }
             }
-            else if (InABox.Core.Security.CanDelete<Assignment>() 
+            else if (InABox.Core.Security.CanDelete<Assignment>()
                      && e.Appointment is AssignmentListDataModelItem assignment)
             {
                 await DeleteAssignment(assignment.Id);
@@ -303,7 +313,7 @@ namespace comal.timesheets
         }
 
         private void CreateAssignment(DateTime date, ScheduleResource resource)
-        {           
+        {
             var assignment = new Assignment()
             {
                 Date = date.Date,
@@ -316,7 +326,7 @@ namespace comal.timesheets
             assignment.EmployeeLink.ID = (resource is ScheduleResource sr)
                 ? (Guid)sr.Id
                 : App.Data.Employee.ID;
-            
+
             var job = (_lookuptype == AssignmentLookupType.ActiveJobs) || (_lookuptype == AssignmentLookupType.UnbookedJobs)
                 ? _jobs.Items.FirstOrDefault(x => x.Selected)
                 : null;
@@ -329,10 +339,10 @@ namespace comal.timesheets
                 assignment.Title = job.Name;
                 job.Selected = false;
             }
-            
+
             var task = _lookuptype == AssignmentLookupType.Tasks
                 ? _kanbans.Items.FirstOrDefault(x => x.Selected)
-                : null;  
+                : null;
             if (task != null)
             {
                 assignment.Task.ID = task.Id;
@@ -341,12 +351,12 @@ namespace comal.timesheets
                 assignment.Title = task.Name;
                 assignment.Description = task.Description;
                 task.Selected = false;
-            }            
-            
+            }
+
             var editor = new AssignmentEdit(assignment);
-            Navigation.PushAsync(editor);            
+            Navigation.PushAsync(editor);
         }
-        
+
         private async Task DeleteAssignment(Guid id)
         {
             var confirm = await MaterialDialog.Instance.ConfirmAsync(

+ 25 - 25
prs.mobile/comal.timesheets/Assignments/DataModels/AssignmentEditDataModel.cs

@@ -191,42 +191,42 @@ namespace comal.timesheets
             set => UpdateValue(c => c.Date, value);
         }
 
-        public TimeSpan Start
+        public TimeSpan ActualStart
         {
-            get 
-            {
-                var start = GetValue(c => c.Actual.Start);
-                if (start == TimeSpan.Zero)
-                    start = GetValue(c => c.Booked.Start);
-                return start;
-            }
+            get  => GetValue(c => c.Actual.Start);                
             set => UpdateValue(c => c.Actual.Start, value);
         }
 
-        public TimeSpan Duration
+        public TimeSpan ActualDuration
         {
-            get
-            {
-                var duration = GetValue(c => c.Actual.Duration);
-                if (duration == TimeSpan.Zero)
-                    duration = GetValue(c => c.Booked.Duration);
-                return duration;
-            }
+            get => GetValue(c => c.Actual.Duration);                
             set => UpdateValue(c => c.Actual.Duration, value);
         }
         
-        public TimeSpan Finish 
+        public TimeSpan ActualFinish 
         {
-            get
-            {
-                var finish = GetValue(c => c.Actual.Finish);
-                if (finish == TimeSpan.Zero)
-                    finish = GetValue(c => c.Booked.Finish);
-                return finish;
-            }
+            get => GetValue(c => c.Actual.Finish);
             set => UpdateValue(c => c.Actual.Finish, value);
         }
-        
+
+        public TimeSpan BookedStart
+        {
+            get => GetValue(c => c.Booked.Start);
+            set => UpdateValue(c => c.Booked.Start, value);
+        }
+
+        public TimeSpan BookedDuration
+        {
+            get => GetValue(c => c.Booked.Duration);
+            set => UpdateValue(c => c.Booked.Duration, value);
+        }
+
+        public TimeSpan BookedFinish
+        {
+            get => GetValue(c => c.Booked.Finish);
+            set => UpdateValue(c => c.Booked.Finish, value);
+        }
+
         public Guid JobID 
         {
             get => GetValue(c => c.JobLink.ID);

+ 6 - 27
prs.mobile/comal.timesheets/Assignments/DataModels/AssignmentListDataModel.cs

@@ -8,8 +8,6 @@ using Xamarin.Forms;
 
 namespace comal.timesheets
 {
-
-
     public class AssignmentListDataModel : ListDataModel<Assignment, AssignmentListDataModelItem>
     {
         public override Columns<Assignment> Columns => new Columns<Assignment>(x => x.ID)
@@ -19,8 +17,10 @@ namespace comal.timesheets
             .Add(x => x.Date)
             .Add(x => x.Actual.Start)
             .Add(x => x.Actual.Finish)
+            .Add(x => x.Actual.Duration)
             .Add(x => x.Booked.Start)
             .Add(x => x.Booked.Finish)
+            .Add(x => x.Booked.Duration)
             .Add(x => x.ActivityLink.Color)
             .Add(x => x.EmployeeLink.ID)
             .Add(x => x.JobLink.ID)
@@ -58,31 +58,10 @@ namespace comal.timesheets
 
         public string Notes => Row.Get<Assignment, String>(c => c.Description);
 
-        public DateTime StartTime
-        {
-            get
-            {
-                var startspan = Row.Get<Assignment, TimeSpan>(c => c.Actual.Start);
-                if (startspan.TotalMinutes != 0)
-                    return Row.Get<Assignment, DateTime>(c => c.Date).Add(Row.Get<Assignment, TimeSpan>(c => c.Actual.Start));
-                else
-                    return Row.Get<Assignment, DateTime>(c => c.Date).Add(Row.Get<Assignment, TimeSpan>(c => c.Booked.Start));
-            }
-        }
-
-
-        public DateTime EndTime
-        {
-            get
-            {
-                var finishspan = Row.Get<Assignment, TimeSpan>(c => c.Actual.Finish);
-                if (finishspan.TotalMinutes != 0)
-                    return Row.Get<Assignment, DateTime>(c => c.Date).Add(Row.Get<Assignment, TimeSpan>(c => c.Actual.Finish));
-                else
-                    return Row.Get<Assignment, DateTime>(c => c.Date).Add(Row.Get<Assignment, TimeSpan>(c => c.Booked.Finish));
-            }
-        }
-
+        public DateTime StartTime => Row.ToObject<Assignment>().EffectiveStart();
+            
+        public DateTime EndTime => Row.ToObject<Assignment>().EffectiveFinish();
+                  
         public bool Completed => !Row.Get<Assignment, DateTime>(c => c.Completed).IsEmpty();
 
         public Color Color

+ 3 - 0
prs.mobile/comal.timesheets/Main/MainPage.xaml.cs

@@ -60,6 +60,9 @@ namespace comal.timesheets
                 GlobalVariables.EmpID = GlobalVariables.GetEmployeeID();
                 GlobalVariables.EmpName = GlobalVariables.GetEmployeeName();
 
+                App.Data.Employee.ID = GlobalVariables.EmpID;
+                App.Data.Employee.Name = GlobalVariables.EmpName;
+
                 MessagingCenter.Subscribe<App>(this, App.MessageOnResume,
                 (o) =>
                 {