Skip to content
Open

Done #284

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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -478,3 +478,6 @@ $RECYCLE.BIN/
*.lnk
/MathGame2
/CodingTracker.TomDonegan/TextFile1.txt

# DB
*.db
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Coding Tracker
Simple coding tracker build with C#, SQLite, and Spectre.Console!

## Features
- SQLite database
- Nice-looking console interface with Spectre.Console
- Record coding sessions by custom time
- Record coding sessions live with a stopwatch

## Running the App

1. Clone the repo
2. Make sure they required libraries are downloaded
```
dotnet add package Dapper
dotnet add package Microsoft.Data.Sqlite
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Json
```
3. Run the app
```
dotnet run
```

## Architectural Choices

- Classes were organized in 3 directories:
- `Models`: For database entities
- `Data`: For data access
- Tried to make 1 unified data access class with all the CRUD methods.
- `Helpers` For general helpers

## Experience

Definitely learned a lot about how to read the docs for an external library, and how it integrates with the base language in apps.

One of the challenges I faced was how to use Dapper with dates considering how SQLite does not have a DATETIME data type, which makes it always stored as TEXT.

I had to write an extension method of sorts to it, but i still need to revisit that.
24 changes: 24 additions & 0 deletions Tenebris-06.CodingTracker/CodingTracker.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

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

<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.79" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.11" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.11" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.11" />
<PackageReference Include="Spectre.Console" Version="0.57.2" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
72 changes: 72 additions & 0 deletions Tenebris-06.CodingTracker/Data/DataAccess.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System.Collections.Immutable;
using Microsoft.Data.Sqlite;
using Dapper;

public class DataAccess
{
string _ConnectionString;

public DataAccess(string Connectionstring)
{
_ConnectionString = Connectionstring;
}

public void Initialize()
{
using var connection = new SqliteConnection(_ConnectionString);
connection.Open();

connection.Execute("""
CREATE TABLE IF NOT EXISTS CodingSessions(
Id INTEGER PRIMARY KEY AUTOINCREMENT,
StartTime TEXT NOT NULL,
EndTime TEXT NOT NULL,
Duration TEXT NOT NULL,
Description TEXT)
""");
}

public void CreateSession(Session session)
{
var sql = """
INSERT INTO CodingSessions (StartTime, EndTime, Duration, Description)
VALUES (@StartTime, @EndTime, @Duration, @Description)
""";
using var connection = new SqliteConnection(_ConnectionString);
connection.Execute(sql, session);
}

public void DeleteSession(int SessionId)
{
var sql = """
DELETE FROM CodingSessions WHERE Id = @Id
""";
using var connection = new SqliteConnection(_ConnectionString);
connection.Execute(sql, new {Id = SessionId});
}

public void UpdateSession(Session session)
{
var sql = """
UPDATE CodingSessions
SET StartTime = @StartTime, EndTime = @EndTime,
Duration = @Duration, Description = @Description
WHERE
Id = @Id
""";
using var connection = new SqliteConnection(_ConnectionString);
connection.Execute(sql, session);
}

public List<Session> ReadSessions()
{
var sql = """
SELECT * FROM CodingSessions
""";
using var connection = new SqliteConnection(_ConnectionString);

var sessions = connection.Query<Session>(sql);

return sessions.ToList();
}
}
23 changes: 23 additions & 0 deletions Tenebris-06.CodingTracker/Helpers/DateTimeHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Globalization;
using System.Security.Cryptography.X509Certificates;
using Spectre.Console;

public static class DateTimeHelper{
public static bool TryGetDateTime(string input, out DateTime result)
{
if (string.IsNullOrWhiteSpace(input))
{
result = DateTime.Now;
return true;
}

return DateTime.TryParseExact(
input,
"yyyy-MM-dd HH:mm:ss",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out result
);
}

}
15 changes: 15 additions & 0 deletions Tenebris-06.CodingTracker/Helpers/TimeSpanHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Data;
using Dapper;

public class TimeSpanHandler : SqlMapper.TypeHandler<TimeSpan>
{
public override void SetValue(IDbDataParameter parameter, TimeSpan value)
{
parameter.Value = value.ToString(@"hh\:mm\:ss");
}

public override TimeSpan Parse(object value)
{
return TimeSpan.Parse(value.ToString()!);
}
}
8 changes: 8 additions & 0 deletions Tenebris-06.CodingTracker/Models/Session.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
public class Session
{
public int Id { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public TimeSpan Duration { get; set; }
public string? Description { get; set; }
}
24 changes: 24 additions & 0 deletions Tenebris-06.CodingTracker/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using Dapper;
using Microsoft.Extensions.Configuration;
using Spectre.Console;

class Program {
static void Main(string[] args)
{

SqlMapper.AddTypeHandler(new TimeSpanHandler());

var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json")
.Build();

DataAccess db = new DataAccess(configuration["Database:ConnectionString"]);
db.Initialize();

var UI = new Menu(db);
UI.MainMenu();

}
}
24 changes: 24 additions & 0 deletions Tenebris-06.CodingTracker/Services/SessionService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
public class SessionService
{
public DateTime startTime;
public void StartSession()
{
startTime = DateTime.Now;
}

public Session EndSession()
{
DateTime endTime = DateTime.Now;
return new Session
{
StartTime = startTime,
EndTime = endTime,
Duration = endTime - startTime
};
}

public TimeSpan GetElapsedTime()
{
return DateTime.Now - startTime;
}
}
Loading