1
\$\begingroup\$

I am writing an ASP.Net MVC app which has a page that will display a standard table which will contain a person's hours for the week. The basic structure of the table would be a 7 column, muti-row table. The Header of each column would display the Day of the Week with the total hours worked that week. There would then be rows for the time of the day starting at 8AM going to 5:30 PM in 15m increments. In the table for each day would be a listing of what projects where worked on that day with an indication of when it started and stopped being worked on. (Please see image below for visual aid).

I have built a ViewModel to hold the data for this table and pass it up but I am not sure if I built it in a manor that makes it efficient to work though and have it's data displayed so I would love to have some feedback on ways I might be able to improve it or even alternate ways of building such a ViewModel.

If this is off topic here please let me know where is on topic and I will delete and post there.

My ViewModel Code:

{
    public class TimesheetHoursTableVM
    {
        public int TimesheetHeaderID { get; set; }
        public DateTime WeekEndingDate { get; set; }
        public decimal TotalWeekHours { get; set; }
        public decimal SundayHours { get; set; }
        public decimal MondayHours { get; set; }
        public decimal TuesdayHours { get; set; }
        public decimal WednesdayHours { get; set; }
        public decimal ThursdayHours { get; set; }
        public decimal FridayHours { get; set; }
        public decimal SaturdayHours { get; set; }
        public IEnumerable<TimesheetDailyHoursVM> SundayTimesheet { get; set; }
        public IEnumerable<TimesheetDailyHoursVM> MondayTimesheet { get; set; }
        public IEnumerable<TimesheetDailyHoursVM> TuesdayTimesheet { get; set; }
        public IEnumerable<TimesheetDailyHoursVM> WednesdayTimesheet { get; set; }
        public IEnumerable<TimesheetDailyHoursVM> ThrusdayTimesheet { get; set; }
        public IEnumerable<TimesheetDailyHoursVM> FrodauTimesheet { get; set; }
        public IEnumerable<TimesheetDailyHoursVM> SaturdayTimesheet { get; set; }
    }

    public class TimesheetDailyHoursVM
    {
        public int TimesheetID { get; set; }
        public DateTime StartDateTime { get; set; }
        public DateTime EndDateTime { get; set; }
        public string ProjectCode { get; set; }
        public string TaskCode { get; set; }
        public string ProjectDescription { get; set; }
        public string TaskDescription { get; set; }
    }
}

Table the data goes into:

enter image description here

\$\endgroup\$
1
\$\begingroup\$

I don't think there is anything necessarilly wrong with your approach especially if it works. However I personal might consider trying to leverage the DayOfWeek enumeration of c# and avoid the individual day timesheets.

This way you could loop over weeks more easily as well as potentially leverage Linq to do things such as calculating the TotalHours as part of the viewModel.

My viewModel for this case might then look like this:

public class TimesheetWeeklyTableVM
{
    public int TimesheetHeaderID { get; set; }
    public DateTime WeekEndingDate { get; set; }
    public decimal TotalWeekHours { get; set; }

    public List<TimesheetDailyVM> DaysOfWeek { get; set; }

    public TimesheetWeeklyTableVM()
    {
        DaysOfWeek = new List<TimesheetDailyVM>();

        foreach (DayOfWeek dayOfWeek in Enum.GetValues(typeof(DayOfWeek)))
        {
            DaysOfWeek.Add(new TimesheetDailyVM()
            {
                DayOfWeek = dayOfWeek
            });
        }
    }
}

public class TimesheetDailyVM
{
    public DayOfWeek DayOfWeek { get; set; }

    public double TotalHours
    {
        get { return TimeSpan.FromSeconds(Tasks.Sum(p => (p.StartDateTime - p.EndDateTime).TotalSeconds)).TotalHours; }
    }

    public IEnumerable<TimesheetDailyHoursVM> Tasks { get; set; }

    public TimesheetDailyVM()
    {
        Tasks = new List<TimesheetDailyHoursVM>();
    }
}

public class TimesheetDailyHoursVM
{
    public int TimesheetID { get; set; }

    public DateTime StartDateTime { get; set; }
    public DateTime EndDateTime { get; set; }
    public string ProjectCode { get; set; }
    public string TaskCode { get; set; }
    public string ProjectDescription { get; set; }
    public string TaskDescription { get; set; }
}

Note, I'm not sure if TotalHours is calculated differently but if it's just a sum of the Task times then you could include that logic into the Viewmodel itself as in.

public double TotalHours
{
    get { return TimeSpan.FromSeconds(Tasks.Sum(p => (p.StartDateTime - p.EndDateTime).TotalSeconds)).TotalHours; }
}

If you wanted to add properties for each individual day to make it easier to access say for example Monday then you could easily do this such as.

public TimesheetDailyVM Monday { get { return Day(DayOfWeek.Monday); }
public TimesheetDailyVM Tuesday { get { return Day(DayOfWeek.Tuesday); }

private TimesheetDailyVM Day(DayOfWeek day) 
{
    return Days.Single(p => p.DayOfWeek == day);
}
\$\endgroup\$
  • \$\begingroup\$ Thanks for this, while my method does work it has lent it's self to a jumble of a mess of code. I like your approach. \$\endgroup\$ – Matthew Verstraete May 4 '16 at 13:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.