From d03a6cc92a25a671d1969f9b34853873f08657c3 Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sat, 24 Jan 2026 11:06:27 +0800 Subject: [PATCH 01/14] initialize project --- .../CodingTracker.Kaylubr.csproj | 20 +++++++++++++++++++ .../Controllers/CodingSessionController.cs | 0 CodingTracker.Kaylubr/Models/CodingSession.cs | 0 CodingTracker.Kaylubr/Program.cs | 1 + CodingTracker.Kaylubr/Utils/Config.cs | 0 CodingTracker.Kaylubr/Utils/Database.cs | 0 CodingTracker.Kaylubr/Utils/Helper.cs | 0 CodingTracker.Kaylubr/Views/UserInterface.cs | 0 CodingTracker.Kaylubr/appsettings.json | 5 +++++ 9 files changed, 26 insertions(+) create mode 100644 CodingTracker.Kaylubr/CodingTracker.Kaylubr.csproj create mode 100644 CodingTracker.Kaylubr/Controllers/CodingSessionController.cs create mode 100644 CodingTracker.Kaylubr/Models/CodingSession.cs create mode 100644 CodingTracker.Kaylubr/Program.cs create mode 100644 CodingTracker.Kaylubr/Utils/Config.cs create mode 100644 CodingTracker.Kaylubr/Utils/Database.cs create mode 100644 CodingTracker.Kaylubr/Utils/Helper.cs create mode 100644 CodingTracker.Kaylubr/Views/UserInterface.cs create mode 100644 CodingTracker.Kaylubr/appsettings.json diff --git a/CodingTracker.Kaylubr/CodingTracker.Kaylubr.csproj b/CodingTracker.Kaylubr/CodingTracker.Kaylubr.csproj new file mode 100644 index 00000000..e289441b --- /dev/null +++ b/CodingTracker.Kaylubr/CodingTracker.Kaylubr.csproj @@ -0,0 +1,20 @@ + + + + Exe + net10.0 + enable + enable + + + + + PreserveNewest + + + + + + + + diff --git a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs new file mode 100644 index 00000000..e69de29b diff --git a/CodingTracker.Kaylubr/Models/CodingSession.cs b/CodingTracker.Kaylubr/Models/CodingSession.cs new file mode 100644 index 00000000..e69de29b diff --git a/CodingTracker.Kaylubr/Program.cs b/CodingTracker.Kaylubr/Program.cs new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/CodingTracker.Kaylubr/Program.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Utils/Config.cs b/CodingTracker.Kaylubr/Utils/Config.cs new file mode 100644 index 00000000..e69de29b diff --git a/CodingTracker.Kaylubr/Utils/Database.cs b/CodingTracker.Kaylubr/Utils/Database.cs new file mode 100644 index 00000000..e69de29b diff --git a/CodingTracker.Kaylubr/Utils/Helper.cs b/CodingTracker.Kaylubr/Utils/Helper.cs new file mode 100644 index 00000000..e69de29b diff --git a/CodingTracker.Kaylubr/Views/UserInterface.cs b/CodingTracker.Kaylubr/Views/UserInterface.cs new file mode 100644 index 00000000..e69de29b diff --git a/CodingTracker.Kaylubr/appsettings.json b/CodingTracker.Kaylubr/appsettings.json new file mode 100644 index 00000000..be023eb9 --- /dev/null +++ b/CodingTracker.Kaylubr/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Data Source=HabitTracker.db" + } +} \ No newline at end of file From e7a50bc95f0da08a64b09c1a1efc92192d936396 Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sat, 24 Jan 2026 11:06:42 +0800 Subject: [PATCH 02/14] add solution --- CodeReviews.Console.CodingTracker.sln | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 CodeReviews.Console.CodingTracker.sln diff --git a/CodeReviews.Console.CodingTracker.sln b/CodeReviews.Console.CodingTracker.sln new file mode 100644 index 00000000..d53da901 --- /dev/null +++ b/CodeReviews.Console.CodingTracker.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodingTracker.Kaylubr", "CodingTracker.Kaylubr\CodingTracker.Kaylubr.csproj", "{6AABB9C0-5449-298C-1EB0-59B25D4A6CAC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6AABB9C0-5449-298C-1EB0-59B25D4A6CAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6AABB9C0-5449-298C-1EB0-59B25D4A6CAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6AABB9C0-5449-298C-1EB0-59B25D4A6CAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6AABB9C0-5449-298C-1EB0-59B25D4A6CAC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {67FA8CC2-65C3-4683-B605-8F131556E3AC} + EndGlobalSection +EndGlobal From 8972078a0755d9c7c4662456b01b195d5f0b6407 Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sat, 24 Jan 2026 11:25:07 +0800 Subject: [PATCH 03/14] finish styling ui --- .../CodingTracker.Kaylubr.csproj | 1 + CodingTracker.Kaylubr/Enums/MenuChoices.cs | 9 ++++ CodingTracker.Kaylubr/Program.cs | 4 +- CodingTracker.Kaylubr/Views/UserInterface.cs | 44 +++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 CodingTracker.Kaylubr/Enums/MenuChoices.cs diff --git a/CodingTracker.Kaylubr/CodingTracker.Kaylubr.csproj b/CodingTracker.Kaylubr/CodingTracker.Kaylubr.csproj index e289441b..de3bc337 100644 --- a/CodingTracker.Kaylubr/CodingTracker.Kaylubr.csproj +++ b/CodingTracker.Kaylubr/CodingTracker.Kaylubr.csproj @@ -15,6 +15,7 @@ + diff --git a/CodingTracker.Kaylubr/Enums/MenuChoices.cs b/CodingTracker.Kaylubr/Enums/MenuChoices.cs new file mode 100644 index 00000000..57a97421 --- /dev/null +++ b/CodingTracker.Kaylubr/Enums/MenuChoices.cs @@ -0,0 +1,9 @@ +namespace CodingTracker.Enums; + +internal enum MenuChoices +{ + View, + Insert, + Update, + Delete +} \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Program.cs b/CodingTracker.Kaylubr/Program.cs index 5f282702..2fa6a3db 100644 --- a/CodingTracker.Kaylubr/Program.cs +++ b/CodingTracker.Kaylubr/Program.cs @@ -1 +1,3 @@ - \ No newline at end of file +using CodingTracker.Views; + +UserInterface.Run(); \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Views/UserInterface.cs b/CodingTracker.Kaylubr/Views/UserInterface.cs index e69de29b..8e6c2474 100644 --- a/CodingTracker.Kaylubr/Views/UserInterface.cs +++ b/CodingTracker.Kaylubr/Views/UserInterface.cs @@ -0,0 +1,44 @@ +using Spectre.Console; +using CodingTracker.Enums; + +namespace CodingTracker.Views; + +internal static class UserInterface +{ + internal static void Run() + { + while (true) + { + RenderTitle(); + + var choice = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("[Chartreuse3_1]Pick operation:[/]") + .HighlightStyle(new Style(Color.Chartreuse3_1)) + .AddChoices(Enum.GetValues()) + ); + + switch (choice) + { + case MenuChoices.View: + break; + case MenuChoices.Insert: + break; + case MenuChoices.Update: + break; + case MenuChoices.Delete: + break; + } + + Console.ReadKey(); + } + } + + static void RenderTitle() + { + Console.Clear(); + var panel = new Panel("Welcome to Coding Session Tracker!"); + panel.Border(BoxBorder.Ascii); + AnsiConsole.Write(panel); + } +} From 74ea22757ca71354feeecf67956da7903128a6fc Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sat, 24 Jan 2026 13:39:16 +0800 Subject: [PATCH 04/14] add functionality for inserting data --- .../Controllers/CodingSessionController.cs | 28 +++++++++++ CodingTracker.Kaylubr/Models/CodingSession.cs | 9 ++++ CodingTracker.Kaylubr/Program.cs | 2 + CodingTracker.Kaylubr/Utils/Config.cs | 16 +++++++ CodingTracker.Kaylubr/Utils/Database.cs | 31 ++++++++++++ CodingTracker.Kaylubr/Utils/Helper.cs | 47 +++++++++++++++++++ CodingTracker.Kaylubr/Views/UserInterface.cs | 7 +-- 7 files changed, 137 insertions(+), 3 deletions(-) diff --git a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs index e69de29b..ca5bc7c8 100644 --- a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs +++ b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs @@ -0,0 +1,28 @@ +using CodingTracker.Utils; + +namespace CodingTracker.Controllers; + +internal static class CodingTrackerController +{ + internal static void InsertSession() + { + DateTime startTime; + DateTime endTime; + + do + { + startTime = Helper.GetTime("start"); + endTime = Helper.GetTime("end"); + } while (!Helper.ValidateTime(startTime, endTime)); + + TimeSpan duration = Helper.GetDuration(startTime, endTime); + + string startTimeInString = startTime.ToString(); + string endTimeInString = endTime.ToString(); + string durationInString = duration.ToString(); + + Database.Insert(startTimeInString, endTimeInString, durationInString); + + Helper.PrintSuccessOperation(); + } +} \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Models/CodingSession.cs b/CodingTracker.Kaylubr/Models/CodingSession.cs index e69de29b..0ae5719a 100644 --- a/CodingTracker.Kaylubr/Models/CodingSession.cs +++ b/CodingTracker.Kaylubr/Models/CodingSession.cs @@ -0,0 +1,9 @@ +namespace CodingTracker.Models; + +internal class CodingSession +{ + int Id { get; set; } + DateTime StartTime { get; set; } + DateTime EndTime { get; set; } + TimeSpan duration { get; set; } +} \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Program.cs b/CodingTracker.Kaylubr/Program.cs index 2fa6a3db..9c42948a 100644 --- a/CodingTracker.Kaylubr/Program.cs +++ b/CodingTracker.Kaylubr/Program.cs @@ -1,3 +1,5 @@ using CodingTracker.Views; +using CodingTracker.Utils; +Database.CreateDatabase(); UserInterface.Run(); \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Utils/Config.cs b/CodingTracker.Kaylubr/Utils/Config.cs index e69de29b..46774a10 100644 --- a/CodingTracker.Kaylubr/Utils/Config.cs +++ b/CodingTracker.Kaylubr/Utils/Config.cs @@ -0,0 +1,16 @@ +using Microsoft.Extensions.Configuration; + +namespace CodingTracker.Utils; + +internal static class Config +{ + internal static string? InitializeConfig() + { + var configuration = new ConfigurationBuilder() + .SetBasePath(AppContext.BaseDirectory) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .Build(); + + return configuration.GetConnectionString("DefaultConnection"); + } +} \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Utils/Database.cs b/CodingTracker.Kaylubr/Utils/Database.cs index e69de29b..2de0fa6b 100644 --- a/CodingTracker.Kaylubr/Utils/Database.cs +++ b/CodingTracker.Kaylubr/Utils/Database.cs @@ -0,0 +1,31 @@ +using Dapper; +using Microsoft.Data.Sqlite; + +namespace CodingTracker.Utils; + +internal static class Database +{ + readonly static string? connectionString = Config.InitializeConfig(); + readonly static SqliteConnection connection = new(connectionString); + + internal static void CreateDatabase() + { + var sql = @"CREATE TABLE IF NOT EXISTS coding_session ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + start_time TEXT, + end_time TEXT, + duration TEXT + )"; + + connection.Execute(sql); + } + + internal static void Insert(string st, string et, string duration) + { + var sql = @"INSERT INTO coding_session (start_time, end_time, duration) + VALUES (@start, @end, @duration) + "; + + connection.Execute(sql, new { start = st, end = et, duration }); + } +} \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Utils/Helper.cs b/CodingTracker.Kaylubr/Utils/Helper.cs index e69de29b..4bdde137 100644 --- a/CodingTracker.Kaylubr/Utils/Helper.cs +++ b/CodingTracker.Kaylubr/Utils/Helper.cs @@ -0,0 +1,47 @@ +using System.Globalization; +using Spectre.Console; + +namespace CodingTracker.Utils; + +internal static class Helper +{ + internal static DateTime GetTime(string message) + { + while (true) + { + var time = AnsiConsole.Ask($"Enter [green]{message}[/] session time in the format (dd-MM-yy HH-mm): "); + + if (DateTime.TryParseExact(time, "dd-MM-yy HH:mm", new CultureInfo("en-US"), DateTimeStyles.None, out _)) + { + return DateTime.ParseExact(time, "dd-MM-yy HH:mm", new CultureInfo("en-US")); + } + + AnsiConsole.MarkupLine("[red]Invalid Format or Invalid Date & Time[/]"); + } + + } + + internal static TimeSpan GetDuration(DateTime start, DateTime end) + { + return end - start; + } + + internal static bool ValidateTime(DateTime start, DateTime end) + { + if (start > end) + { + AnsiConsole.MarkupLine("[red]Starting time shouldn't be greater than the end time.[/]"); + return false; + } + + return true; + } + + internal static void PrintSuccessOperation() + { + AnsiConsole.MarkupLine("\n[green]Successful operation![/]"); + + AnsiConsole.WriteLine("\nPress any key to continue.."); + Console.ReadKey(); + } +} diff --git a/CodingTracker.Kaylubr/Views/UserInterface.cs b/CodingTracker.Kaylubr/Views/UserInterface.cs index 8e6c2474..8b91a645 100644 --- a/CodingTracker.Kaylubr/Views/UserInterface.cs +++ b/CodingTracker.Kaylubr/Views/UserInterface.cs @@ -1,5 +1,7 @@ using Spectre.Console; using CodingTracker.Enums; +using CodingTracker.Controllers; +using CodingTracker.Models; namespace CodingTracker.Views; @@ -14,7 +16,7 @@ internal static void Run() var choice = AnsiConsole.Prompt( new SelectionPrompt() .Title("[Chartreuse3_1]Pick operation:[/]") - .HighlightStyle(new Style(Color.Chartreuse3_1)) + .HighlightStyle(new Style(Color.Green)) .AddChoices(Enum.GetValues()) ); @@ -23,14 +25,13 @@ internal static void Run() case MenuChoices.View: break; case MenuChoices.Insert: + CodingTrackerController.InsertSession(); break; case MenuChoices.Update: break; case MenuChoices.Delete: break; } - - Console.ReadKey(); } } From 75c147a4e27aedc982f19ebbd325a0953492e299 Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sat, 24 Jan 2026 13:39:51 +0800 Subject: [PATCH 05/14] update gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 49976e11..47972c0c 100644 --- a/.gitignore +++ b/.gitignore @@ -478,3 +478,5 @@ $RECYCLE.BIN/ *.lnk /MathGame2 /CodingTracker.TomDonegan/TextFile1.txt + +*.db \ No newline at end of file From c0583760bd4ed14034b486bf6326a477c06dc92a Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sat, 24 Jan 2026 14:39:34 +0800 Subject: [PATCH 06/14] finish functionality for rendering data --- .../Controllers/CodingSessionController.cs | 12 ++++-- CodingTracker.Kaylubr/Models/CodingSession.cs | 8 ++-- CodingTracker.Kaylubr/Utils/Database.cs | 8 ++++ CodingTracker.Kaylubr/Utils/Helper.cs | 42 ++++++++++++++++++- CodingTracker.Kaylubr/Views/UserInterface.cs | 16 ++++--- 5 files changed, 72 insertions(+), 14 deletions(-) diff --git a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs index ca5bc7c8..3eb80455 100644 --- a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs +++ b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs @@ -1,3 +1,4 @@ +using CodingTracker.Models; using CodingTracker.Utils; namespace CodingTracker.Controllers; @@ -15,14 +16,19 @@ internal static void InsertSession() endTime = Helper.GetTime("end"); } while (!Helper.ValidateTime(startTime, endTime)); - TimeSpan duration = Helper.GetDuration(startTime, endTime); + string duration = Helper.GetDuration(startTime, endTime); string startTimeInString = startTime.ToString(); string endTimeInString = endTime.ToString(); - string durationInString = duration.ToString(); - Database.Insert(startTimeInString, endTimeInString, durationInString); + Database.Insert(startTimeInString, endTimeInString, duration); Helper.PrintSuccessOperation(); } + + internal static void LogAllRecords() + { + List codingSessions = Database.GetAll(); + Helper.RenderCodingSessionInTable(codingSessions); + } } \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Models/CodingSession.cs b/CodingTracker.Kaylubr/Models/CodingSession.cs index 0ae5719a..b4b47b7a 100644 --- a/CodingTracker.Kaylubr/Models/CodingSession.cs +++ b/CodingTracker.Kaylubr/Models/CodingSession.cs @@ -2,8 +2,8 @@ namespace CodingTracker.Models; internal class CodingSession { - int Id { get; set; } - DateTime StartTime { get; set; } - DateTime EndTime { get; set; } - TimeSpan duration { get; set; } + internal int Id { get; set; } + internal DateTime StartTime { get; set; } + internal DateTime EndTime { get; set; } + internal required string Duration { get; set; } } \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Utils/Database.cs b/CodingTracker.Kaylubr/Utils/Database.cs index 2de0fa6b..71584486 100644 --- a/CodingTracker.Kaylubr/Utils/Database.cs +++ b/CodingTracker.Kaylubr/Utils/Database.cs @@ -1,3 +1,4 @@ +using CodingTracker.Models; using Dapper; using Microsoft.Data.Sqlite; @@ -28,4 +29,11 @@ internal static void Insert(string st, string et, string duration) connection.Execute(sql, new { start = st, end = et, duration }); } + + internal static List GetAll() + { + var sql = "SELECT * FROM coding_session"; + List records = connection.Query(sql).ToList(); + return records; + } } \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Utils/Helper.cs b/CodingTracker.Kaylubr/Utils/Helper.cs index 4bdde137..d5927834 100644 --- a/CodingTracker.Kaylubr/Utils/Helper.cs +++ b/CodingTracker.Kaylubr/Utils/Helper.cs @@ -1,4 +1,5 @@ using System.Globalization; +using CodingTracker.Models; using Spectre.Console; namespace CodingTracker.Utils; @@ -21,9 +22,9 @@ internal static DateTime GetTime(string message) } - internal static TimeSpan GetDuration(DateTime start, DateTime end) + internal static string GetDuration(DateTime start, DateTime end) { - return end - start; + return (end - start).ToString(@"hh\:mm\:ss"); } internal static bool ValidateTime(DateTime start, DateTime end) @@ -37,6 +38,43 @@ internal static bool ValidateTime(DateTime start, DateTime end) return true; } + internal static void RenderCodingSessionInTable(List codingSessions) + { + var table = new Table() + .Title("\n[green bold]Session Records[/]") + .Border(TableBorder.Heavy); + + table.AddColumn("ID"); + table.AddColumn("Starting time"); + table.AddColumn("End time"); + table.AddColumn("Duration"); + + foreach (var session in codingSessions) + { + table.AddRow(session.Id.ToString(), session.StartTime.ToString(), session.EndTime.ToString(), session.Duration); + } + + AnsiConsole.Write(table); + + AnsiConsole.WriteLine("\nPress any key to exit.."); + Console.ReadKey(); + } + + internal static bool Confirmation() + { + string? choice; + + do + { + choice = AnsiConsole.Ask(@"Do you want to perform the operation [green]y[/] or [red]n[/]:").Trim().ToLower(); + } while (choice != "y" && choice != "n"); + + if (choice == "n") + return false; + + return true; + } + internal static void PrintSuccessOperation() { AnsiConsole.MarkupLine("\n[green]Successful operation![/]"); diff --git a/CodingTracker.Kaylubr/Views/UserInterface.cs b/CodingTracker.Kaylubr/Views/UserInterface.cs index 8b91a645..140f5a48 100644 --- a/CodingTracker.Kaylubr/Views/UserInterface.cs +++ b/CodingTracker.Kaylubr/Views/UserInterface.cs @@ -1,7 +1,7 @@ using Spectre.Console; -using CodingTracker.Enums; using CodingTracker.Controllers; -using CodingTracker.Models; +using CodingTracker.Enums; +using CodingTracker.Utils; namespace CodingTracker.Views; @@ -15,14 +15,20 @@ internal static void Run() var choice = AnsiConsole.Prompt( new SelectionPrompt() - .Title("[Chartreuse3_1]Pick operation:[/]") + .Title("\n[Green]Pick operation:[/]") .HighlightStyle(new Style(Color.Green)) .AddChoices(Enum.GetValues()) - ); + ); + + if (!Helper.Confirmation()) + { + continue; + } switch (choice) { case MenuChoices.View: + CodingTrackerController.LogAllRecords(); break; case MenuChoices.Insert: CodingTrackerController.InsertSession(); @@ -39,7 +45,7 @@ static void RenderTitle() { Console.Clear(); var panel = new Panel("Welcome to Coding Session Tracker!"); - panel.Border(BoxBorder.Ascii); + panel.Border(BoxBorder.Heavy); AnsiConsole.Write(panel); } } From 29bb1694b9b1e9be26fd803f16e6ce0ee139a02e Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sun, 25 Jan 2026 12:34:54 +0800 Subject: [PATCH 07/14] feat: add updating functionality --- .../Controllers/CodingSessionController.cs | 41 ++++++----- CodingTracker.Kaylubr/Models/CodingSession.cs | 10 +-- CodingTracker.Kaylubr/Utils/Database.cs | 35 +++++++-- CodingTracker.Kaylubr/Utils/Helper.cs | 71 +++++++++++++++---- CodingTracker.Kaylubr/Views/UserInterface.cs | 1 + 5 files changed, 116 insertions(+), 42 deletions(-) diff --git a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs index 3eb80455..ce5f81b9 100644 --- a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs +++ b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs @@ -7,28 +7,35 @@ internal static class CodingTrackerController { internal static void InsertSession() { - DateTime startTime; - DateTime endTime; + var (startTime, endTime) = Helper.GetStartAndEndTime(); + string duration = Helper.GetDuration(startTime, endTime); + Database.Insert(startTime, endTime, duration); + Helper.Pause("Successful Operation!", success: true); + } - do - { - startTime = Helper.GetTime("start"); - endTime = Helper.GetTime("end"); - } while (!Helper.ValidateTime(startTime, endTime)); + internal static void LogAllRecords() + { + Helper.RenderCodingSessionInTable(Database.GetAll()); + Helper.Pause(); + } - string duration = Helper.GetDuration(startTime, endTime); + internal static void UpdateRecord() + { + Helper.RenderCodingSessionInTable(Database.GetAll()); - string startTimeInString = startTime.ToString(); - string endTimeInString = endTime.ToString(); + int id = Helper.GetID(); - Database.Insert(startTimeInString, endTimeInString, duration); + if (!Database.FindOneSession(id)) + { + Helper.Pause("Record not found!", success: false); + return; + } - Helper.PrintSuccessOperation(); - } + var (startTime, endTime) = Helper.GetStartAndEndTime(); + string duration = Helper.GetDuration(startTime, endTime); - internal static void LogAllRecords() - { - List codingSessions = Database.GetAll(); - Helper.RenderCodingSessionInTable(codingSessions); + Database.Update(id, startTime, endTime, duration); + + Helper.Pause("Successful Operation!", success: true); } } \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Models/CodingSession.cs b/CodingTracker.Kaylubr/Models/CodingSession.cs index b4b47b7a..95f00f66 100644 --- a/CodingTracker.Kaylubr/Models/CodingSession.cs +++ b/CodingTracker.Kaylubr/Models/CodingSession.cs @@ -1,9 +1,9 @@ namespace CodingTracker.Models; -internal class CodingSession +public class CodingSession { - internal int Id { get; set; } - internal DateTime StartTime { get; set; } - internal DateTime EndTime { get; set; } - internal required string Duration { get; set; } + public int Id { get; set; } + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public string Duration { get; set; } = string.Empty; } \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Utils/Database.cs b/CodingTracker.Kaylubr/Utils/Database.cs index 71584486..a3600269 100644 --- a/CodingTracker.Kaylubr/Utils/Database.cs +++ b/CodingTracker.Kaylubr/Utils/Database.cs @@ -12,10 +12,10 @@ internal static class Database internal static void CreateDatabase() { var sql = @"CREATE TABLE IF NOT EXISTS coding_session ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - start_time TEXT, - end_time TEXT, - duration TEXT + Id INTEGER PRIMARY KEY AUTOINCREMENT, + StartTime TEXT, + EndTime TEXT, + Duration TEXT )"; connection.Execute(sql); @@ -23,7 +23,7 @@ duration TEXT internal static void Insert(string st, string et, string duration) { - var sql = @"INSERT INTO coding_session (start_time, end_time, duration) + var sql = @"INSERT INTO coding_session (StartTime, EndTime, Duration) VALUES (@start, @end, @duration) "; @@ -34,6 +34,31 @@ internal static List GetAll() { var sql = "SELECT * FROM coding_session"; List records = connection.Query(sql).ToList(); + return records; } + + internal static void Update(int id, string st, string et, string duration) + { + var sql = "UPDATE coding_session SET StartTime = @st, EndTime = @et, Duration = @duration WHERE Id = @id"; + var obj = new { id, st, et, duration }; + + connection.Execute(sql, obj); + } + + internal static bool FindOneSession(int id) + { + var sql = "SELECT * FROM coding_session WHERE Id = @id"; + var obj = new { id }; + + try + { + connection.QuerySingle(sql, obj); + return true; + } + catch + { + return false; + } + } } \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Utils/Helper.cs b/CodingTracker.Kaylubr/Utils/Helper.cs index d5927834..071fb9b9 100644 --- a/CodingTracker.Kaylubr/Utils/Helper.cs +++ b/CodingTracker.Kaylubr/Utils/Helper.cs @@ -6,7 +6,31 @@ namespace CodingTracker.Utils; internal static class Helper { - internal static DateTime GetTime(string message) + internal static int GetID() + { + AnsiConsole.WriteLine(); + return AnsiConsole.Ask($"\nEnter the [green]ID[/] of the row to be edited: "); + } + + internal static (string StartTime, string EndTime) GetStartAndEndTime() + { + DateTime start; + DateTime end; + + do + { + AnsiConsole.WriteLine(); + start = GetTime("start"); + end = GetTime("end"); + } while (!ValidateTime(start, end)); + + string startTime = start.ToString(); + string endTime = end.ToString(); + + return (startTime, endTime); + } + + static DateTime GetTime(string message) { while (true) { @@ -22,12 +46,15 @@ internal static DateTime GetTime(string message) } - internal static string GetDuration(DateTime start, DateTime end) + internal static string GetDuration(string start, string end) { - return (end - start).ToString(@"hh\:mm\:ss"); + DateTime startTime = DateTime.Parse(start); + DateTime endTime = DateTime.Parse(end); + + return (endTime - startTime).ToString(@"hh\:mm\:ss"); } - internal static bool ValidateTime(DateTime start, DateTime end) + static bool ValidateTime(DateTime start, DateTime end) { if (start > end) { @@ -40,8 +67,9 @@ internal static bool ValidateTime(DateTime start, DateTime end) internal static void RenderCodingSessionInTable(List codingSessions) { + AnsiConsole.Clear(); var table = new Table() - .Title("\n[green bold]Session Records[/]") + .Title("[green bold]Session Records[/]") .Border(TableBorder.Heavy); table.AddColumn("ID"); @@ -55,31 +83,44 @@ internal static void RenderCodingSessionInTable(List codingSessio } AnsiConsole.Write(table); - - AnsiConsole.WriteLine("\nPress any key to exit.."); - Console.ReadKey(); } internal static bool Confirmation() { - string? choice; + AnsiConsole.WriteLine(); + string? choice; do { - choice = AnsiConsole.Ask(@"Do you want to perform the operation [green]y[/] or [red]n[/]:").Trim().ToLower(); - } while (choice != "y" && choice != "n"); + choice = AnsiConsole.Ask("Do you want to perform the operation [bold green]Y[/] or [bold red]N[/]:").Trim().ToUpper(); + } while (choice != "Y" && choice != "N"); - if (choice == "n") + if (choice == "N") return false; return true; } - internal static void PrintSuccessOperation() + internal static void Pause() + { + AnsiConsole.Write("\nPress any key to continue.."); + Console.ReadKey(); + } + + internal static void Pause(string message, bool success) { - AnsiConsole.MarkupLine("\n[green]Successful operation![/]"); + if (success) + { + AnsiConsole.MarkupLine($"\n[green]{message}[/]"); + } + else + { + AnsiConsole.MarkupLine($"\n[red]{message}[/]"); + } - AnsiConsole.WriteLine("\nPress any key to continue.."); + AnsiConsole.Write("\nPress any key to continue.."); Console.ReadKey(); + + AnsiConsole.Clear(); } } diff --git a/CodingTracker.Kaylubr/Views/UserInterface.cs b/CodingTracker.Kaylubr/Views/UserInterface.cs index 140f5a48..c48c7e52 100644 --- a/CodingTracker.Kaylubr/Views/UserInterface.cs +++ b/CodingTracker.Kaylubr/Views/UserInterface.cs @@ -34,6 +34,7 @@ internal static void Run() CodingTrackerController.InsertSession(); break; case MenuChoices.Update: + CodingTrackerController.UpdateRecord(); break; case MenuChoices.Delete: break; From 0c0da00b0e0f9c658a3ff950cab3c13c7f7fa5be Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sun, 25 Jan 2026 13:07:37 +0800 Subject: [PATCH 08/14] feat: add deleting functionality --- .../Controllers/CodingSessionController.cs | 25 +++++++++++++++++-- CodingTracker.Kaylubr/Utils/Database.cs | 6 +++++ CodingTracker.Kaylubr/Utils/Helper.cs | 8 +++--- CodingTracker.Kaylubr/Views/UserInterface.cs | 3 ++- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs index ce5f81b9..7b8646fc 100644 --- a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs +++ b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs @@ -1,4 +1,3 @@ -using CodingTracker.Models; using CodingTracker.Utils; namespace CodingTracker.Controllers; @@ -23,7 +22,7 @@ internal static void UpdateRecord() { Helper.RenderCodingSessionInTable(Database.GetAll()); - int id = Helper.GetID(); + int id = Helper.GetID("EDITED"); if (!Database.FindOneSession(id)) { @@ -38,4 +37,26 @@ internal static void UpdateRecord() Helper.Pause("Successful Operation!", success: true); } + + internal static void DeleteRecord() + { + Helper.RenderCodingSessionInTable(Database.GetAll()); + + int id = Helper.GetID("DELETED"); + + if (!Helper.Confirmation("Are you sure?")) + { + return; + } + + Database.DeleteOne(id); + + if (!Database.FindOneSession(id)) + { + Helper.Pause("Record not found!", success: false); + return; + } + + Helper.Pause("Successful Operation!", success: true); + } } \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Utils/Database.cs b/CodingTracker.Kaylubr/Utils/Database.cs index a3600269..d17501ea 100644 --- a/CodingTracker.Kaylubr/Utils/Database.cs +++ b/CodingTracker.Kaylubr/Utils/Database.cs @@ -46,6 +46,12 @@ internal static void Update(int id, string st, string et, string duration) connection.Execute(sql, obj); } + internal static void DeleteOne(int id) + { + var sql = "DELETE FROM coding_session WHERE id = @id"; + connection.Execute(sql, new { id }); + } + internal static bool FindOneSession(int id) { var sql = "SELECT * FROM coding_session WHERE Id = @id"; diff --git a/CodingTracker.Kaylubr/Utils/Helper.cs b/CodingTracker.Kaylubr/Utils/Helper.cs index 071fb9b9..8d1907d6 100644 --- a/CodingTracker.Kaylubr/Utils/Helper.cs +++ b/CodingTracker.Kaylubr/Utils/Helper.cs @@ -6,10 +6,10 @@ namespace CodingTracker.Utils; internal static class Helper { - internal static int GetID() + internal static int GetID(string mode) { AnsiConsole.WriteLine(); - return AnsiConsole.Ask($"\nEnter the [green]ID[/] of the row to be edited: "); + return AnsiConsole.Ask($"\nEnter the [green]ID[/] of the row to be [bold]{mode}[/]: "); } internal static (string StartTime, string EndTime) GetStartAndEndTime() @@ -85,14 +85,14 @@ internal static void RenderCodingSessionInTable(List codingSessio AnsiConsole.Write(table); } - internal static bool Confirmation() + internal static bool Confirmation(string message) { AnsiConsole.WriteLine(); string? choice; do { - choice = AnsiConsole.Ask("Do you want to perform the operation [bold green]Y[/] or [bold red]N[/]:").Trim().ToUpper(); + choice = AnsiConsole.Ask($"{message} [bold green]Y[/] or [bold red]N[/]:").Trim().ToUpper(); } while (choice != "Y" && choice != "N"); if (choice == "N") diff --git a/CodingTracker.Kaylubr/Views/UserInterface.cs b/CodingTracker.Kaylubr/Views/UserInterface.cs index c48c7e52..9298a19a 100644 --- a/CodingTracker.Kaylubr/Views/UserInterface.cs +++ b/CodingTracker.Kaylubr/Views/UserInterface.cs @@ -20,7 +20,7 @@ internal static void Run() .AddChoices(Enum.GetValues()) ); - if (!Helper.Confirmation()) + if (!Helper.Confirmation("Do you want to do the operation?")) { continue; } @@ -37,6 +37,7 @@ internal static void Run() CodingTrackerController.UpdateRecord(); break; case MenuChoices.Delete: + CodingTrackerController.DeleteRecord(); break; } } From 0464d94b6f26179477fcf51db08d199dfb8692af Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sun, 25 Jan 2026 13:31:35 +0800 Subject: [PATCH 09/14] feat: add a log if the records are empty --- .../Controllers/CodingSessionController.cs | 60 ++++++++++++------- CodingTracker.Kaylubr/Utils/Helper.cs | 34 +++++++---- 2 files changed, 60 insertions(+), 34 deletions(-) diff --git a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs index 7b8646fc..abf9bf77 100644 --- a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs +++ b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs @@ -20,43 +20,57 @@ internal static void LogAllRecords() internal static void UpdateRecord() { - Helper.RenderCodingSessionInTable(Database.GetAll()); - - int id = Helper.GetID("EDITED"); + bool exists = Helper.RenderCodingSessionInTable(Database.GetAll()); - if (!Database.FindOneSession(id)) + if (exists) { - Helper.Pause("Record not found!", success: false); - return; - } + int id = Helper.GetID("EDITED"); - var (startTime, endTime) = Helper.GetStartAndEndTime(); - string duration = Helper.GetDuration(startTime, endTime); + if (!Database.FindOneSession(id)) + { + Helper.Pause("Record not found!", success: false); + return; + } - Database.Update(id, startTime, endTime, duration); + var (startTime, endTime) = Helper.GetStartAndEndTime(); + string duration = Helper.GetDuration(startTime, endTime); - Helper.Pause("Successful Operation!", success: true); + Database.Update(id, startTime, endTime, duration); + + Helper.Pause("Successful Operation!", success: true); + } + else + { + Helper.Pause(); + } } internal static void DeleteRecord() { - Helper.RenderCodingSessionInTable(Database.GetAll()); - - int id = Helper.GetID("DELETED"); + bool exists = Helper.RenderCodingSessionInTable(Database.GetAll()); - if (!Helper.Confirmation("Are you sure?")) + if (exists) { - return; - } + int id = Helper.GetID("DELETED"); + + if (!Helper.Confirmation("Are you sure?")) + { + return; + } - Database.DeleteOne(id); + Database.DeleteOne(id); - if (!Database.FindOneSession(id)) + if (!Database.FindOneSession(id)) + { + Helper.Pause("Record not found!", success: false); + return; + } + + Helper.Pause("Successful Operation!", success: true); + } + else { - Helper.Pause("Record not found!", success: false); - return; + Helper.Pause(); } - - Helper.Pause("Successful Operation!", success: true); } } \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Utils/Helper.cs b/CodingTracker.Kaylubr/Utils/Helper.cs index 8d1907d6..b56277cc 100644 --- a/CodingTracker.Kaylubr/Utils/Helper.cs +++ b/CodingTracker.Kaylubr/Utils/Helper.cs @@ -65,24 +65,36 @@ static bool ValidateTime(DateTime start, DateTime end) return true; } - internal static void RenderCodingSessionInTable(List codingSessions) + internal static bool RenderCodingSessionInTable(List codingSessions) { AnsiConsole.Clear(); - var table = new Table() - .Title("[green bold]Session Records[/]") - .Border(TableBorder.Heavy); - table.AddColumn("ID"); - table.AddColumn("Starting time"); - table.AddColumn("End time"); - table.AddColumn("Duration"); + if (codingSessions.Count >= 1) + { + var table = new Table() + .Title("[green bold]Session Records[/]") + .Border(TableBorder.Heavy); + + table.AddColumn("ID"); + table.AddColumn("Starting time"); + table.AddColumn("End time"); + table.AddColumn("Duration"); + + foreach (var session in codingSessions) + { + table.AddRow(session.Id.ToString(), session.StartTime.ToString(), session.EndTime.ToString(), session.Duration); + } - foreach (var session in codingSessions) + AnsiConsole.Write(table); + + return true; + } + else { - table.AddRow(session.Id.ToString(), session.StartTime.ToString(), session.EndTime.ToString(), session.Duration); + AnsiConsole.MarkupLine("[red]No coding sessions to display. Add a session to see it here.[/]"); + return false; } - AnsiConsole.Write(table); } internal static bool Confirmation(string message) From 8723aa8b947729f856aed19ef0e5feaa592d8dcd Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sun, 25 Jan 2026 13:55:28 +0800 Subject: [PATCH 10/14] seperate user input methods from helper class into its own userinput class --- .../Controllers/CodingSessionController.cs | 22 ++++---- CodingTracker.Kaylubr/Utils/Helper.cs | 51 +---------------- CodingTracker.Kaylubr/Utils/UserInput.cs | 56 +++++++++++++++++++ 3 files changed, 68 insertions(+), 61 deletions(-) create mode 100644 CodingTracker.Kaylubr/Utils/UserInput.cs diff --git a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs index abf9bf77..66845893 100644 --- a/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs +++ b/CodingTracker.Kaylubr/Controllers/CodingSessionController.cs @@ -6,8 +6,8 @@ internal static class CodingTrackerController { internal static void InsertSession() { - var (startTime, endTime) = Helper.GetStartAndEndTime(); - string duration = Helper.GetDuration(startTime, endTime); + var (startTime, endTime) = UserInput.GetStartAndEndTime(); + string duration = UserInput.GetDuration(startTime, endTime); Database.Insert(startTime, endTime, duration); Helper.Pause("Successful Operation!", success: true); } @@ -24,7 +24,7 @@ internal static void UpdateRecord() if (exists) { - int id = Helper.GetID("EDITED"); + int id = UserInput.GetID("EDITED"); if (!Database.FindOneSession(id)) { @@ -32,8 +32,8 @@ internal static void UpdateRecord() return; } - var (startTime, endTime) = Helper.GetStartAndEndTime(); - string duration = Helper.GetDuration(startTime, endTime); + var (startTime, endTime) = UserInput.GetStartAndEndTime(); + string duration = UserInput.GetDuration(startTime, endTime); Database.Update(id, startTime, endTime, duration); @@ -51,21 +51,21 @@ internal static void DeleteRecord() if (exists) { - int id = Helper.GetID("DELETED"); + int id = UserInput.GetID("DELETED"); - if (!Helper.Confirmation("Are you sure?")) + if (!Database.FindOneSession(id)) { + Helper.Pause("Record not found!", success: false); return; } - Database.DeleteOne(id); - - if (!Database.FindOneSession(id)) + if (!Helper.Confirmation("Are you sure?")) { - Helper.Pause("Record not found!", success: false); return; } + Database.DeleteOne(id); + Helper.Pause("Successful Operation!", success: true); } else diff --git a/CodingTracker.Kaylubr/Utils/Helper.cs b/CodingTracker.Kaylubr/Utils/Helper.cs index b56277cc..bda8863b 100644 --- a/CodingTracker.Kaylubr/Utils/Helper.cs +++ b/CodingTracker.Kaylubr/Utils/Helper.cs @@ -1,4 +1,3 @@ -using System.Globalization; using CodingTracker.Models; using Spectre.Console; @@ -6,55 +5,7 @@ namespace CodingTracker.Utils; internal static class Helper { - internal static int GetID(string mode) - { - AnsiConsole.WriteLine(); - return AnsiConsole.Ask($"\nEnter the [green]ID[/] of the row to be [bold]{mode}[/]: "); - } - - internal static (string StartTime, string EndTime) GetStartAndEndTime() - { - DateTime start; - DateTime end; - - do - { - AnsiConsole.WriteLine(); - start = GetTime("start"); - end = GetTime("end"); - } while (!ValidateTime(start, end)); - - string startTime = start.ToString(); - string endTime = end.ToString(); - - return (startTime, endTime); - } - - static DateTime GetTime(string message) - { - while (true) - { - var time = AnsiConsole.Ask($"Enter [green]{message}[/] session time in the format (dd-MM-yy HH-mm): "); - - if (DateTime.TryParseExact(time, "dd-MM-yy HH:mm", new CultureInfo("en-US"), DateTimeStyles.None, out _)) - { - return DateTime.ParseExact(time, "dd-MM-yy HH:mm", new CultureInfo("en-US")); - } - - AnsiConsole.MarkupLine("[red]Invalid Format or Invalid Date & Time[/]"); - } - - } - - internal static string GetDuration(string start, string end) - { - DateTime startTime = DateTime.Parse(start); - DateTime endTime = DateTime.Parse(end); - - return (endTime - startTime).ToString(@"hh\:mm\:ss"); - } - - static bool ValidateTime(DateTime start, DateTime end) + internal static bool ValidateTime(DateTime start, DateTime end) { if (start > end) { diff --git a/CodingTracker.Kaylubr/Utils/UserInput.cs b/CodingTracker.Kaylubr/Utils/UserInput.cs new file mode 100644 index 00000000..20f0eca1 --- /dev/null +++ b/CodingTracker.Kaylubr/Utils/UserInput.cs @@ -0,0 +1,56 @@ +using Spectre.Console; +using System.Globalization; + +namespace CodingTracker.Utils; + +internal static class UserInput +{ + internal static int GetID(string mode) + { + AnsiConsole.WriteLine(); + return AnsiConsole.Ask($"\nEnter the [green]ID[/] of the row to be [bold]{mode}[/]: "); + } + + internal static (string StartTime, string EndTime) GetStartAndEndTime() + { + DateTime start; + DateTime end; + + do + { + AnsiConsole.WriteLine(); + start = GetTime("START"); + end = GetTime("END"); + } while (!Helper.ValidateTime(start, end)); + + string startTime = start.ToString(); + string endTime = end.ToString(); + + return (startTime, endTime); + } + + static DateTime GetTime(string message) + { + while (true) + { + var time = AnsiConsole.Ask($"Enter [bold green]{message}[/] session time in the format (dd-MM-yy HH-mm): "); + + if (DateTime.TryParseExact(time, "dd-MM-yy HH:mm", new CultureInfo("en-US"), DateTimeStyles.None, out _)) + { + return DateTime.ParseExact(time, "dd-MM-yy HH:mm", new CultureInfo("en-US")); + } + + AnsiConsole.MarkupLine("[red]Invalid Format or Invalid Date & Time[/]"); + } + + } + + internal static string GetDuration(string start, string end) + { + DateTime startTime = DateTime.Parse(start); + DateTime endTime = DateTime.Parse(end); + + return (endTime - startTime).ToString(@"hh\:mm\:ss"); + } + +} \ No newline at end of file From 5a5826fdc9da2db7641c898d07b16f2d25629baa Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sun, 25 Jan 2026 13:56:55 +0800 Subject: [PATCH 11/14] remove op prompt for view records --- CodingTracker.Kaylubr/Views/UserInterface.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/CodingTracker.Kaylubr/Views/UserInterface.cs b/CodingTracker.Kaylubr/Views/UserInterface.cs index 9298a19a..2e59485c 100644 --- a/CodingTracker.Kaylubr/Views/UserInterface.cs +++ b/CodingTracker.Kaylubr/Views/UserInterface.cs @@ -20,11 +20,6 @@ internal static void Run() .AddChoices(Enum.GetValues()) ); - if (!Helper.Confirmation("Do you want to do the operation?")) - { - continue; - } - switch (choice) { case MenuChoices.View: @@ -32,11 +27,23 @@ internal static void Run() break; case MenuChoices.Insert: CodingTrackerController.InsertSession(); + + if (!Helper.Confirmation("Proceed with this operation? (No will return to the main menu)")) + continue; + break; case MenuChoices.Update: CodingTrackerController.UpdateRecord(); + + if (!Helper.Confirmation("Proceed with this operation? (No will return to the main menu)")) + continue; + break; case MenuChoices.Delete: + + if (!Helper.Confirmation("Proceed with this operation? (No will return to the main menu)")) + continue; + CodingTrackerController.DeleteRecord(); break; } From f4b93f96a3223611d224145ec510e83fc3bb4b62 Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sun, 25 Jan 2026 14:05:06 +0800 Subject: [PATCH 12/14] add readme file --- CodingTracker.Kaylubr/Enums/MenuChoices.cs | 9 +++++---- CodingTracker.Kaylubr/Views/UserInterface.cs | 11 +++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CodingTracker.Kaylubr/Enums/MenuChoices.cs b/CodingTracker.Kaylubr/Enums/MenuChoices.cs index 57a97421..a59f91fa 100644 --- a/CodingTracker.Kaylubr/Enums/MenuChoices.cs +++ b/CodingTracker.Kaylubr/Enums/MenuChoices.cs @@ -2,8 +2,9 @@ namespace CodingTracker.Enums; internal enum MenuChoices { - View, - Insert, - Update, - Delete + View, + Insert, + Update, + Delete, + Exit } \ No newline at end of file diff --git a/CodingTracker.Kaylubr/Views/UserInterface.cs b/CodingTracker.Kaylubr/Views/UserInterface.cs index 2e59485c..dfe024b8 100644 --- a/CodingTracker.Kaylubr/Views/UserInterface.cs +++ b/CodingTracker.Kaylubr/Views/UserInterface.cs @@ -25,20 +25,23 @@ internal static void Run() case MenuChoices.View: CodingTrackerController.LogAllRecords(); break; + case MenuChoices.Insert: - CodingTrackerController.InsertSession(); if (!Helper.Confirmation("Proceed with this operation? (No will return to the main menu)")) continue; + CodingTrackerController.InsertSession(); break; + case MenuChoices.Update: - CodingTrackerController.UpdateRecord(); if (!Helper.Confirmation("Proceed with this operation? (No will return to the main menu)")) continue; + CodingTrackerController.UpdateRecord(); break; + case MenuChoices.Delete: if (!Helper.Confirmation("Proceed with this operation? (No will return to the main menu)")) @@ -46,6 +49,10 @@ internal static void Run() CodingTrackerController.DeleteRecord(); break; + case MenuChoices.Exit: + AnsiConsole.WriteLine("\nExiting.."); + Environment.Exit(0); + break; } } } From e2e505d24f44ff3ca040388969104ea92d114e76 Mon Sep 17 00:00:00 2001 From: kaylubr Date: Sun, 25 Jan 2026 14:05:13 +0800 Subject: [PATCH 13/14] add readme file --- README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..e69de29b From 064bbc3b05a8c27d40657179d079d2949dcb0392 Mon Sep 17 00:00:00 2001 From: Kyle Benedict Reyes Date: Sun, 25 Jan 2026 14:31:50 +0800 Subject: [PATCH 14/14] Update readme --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/README.md b/README.md index e69de29b..ea30f115 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,42 @@ +# Coding Tracker Console App + +A simple console-based coding session tracker built with **.NET**, **Dapper**, **Microsoft.Extensions.Configuration**, **Microsoft.Data.Sqlite**, and **Spectre.Console**. The app allows you to **view, add, edit, and delete** coding sessions in a lightweight SQLite database with a clean console interface. +I like this project because I feel like I had better grasp on OOP and patterns like DRY and KISS + +--- + +## Features + +- Add new coding sessions with start and end times +- View all recorded sessions in a formatted console table +- Edit existing sessions directly from the console +- Delete sessions when needed +- Uses **Spectre.Console** for a colorful and user-friendly terminal UI +- Configuration handled via **Microsoft.Extensions.Configuration** for flexible database and app settings + +--- + +## Challenges + +One thing that really frustrated me was how **Dapper maps values** from the database to C# objects. + +At first, I named my columns `start_time` and `end_time`. When I tried to render them, Dapper didn’t automatically convert them into `DateTime` even though the types were declared in `models/CodingSession.cs`. The issue was that Dapper maps columns to properties **by name**, and I was sticking to C#’s PascalCase naming convention instead of the database’s snake_case convention. + +The fix was simple: rename the columns to `StartTime` and `EndTime` to match the property names in my model. Once that was done, Dapper handled the mapping perfectly. + +--- + +## Lessons Learned + +- **Dapper is incredibly convenient**. You don’t need to manually open or close the database connection, and retrieving rows into a list is simple using Dapper’s built-in methods +- Keeping column names and model property names consistent is crucial for smooth mapping +- **Spectre.Console** makes even simple console apps feel interactive and polished + +--- + +## Resources Used + +- [Dapper Documentation](https://dapper-tutorial.net/) +- [Microsoft.Data.Sqlite](https://learn.microsoft.com/en-us/dotnet/standard/data/sqlite/) +- [Microsoft.Extensions.Configuration](https://learn.microsoft.com/en-us/dotnet/core/extensions/configuration) +- [Spectre.Console](https://spectreconsole.net/)