Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions CodingTracker.urasylmaz1/CodingTracker.urasylmaz1.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<None Remove="appsettings.json" />
</ItemGroup>

<ItemGroup>
<Content Include="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.72" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.7" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.7" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.7" />
<PackageReference Include="Spectre.Console" Version="0.55.2" />
</ItemGroup>

</Project>
3 changes: 3 additions & 0 deletions CodingTracker.urasylmaz1/CodingTracker.urasylmaz1.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Solution>
<Project Path="CodingTracker.urasylmaz1.csproj" />
</Solution>
150 changes: 150 additions & 0 deletions CodingTracker.urasylmaz1/Controllers/CodingController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
using CodingTracker.urasylmaz1.Helpers;
using CodingTracker.urasylmaz1.Models;
using Dapper;
using Microsoft.Data.Sqlite;
using Spectre.Console;
using System;
using System.Collections.Generic;
using System.Text;

namespace CodingTracker.urasylmaz1.Controllers
{
public class CodingController
{
private readonly string _connectionString;
public CodingController(string connectionString)
{
_connectionString = connectionString;
}

public void Run()
{
bool running = true;

while (running)
{
Console.Clear();

var choice = AnsiConsole.Prompt(
new SelectionPrompt<string>()
.Title("[green]Coding Tracker[/]")
.AddChoices(
"Add Session",
"View Sessions",
"Delete Session",
"Exit"
)
);

switch (choice)
{
case "Add Session":
AddSession();
break;

case "View Sessions":
ReadSession();
break;

case "Delete Session":
RemoveSession();
break;

case "Exit":
running = false;
break;
}

if (running)
{
AnsiConsole.MarkupLine(
"\n[yellow]Press any key to continue...[/]"
);

Console.ReadKey();
}
}
}

public void AddSession()
{
DateTime start =
UserInput.GetDateTime(
"Enter start time (yyyy-MM-dd HH:mm):"
);

DateTime end =
UserInput.GetDateTime(
"Enter end time (yyyy-MM-dd HH:mm):"
);

string duration = (end - start).ToString();

CodingSession session = new()
{
StartTime = start,
EndTime = end,
Duration = duration
};

using var connection =
new SqliteConnection(_connectionString);

string sql = @"
INSERT INTO CodingSessions
(StartTime, EndTime, Duration)
VALUES
(@StartTime, @EndTime, @Duration)
";

connection.Execute(sql, session);
}

public void ReadSession()
{
using var connection = new SqliteConnection(_connectionString);
List<CodingSession> sessions = connection.Query<CodingSession>("SELECT * FROM CodingSessions").AsList();
var table = new Table();

table.AddColumn("Id");
table.AddColumn("Start Time");
table.AddColumn("End Time");
table.AddColumn("Duration");

foreach (var session in sessions)
{
table.AddRow(
session.Id.ToString(),
session.StartTime.ToString(),
session.EndTime.ToString(),
session.Duration.ToString()
);
}

AnsiConsole.Write(table);
}

public void RemoveSession()
{
ReadSession();

int id = AnsiConsole.Ask<int>("Enter session Id to delete:");

bool exists = Validation.SessionExists(_connectionString, id );

if (!exists)
{
AnsiConsole.MarkupLine("[red]Session not found.[/]" );
return;
}

using var connection = new SqliteConnection(_connectionString);

string sql ="DELETE FROM CodingSessions WHERE Id = @Id";

connection.Execute(sql, new { Id = id });

AnsiConsole.MarkupLine("[green]Session deleted.[/]");
}
}
}
38 changes: 38 additions & 0 deletions CodingTracker.urasylmaz1/Data/Database.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Dapper;
using Microsoft.Data.Sqlite;
using System;
using System.Collections.Generic;
using System.Text;

namespace CodingTracker.urasylmaz1.Data
{
public class Database
{
private readonly string _connectionString;
public Database(string connectionString)
{
_connectionString = connectionString;
}

public void Initialize()
{
// using Dapper instead of raw ADO.NET for simplicity

using var connection =
new SqliteConnection(_connectionString);

string sql = @"
CREATE TABLE IF NOT EXISTS CodingSessions
(
Id INTEGER PRIMARY KEY AUTOINCREMENT,
StartTime TEXT,
EndTime TEXT,
Duration TEXT
);
";

connection.Execute(sql);
}

}
}
36 changes: 36 additions & 0 deletions CodingTracker.urasylmaz1/Helpers/UserInput.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Spectre.Console;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;

namespace CodingTracker.urasylmaz1.Helpers
{
public class UserInput
{
public static DateTime GetDateTime(string message)
{
while (true)
{
string input = AnsiConsole.Ask<string>(message);

if (Validation.IsValidDateTime(input))
{
return DateTime.ParseExact(
input,
"yyyy-MM-dd HH:mm",
null
);
}

AnsiConsole.MarkupLine(
"[red]Invalid format![/]"
);

AnsiConsole.MarkupLine(
"[yellow]Use format: yyyy-MM-dd HH:mm[/]"
);
}
}
}
}
27 changes: 27 additions & 0 deletions CodingTracker.urasylmaz1/Helpers/Validation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using CodingTracker.urasylmaz1.Models;
using Dapper;
using Microsoft.Data.Sqlite;
using System;
using System.Collections.Generic;
using System.Text;

namespace CodingTracker.urasylmaz1.Helpers
{
public class Validation
{
public static bool IsValidDateTime(string input)
{
return DateTime.TryParseExact(input, "yyyy-MM-dd HH:mm", null, System.Globalization.DateTimeStyles.None, out _); // TryParseExact returns true if parsing is successful, false otherwise
}
public static bool SessionExists(string connectionString, int id)
{
using var connection = new SqliteConnection(connectionString);

string sql ="SELECT * FROM CodingSessions WHERE Id = @Id";

var session = connection.QuerySingleOrDefault<CodingSession>(sql,new { Id = id } );

return session != null;
}
}
}
17 changes: 17 additions & 0 deletions CodingTracker.urasylmaz1/Models/CodingSession.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace CodingTracker.urasylmaz1.Models
{
public class CodingSession
{
public int Id { get; set; }

public DateTime StartTime { get; set; }

public DateTime EndTime { get; set; }

public string Duration { get; set; } = string.Empty;
}
}
33 changes: 33 additions & 0 deletions CodingTracker.urasylmaz1/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using CodingTracker.urasylmaz1.Controllers;
using CodingTracker.urasylmaz1.Data;
using Microsoft.Extensions.Configuration;

namespace CodingTracker.urasylmaz1
{
class Program
{

static void Main(string[] args)
{

var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
string? connectionString = config.GetConnectionString("DefaultConnection");

if (string.IsNullOrWhiteSpace(connectionString))
{
Console.WriteLine("Connection string missing.");
return;
}

Database db = new(connectionString);

db.Initialize();

CodingController controller = new(connectionString);

controller.Run();
}
}
}
5 changes: 5 additions & 0 deletions CodingTracker.urasylmaz1/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=codingtracker.db"
}
}
Loading