Skip to content

Finished project#121

Closed
davetn657 wants to merge 2 commits intothe-csharp-academy:mainfrom
davetn657:main
Closed

Finished project#121
davetn657 wants to merge 2 commits intothe-csharp-academy:mainfrom
davetn657:main

Conversation

@davetn657
Copy link
Copy Markdown

No description provided.

davetn657 and others added 2 commits March 17, 2026 13:02
Added project overview, requirements, technologies, and reflections.
@chrisjamiecarter chrisjamiecarter self-assigned this Apr 12, 2026
Copy link
Copy Markdown
Collaborator

@chrisjamiecarter chrisjamiecarter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @davetn657 👋,

Excellent work on your Shifts Logger project submission 🎉!

I have performed a peer review. Review/ignore any comments as you wish.


🟢 Requirements

⭐ You have fulfilled all of the project requirements!

  • WebAPI records worker shifts
  • Two applications created (WebAPI + Console UI)
  • Validation occurs in UI App
  • API controller is lean
  • Code-First Approach with EF Core migrations
  • Shift duration calculated from start and end times

I will go ahead and mark as approved, keep up the excellent work on the next projects! 😊

Best regards,
@chrisjamiecarter 👍

Comment on lines +1 to +24
namespace ShiftsLogger.davetn657.Controllers
{
internal class Validation
{
public Validation()
{

}

internal DateTime? IsValidTime(string time)
{
if (DateTime.TryParse(time, out DateTime convertedTime)) return convertedTime;

return null;
}

internal DateTime? IsValidTime(DateTime? startTime, DateTime? endTime)
{
if (endTime < startTime) return null;

return endTime;
}
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Namespaces

💡 As per the academy's code-conventions, use file-scoped namespaces.

➡️ From C# 10, we are able to remove the block/braces and save on level of indentation, optimising space and improving readability.

Suggested change
namespace ShiftsLogger.davetn657.Controllers
{
internal class Validation
{
public Validation()
{
}
internal DateTime? IsValidTime(string time)
{
if (DateTime.TryParse(time, out DateTime convertedTime)) return convertedTime;
return null;
}
internal DateTime? IsValidTime(DateTime? startTime, DateTime? endTime)
{
if (endTime < startTime) return null;
return endTime;
}
}
}
namespace ShiftsLogger.davetn657.Controllers;
internal class Validation
{
public Validation()
{
}
internal DateTime? IsValidTime(string time)
{
if (DateTime.TryParse(time, out DateTime convertedTime)) return convertedTime;
return null;
}
internal DateTime? IsValidTime(DateTime? startTime, DateTime? endTime)
{
if (endTime < startTime) return null;
return endTime;
}
}

Comment on lines +3 to +23
internal class Validation
{
public Validation()
{

}

internal DateTime? IsValidTime(string time)
{
if (DateTime.TryParse(time, out DateTime convertedTime)) return convertedTime;

return null;
}

internal DateTime? IsValidTime(DateTime? startTime, DateTime? endTime)
{
if (endTime < startTime) return null;

return endTime;
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Static Class/Methods

💡 These should be static as they do not require an instance.

Suggested change
internal class Validation
{
public Validation()
{
}
internal DateTime? IsValidTime(string time)
{
if (DateTime.TryParse(time, out DateTime convertedTime)) return convertedTime;
return null;
}
internal DateTime? IsValidTime(DateTime? startTime, DateTime? endTime)
{
if (endTime < startTime) return null;
return endTime;
}
}
internal static class Validation
{
internal static DateTime? IsValidTime(string time)
{
if (DateTime.TryParse(time, out DateTime convertedTime)) return convertedTime;
return null;
}
internal static DateTime? IsValidTime(DateTime? startTime, DateTime? endTime)
{
if (endTime < startTime) return null;
return endTime;
}
}

internal class Shift
{
[JsonPropertyName("id")]
public int id { get; set; }
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Inconsistent Property Naming

⚠️ Property id should be Id to follow PascalCase convention for public API members. Even with [JsonPropertyName("id")], the C# property should follow naming conventions:

Suggested change
public int id { get; set; }
public int Id { get; set; }


if (Int32.TryParse(selected, out int i))
{
EditShift(shifts.UserShifts[i]);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Fire-and-Forget Async Call

⚠️ EditShift is an async method by called without await.

Suggested change
EditShift(shifts.UserShifts[i]);
await EditShift(shifts.UserShifts[i]);


var name = AnsiConsole.Ask<string>("Enter shift logger's name (or type r to return): ");

if (name.ToLower() == "r") return;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Magic String

⚠️ The string "r" is used as a magic value for return navigation. Extract to a named constant:

private const string ReturnOption = "r";
// Then use: if (name.ToLower() == ReturnOption)

"Add Shift"
};

var logNames = new List<Shift>();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Misleading Variable Name

ℹ️ Variable logNames suggests a collection of names but is actually a List<Shift>. Consider allShifts or shifts.


public Shift? GetShiftById(int id)
{
var savedFlight = _dbContext.Shifts.Find(id);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Copy-Paste Variable Name

ℹ️ Variable savedFlight appears to be a leftover from another project. Should be savedShift:

var savedShift = _dbContext.Shifts.Find(id);
return savedShift;

}
}

private void TitleCard(string title)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Good Use of Spectre.Console

⭐ Excellent Polished CLI experience with FigletText for titles and nice formatting!

public string DeleteShift(int id);
}

public class LoggingService : ILoggingService
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Good Service Implementation

⭐ Good use of dependency injection and the service pattern with interface ILoggingService. This makes the code testable and follows SOLID principles!

{
[ApiController]
[Route("api/[controller]")]
public class ShiftsController : ControllerBase
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Lean API Controller

⭐ The controller follows best practices - it's thin and delegates to the service layer. Well done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants