diff --git a/CodingTracker/CodingTracker.sln b/CodingTracker/CodingTracker.sln new file mode 100644 index 00000000..0fef2785 --- /dev/null +++ b/CodingTracker/CodingTracker.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35707.178 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodingTracker", "CodingTracker\CodingTracker.csproj", "{03120830-35AE-49F7-AC34-1EDC2B3F8ACF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {03120830-35AE-49F7-AC34-1EDC2B3F8ACF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03120830-35AE-49F7-AC34-1EDC2B3F8ACF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03120830-35AE-49F7-AC34-1EDC2B3F8ACF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03120830-35AE-49F7-AC34-1EDC2B3F8ACF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/CodingTracker/CodingTracker/App.config b/CodingTracker/CodingTracker/App.config new file mode 100644 index 00000000..71516352 --- /dev/null +++ b/CodingTracker/CodingTracker/App.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/CodingTracker/CodingTracker/CodingTracker.csproj b/CodingTracker/CodingTracker/CodingTracker.csproj new file mode 100644 index 00000000..ffff1342 --- /dev/null +++ b/CodingTracker/CodingTracker/CodingTracker.csproj @@ -0,0 +1,17 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + diff --git a/CodingTracker/CodingTracker/CodingTracker.db b/CodingTracker/CodingTracker/CodingTracker.db new file mode 100644 index 00000000..db8c178b Binary files /dev/null and b/CodingTracker/CodingTracker/CodingTracker.db differ diff --git a/CodingTracker/CodingTracker/Controllers/CodingSessionController.cs b/CodingTracker/CodingTracker/Controllers/CodingSessionController.cs new file mode 100644 index 00000000..cb2afe27 --- /dev/null +++ b/CodingTracker/CodingTracker/Controllers/CodingSessionController.cs @@ -0,0 +1,101 @@ +using CodingTracker.Models; +using Dapper; +using Microsoft.Data.Sqlite; +using System.Configuration; + +namespace CodingTracker.Controllers; + +internal class CodingSessionController +{ + protected readonly string _connectionString = ConfigurationManager.AppSettings.Get("Connectionstring") ?? throw new Exception("Key value pair doesn't exist in the config-file!"); + + public List GetAll() + { + using (var connection = new SqliteConnection(_connectionString)) + { + string query = "SELECT * FROM CodingSession"; + + connection.Open(); + + return connection.Query(query).ToList(); + } + } + + public CodingSession GetById(int id) + { + using (var connection = new SqliteConnection(_connectionString)) + { + string query = "SELECT * FROM CodingSession WHERE Id = @Id"; + + connection.Open(); + + return connection.Query(query, new { Id = id }).First(); + } + } + + /// + /// Returns the number of rows affected + /// + /// + /// + public int Add(CodingSession codingSession) + { + using (var connection = new SqliteConnection(_connectionString)) + { + string sql = "INSERT INTO CodingSession (StartTime, EndTime, Duration) VALUES (@StartTime, @EndTime, @Duration)"; + + connection.Open(); + + return connection.Execute(sql, codingSession); + } + } + + /// + /// Returns the number of rows affected + /// + /// + /// + public int Update(CodingSession codingSession) + { + using (var connection = new SqliteConnection(_connectionString)) + { + string sql = "UPDATE CodingSession SET StartTime = @StartTime, EndTime = @EndTime, Duration = @Duration WHERE id = @Id"; + + connection.Open(); + + return connection.Execute(sql, codingSession); + } + } + + /// + /// Returns the number of rows affected + /// + /// + /// + public int Delete(int id) + { + using (var connection = new SqliteConnection(_connectionString)) + { + string sql = "DELETE FROM CodingSession WHERE id = @Id"; + + connection.Open(); + + return connection.Execute(sql, new { Id = id}); + } + } + + internal bool Exists(int id) + { + using (var connection = new SqliteConnection(_connectionString)) + { + string sql = "SELECT * FROM CodingSession WHERE id = @Id"; + + connection.Open(); + + var reader = connection.ExecuteScalar(sql, new { Id = id }); + + return reader != null; + } + + } +} diff --git a/CodingTracker/CodingTracker/Database.cs b/CodingTracker/CodingTracker/Database.cs new file mode 100644 index 00000000..d72b8188 --- /dev/null +++ b/CodingTracker/CodingTracker/Database.cs @@ -0,0 +1,35 @@ +using Microsoft.Data.Sqlite; +using System.Configuration; + +namespace CodingTracker; + +internal static class Database +{ + private static readonly string _connectionString = ConfigurationManager.AppSettings.Get("Connectionstring") ?? + throw new Exception("Key value pair doesn't exist in the config-file!"); + + private static readonly string _databasePath = ConfigurationManager.AppSettings.Get("DatabasePath") ?? + throw new Exception("Key value pair doesn't exist in the config-file!"); + internal static void CreateDatabase() + { + if (!File.Exists(_databasePath)) + { + using (SqliteConnection connection = new SqliteConnection(_connectionString)) + { + connection.Open(); + + var command = connection.CreateCommand(); + command.CommandText = + @"CREATE TABLE CodingSession + ( + Id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + StartTime TEXT NOT NULL, + EndTime TEXT NOT NULL, + Duration INTEGER NOT NULL + )"; + + command.ExecuteNonQuery(); + } + } + } +} diff --git a/CodingTracker/CodingTracker/Enums/MenuItems.cs b/CodingTracker/CodingTracker/Enums/MenuItems.cs new file mode 100644 index 00000000..390b4577 --- /dev/null +++ b/CodingTracker/CodingTracker/Enums/MenuItems.cs @@ -0,0 +1,11 @@ +namespace CodingTracker.Enums; + +internal enum MenuItems +{ + StartCodingSession, + ViewAll, + Add, + Update, + Delete, + Quit +} diff --git a/CodingTracker/CodingTracker/Models/CodingSession.cs b/CodingTracker/CodingTracker/Models/CodingSession.cs new file mode 100644 index 00000000..50c6e9ff --- /dev/null +++ b/CodingTracker/CodingTracker/Models/CodingSession.cs @@ -0,0 +1,9 @@ +namespace CodingTracker.Models; + +internal class CodingSession +{ + public int Id { get; set; } + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public double Duration { get; set; } +} diff --git a/CodingTracker/CodingTracker/Program.cs b/CodingTracker/CodingTracker/Program.cs new file mode 100644 index 00000000..9ea0ee5b --- /dev/null +++ b/CodingTracker/CodingTracker/Program.cs @@ -0,0 +1,7 @@ +using CodingTracker; +using CodingTracker.UserInterface; + +Database.CreateDatabase(); + +UserMenu userMenu = new UserMenu(); +userMenu.ShowMenu(); diff --git a/CodingTracker/CodingTracker/Properties/launchSettings.json b/CodingTracker/CodingTracker/Properties/launchSettings.json new file mode 100644 index 00000000..09130bf4 --- /dev/null +++ b/CodingTracker/CodingTracker/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "CodingTracker": { + "commandName": "Project", + "workingDirectory": "C:\\Users\\gilles.lagrilliere\\OneDrive - Codraft\\Documents\\C#-projects\\CodeReviews.Console.CodingTracker\\CodingTracker\\CodingTracker" + } + } +} \ No newline at end of file diff --git a/CodingTracker/CodingTracker/UserInterface/UserInput.cs b/CodingTracker/CodingTracker/UserInterface/UserInput.cs new file mode 100644 index 00000000..79d40441 --- /dev/null +++ b/CodingTracker/CodingTracker/UserInterface/UserInput.cs @@ -0,0 +1,159 @@ +using CodingTracker.Controllers; +using CodingTracker.Models; +using Spectre.Console; +using System.Diagnostics; + +namespace CodingTracker.UserInterface; + +internal static class UserInput +{ + private static readonly CodingSessionController _controller = new CodingSessionController(); + public static void ViewAll() + { + var AllCodingSessions = _controller.GetAll(); + + PrintCodingSessions(AllCodingSessions); + + Console.WriteLine("Press any key to continue"); + Console.ReadKey(); + } + + public static void Add() + { + var session = AskForInput(); + + _controller.Add(session); + } + + public static void Update() + { + var AllCodingSessions = _controller.GetAll(); + + PrintCodingSessions(AllCodingSessions); + + int id; + do + { + id = AnsiConsole.Ask("Choose the [yellow]Id[/] of a session to update."); + } + while (!_controller.Exists(id)); + + var session = AskForInput(); + session.Id = id; + + _controller.Update(session); + } + + public static void Delete() + { + var AllCodingSessions = _controller.GetAll(); + + PrintCodingSessions(AllCodingSessions); + int id; + + do + { + id = AnsiConsole.Ask("Choose a valid [yellow]Id[/] of a session to delete."); + } + while (!_controller.Exists(id)); + + _controller.Delete(id); + } + + public static void StartCodingSession() + { + Console.WriteLine("press any key to start the session"); + Console.ReadKey(true); + + Stopwatch stopwatch = Stopwatch.StartNew(); + stopwatch.Start(); + + var startTime = DateTime.Now; + startTime = new DateTime( + startTime.Ticks - (startTime.Ticks % TimeSpan.TicksPerSecond), + startTime.Kind + ); + + Console.WriteLine("press enter to stop the session"); + + ConsoleKeyInfo input; + do + { + input = Console.ReadKey(); + } + while (input.Key is not ConsoleKey.Enter); + + stopwatch.Stop(); + var endTime = DateTime.Now; + endTime = new DateTime( + endTime.Ticks - (endTime.Ticks % TimeSpan.TicksPerSecond), + endTime.Kind + ); + + var duration = new TimeSpan(stopwatch.Elapsed.Ticks / TimeSpan.TicksPerSecond * TimeSpan.TicksPerSecond); //truncate the milliseconds + + string elapsedTime = $"{duration.Hours:00}:{duration.Minutes:00}:{duration.Seconds:00}"; + Console.WriteLine("Codingtime: " + elapsedTime); + Console.ReadKey(); + + var session = new CodingSession() + { + StartTime = startTime, + EndTime = endTime, + Duration = duration.TotalSeconds + }; + + _controller.Add(session); + } + + private static string ConvertDateToString(DateTime date) + { + return date.ToString("dd-MM-yyyy HH:mm"); + } + + private static string ConvertTimeSpanToString(double duration) + { + return TimeSpan.FromSeconds(duration).ToString(); + } + + private static void PrintCodingSessions(List sessions) + { + var table = new Table(); + table.AddColumns("Id", "StartTime", "EndTime", "Duration"); + + foreach (var session in sessions) + { + var startTime = ConvertDateToString(session.StartTime); + var endTime = ConvertDateToString(session.EndTime); + var duration = ConvertTimeSpanToString(session.Duration); + + table.AddRow([session.Id.ToString(), startTime, endTime, duration]); + } + + AnsiConsole.Write(table); + } + + private static CodingSession AskForInput() + { + var startTime = AnsiConsole.Ask("What time did you start(mm-dd-yyyy hh:mm): "); + var endTime = AnsiConsole.Ask("What time did you end(mm-dd-yyyy hh:mm): "); + while (DateTime.Compare(startTime, endTime) > 0) + { + Console.WriteLine("EndTime can not be before the starttime."); + endTime = AnsiConsole.Ask("What time did you end(mm-dd-yyyy hh:mm): "); + } + + var duration = endTime - startTime; + + CodingSession session = new CodingSession() + { + StartTime = startTime, + EndTime = endTime, + Duration = duration.TotalSeconds + }; + + return session; + } + + +} diff --git a/CodingTracker/CodingTracker/UserInterface/UserMenu.cs b/CodingTracker/CodingTracker/UserInterface/UserMenu.cs new file mode 100644 index 00000000..0dcd2917 --- /dev/null +++ b/CodingTracker/CodingTracker/UserInterface/UserMenu.cs @@ -0,0 +1,62 @@ +using CodingTracker.Controllers; +using CodingTracker.Enums; +using Spectre.Console; + +namespace CodingTracker.UserInterface; + +internal class UserMenu +{ + private CodingSessionController _controller = new CodingSessionController(); + public void ShowMenu() + { + while (true) + { + Console.Clear(); + + var choice = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Pick an option") + .AddChoices(Enum.GetValues())); + + switch (choice) + { + case MenuItems.StartCodingSession: + ClearConsole(); + UserInput.StartCodingSession(); + break; + + case MenuItems.ViewAll: + ClearConsole(); + UserInput.ViewAll(); + break; + + case MenuItems.Add: + ClearConsole(); + UserInput.Add(); + break; + + case MenuItems.Update: + ClearConsole(); + UserInput.Update(); + break; + + case MenuItems.Delete: + ClearConsole(); + UserInput.Delete(); + break; + + case MenuItems.Quit: + Environment.Exit(0); + break; + + default: + break; + } + } + } + + private void ClearConsole() + { + Console.Clear(); + } +}