diff --git a/README.md b/README.md
new file mode 100644
index 00000000..c2f17bd1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,42 @@
+## Console Habit Tracker ##
+
+This is my first CRUD application! It tracks whatever the user wants to track!
+
+Made with C# and SQLite.
+
+## Requirements 🗒️ ##
+
+- Users need to be able to input the date of the occurrence of the habit
+
+- The application should store and retrieve data from a real database
+
+- When the application starts, it should create a sqlite database, if one isn’t present.
+
+- It should also create a table in the database, where the habit will be logged.
+
+- The users should be able to insert, delete, update and view their logged habit.
+
+- You should handle all possible errors so that the application never crashes.
+
+- You can only interact with the database using ADO.NET. You can’t use mappers such as Entity Framework or Dapper.
+
+## Features đź§¶ ##
+
+- SQLite connection to store and read information. If the database does not exist, the program creates one on start.
+
+- Console based UI to navigate by user input
+
+
+- Users can Create, Read, Update or Delete entries :D
+
+## Challenges & Lessons đź’˝##
+
+- This was the first time I integrated a database to a program! I already knew SQL and some C#, but I've mostly worked with Python. It was fun to learn how to use a SQL connection on my program, and the C# documentation was really useful.
+
+- I've tried to organize my code with methods, but I only made it more complicated to read. So I tried to use the KISS and DRY methodology to keep it simple and make it easier to understand.
+
+## Areas to Improve đź“”#
+
+- Make the tables more user-friendly when printed!
+
+- Organize the code better
\ No newline at end of file
diff --git a/image.png b/image.png
new file mode 100644
index 00000000..57f6c816
Binary files /dev/null and b/image.png differ
diff --git a/project/Program.cs b/project/Program.cs
new file mode 100644
index 00000000..b97808b6
--- /dev/null
+++ b/project/Program.cs
@@ -0,0 +1,394 @@
+using System.IO;
+using Microsoft.Data.Sqlite;
+using SQLitePCL;
+
+void Main() {
+ bool play = true;
+ string idStr = "";
+ int idHabit = 0;
+ string answer = "";
+
+ CreateDatabase();
+ Console.Clear();
+
+ while (play)
+ {
+ switch (Options())
+ {
+ case 1: // create
+ CreateInput();
+ break;
+ case 2: // read
+ ReadTable();
+ break;
+ case 3: // update
+ idStr = "";
+ idHabit = 0;
+
+ while(!int.TryParse(idStr, out idHabit))
+ {
+ System.Console.WriteLine();
+ System.Console.WriteLine("Input Habit ID to check: ");
+ idStr = Console.ReadLine();
+ System.Console.WriteLine();
+ }
+ CheckRow(idHabit);
+ System.Console.WriteLine();
+ System.Console.WriteLine("Is that correct? (y/n)");
+ answer = Console.ReadLine().Trim().ToLower();
+ System.Console.WriteLine();
+ if (answer == "y")
+ {
+ UpdateRow(idHabit);
+ System.Console.WriteLine();
+ System.Console.WriteLine("Row updated!");
+ System.Console.WriteLine("Press Enter to continue.");
+ Console.ReadKey();
+ }
+ break;
+ case 4: // delete
+ idStr = "";
+ idHabit = 0;
+
+ while(!int.TryParse(idStr, out idHabit))
+ {
+ System.Console.WriteLine();
+ System.Console.WriteLine("Input Habit ID to check: ");
+ idStr = Console.ReadLine();
+ System.Console.WriteLine();
+ }
+ CheckRow(idHabit);
+ System.Console.WriteLine();
+ System.Console.WriteLine("Is that correct? (y/n)");
+ answer = Console.ReadLine().Trim().ToLower();
+ System.Console.WriteLine();
+ if (answer == "y")
+ {
+ DeleteRow(idHabit);
+ System.Console.WriteLine();
+ System.Console.WriteLine("Row deleted!");
+ System.Console.WriteLine("Press Enter to continue.");
+ Console.ReadKey();
+ }
+
+ break;
+ case 5: // exit
+ play = false;
+ break;
+
+ }
+ System.Console.WriteLine();
+ }
+
+ System.Console.WriteLine("Exiting now. See you later!");
+ System.Console.WriteLine();
+ Environment.Exit(0);
+}
+
+int Options()
+{
+ string userAnswer = "";
+ int option = 0;
+
+ System.Console.WriteLine("**** Options ****");
+ System.Console.WriteLine("1) Create ........");
+ System.Console.WriteLine("2) Read ..........");
+ System.Console.WriteLine("3) Update ........");
+ System.Console.WriteLine("4) Delete ........");
+ System.Console.WriteLine("5) Exit ..........");
+ System.Console.WriteLine();
+
+ while (!int.TryParse(userAnswer, out option) && option < 1 || option > 5)
+ {
+ userAnswer = Console.ReadLine();
+ System.Console.WriteLine();
+ }
+
+ return option;
+}
+
+void CreateDatabase()
+{
+ string connectionStr = $"Data Source=habits.db";
+
+ Batteries.Init();
+ using var connection = new SqliteConnection(connectionStr);
+ connection.Open();
+
+ var createTable = @"
+ CREATE TABLE IF NOT EXISTS Habits(
+ Id INTEGER PRIMARY KEY AUTOINCREMENT,
+ Habit TEXT NOT NULL,
+ Quantity INTEGER NOT NULL,
+ Date TEXT
+ );";
+
+ using (var command = new SqliteCommand(createTable, connection))
+ {
+ command.ExecuteNonQuery();
+ }
+
+ connection.Close();
+}
+
+void CreateRow(string habit, int quantity, DateOnly date)
+{
+ string connectionStr = $"Data Source=habits.db";
+
+ Batteries.Init();
+ using var connection = new SqliteConnection(connectionStr);
+ connection.Open();
+
+ var createInput = $"""
+ INSERT OR IGNORE INTO Habits(Habit, Quantity, Date)
+ VALUES ('{habit}', '{quantity}', '{date.ToString()}');
+ """;
+
+ using (var command = new SqliteCommand(createInput, connection))
+ {
+ command.ExecuteNonQuery();
+ }
+
+ connection.Close();
+}
+
+void CheckRow(int id)
+{
+ string connectionStr = $"Data Source=habits.db";
+
+ Batteries.Init();
+ using var connection = new SqliteConnection(connectionStr);
+ connection.Open();
+
+ using var command = connection.CreateCommand();
+ command.CommandText = $"""
+ SELECT Id,
+ Habit,
+ Quantity,
+ Date
+ FROM Habits
+ WHERE Id = {id};
+ """;
+ using var reader = command.ExecuteReader();
+
+ System.Console.WriteLine("** You Selected: **");
+ while (reader.Read())
+ {
+ var habitId = reader.GetString(0);
+ var habitName = reader.GetString(1);
+ var habitQuantity = reader.GetString(2);
+ var habitDate = reader.GetString(3);
+
+ Console.WriteLine($"ID: {habitId} - HABIT: {habitName} - QUANTITY: {habitQuantity} - DATE: {habitDate}");
+ }
+
+ connection.Close();
+}
+
+void DeleteRow(int id)
+{
+ string connectionStr = $"Data Source=habits.db";
+
+ Batteries.Init();
+ using var connection = new SqliteConnection(connectionStr);
+ connection.Open();
+
+ var createInput = $"""
+ DELETE FROM Habits
+ WHERE Id = {id};
+ """;
+
+ using (var command = new SqliteCommand(createInput, connection))
+ {
+ command.ExecuteNonQuery();
+ }
+
+ connection.Close();
+}
+
+void UpdateRow(int id)
+{
+ string connectionStr = $"Data Source=habits.db";
+
+ Batteries.Init();
+ using var connection = new SqliteConnection(connectionStr);
+ connection.Open();
+
+ string answer = "";
+ int answerInt = 0;
+ string column = "";
+ string value = "";
+
+ string quantityStr = "";
+ int quantity = 0;
+ DateOnly date;
+ string dateStr = "";
+
+
+ while (!int.TryParse(answer, out answerInt) || answerInt < 1 || answerInt > 3)
+ {
+ System.Console.WriteLine("Which value would you like to update?");
+ System.Console.WriteLine("1) Habit name ....................");
+ System.Console.WriteLine("2) Habit quantity ................");
+ System.Console.WriteLine("3) Habit date ....................");
+ System.Console.WriteLine();
+ answer = Console.ReadLine();
+ int.TryParse(answer, out answerInt);
+
+ System.Console.WriteLine();
+ }
+
+ switch (answerInt)
+ {
+ case 1:
+ column = "Habit";
+ System.Console.WriteLine("Input the new name");
+ System.Console.WriteLine();
+ value = Console.ReadLine();
+ break;
+ case 2:
+ column = "Quantity";
+ while (!int.TryParse(quantityStr, out quantity)){
+ System.Console.WriteLine("Input the new quantity");
+ System.Console.WriteLine();
+ quantityStr = Console.ReadLine();
+ }
+ value = quantity.ToString();
+ break;
+ case 3:
+ column = "Date";
+ while (!DateOnly.TryParse(dateStr, out date) || dateStr.ToLower().Trim() != "today" ){
+ System.Console.WriteLine("Input the new date");
+ System.Console.WriteLine();
+ dateStr = Console.ReadLine();
+ if (dateStr.ToLower().Trim() == "today") {
+ dateStr = DateTime.Today.ToString();
+ break;
+ }
+ }
+ value = date.ToString();
+ break;
+ }
+
+
+ var createInput = $"""
+ UPDATE Habits
+ SET {column} = {value}
+ WHERE Id = {id};
+ """;
+
+ using (var command = new SqliteCommand(createInput, connection))
+ {
+ command.ExecuteNonQuery();
+ }
+
+ connection.Close();
+}
+
+void ReadTable()
+{
+ System.Console.WriteLine("** YOUR HABITS **");
+
+ using var connection = new SqliteConnection("Data Source=habits.db");
+ connection.Open();
+
+ using var command = connection.CreateCommand();
+ command.CommandText = """
+ SELECT Id,
+ Habit,
+ Quantity,
+ Date
+ FROM Habits
+ """;
+ using var reader = command.ExecuteReader();
+
+ while (reader.Read())
+ {
+ var habitId = reader.GetString(0);
+ var habitName = reader.GetString(1);
+ var habitQuantity = reader.GetString(2);
+ var habitDate = reader.GetString(3);
+
+ Console.WriteLine($"ID: {habitId} - HABIT: {habitName} - QUANTITY: {habitQuantity} - DATE: {habitDate}");
+ }
+
+ connection.Close();
+
+ System.Console.WriteLine();
+ System.Console.WriteLine("Press Enter to continue.");
+ Console.ReadKey();
+}
+
+
+
+void CreateInput()
+{
+ int habitQuantity = 0;
+ DateOnly habitDate;
+
+ System.Console.WriteLine("Habit Name:");
+ string habitName = Console.ReadLine().Trim();
+ System.Console.WriteLine();
+
+ System.Console.WriteLine("Quantity:");
+ string quantityStr = Console.ReadLine();
+ while (!int.TryParse(quantityStr, out habitQuantity))
+ {
+ System.Console.WriteLine("Invalid quantity. Only integers are accepted!");
+ System.Console.WriteLine("Quantity:");
+ quantityStr = Console.ReadLine();
+ }
+ System.Console.WriteLine();
+
+ System.Console.WriteLine("Date: (Tip: use 'Today' for today's date!)");
+ string dateStr = Console.ReadLine().Trim().ToLower();
+ if (dateStr != "today"){
+ while (!DateOnly.TryParse(dateStr, out habitDate))
+ {
+ System.Console.WriteLine();
+ System.Console.WriteLine("Invalid date. Only dates are accepted!");
+ System.Console.WriteLine("Date: (Tip: use 'Today' for today's date!)");
+ dateStr = Console.ReadLine();
+ }
+ }
+ else
+ {
+ habitDate = DateOnly.Parse(DateTime.Today.ToShortDateString());
+ }
+
+ System.Console.WriteLine();
+ System.Console.WriteLine("** Your Input: **");
+ System.Console.WriteLine($"Habit: {habitName}");
+ System.Console.WriteLine($"Quantity: {habitQuantity}");
+ System.Console.WriteLine($"Date: {habitDate}");
+ System.Console.WriteLine();
+
+ System.Console.WriteLine("Is that correct? (y/n)");
+ string userAnswer = Console.ReadLine().Trim().ToLower();
+ System.Console.WriteLine();
+
+ if (userAnswer == "y")
+ {
+ System.Console.WriteLine("Saving habit......");
+ CreateRow(habitName, habitQuantity, habitDate);
+ System.Console.WriteLine("Saved!");
+ System.Console.WriteLine();
+ System.Console.WriteLine("Press Enter to continue.");
+ Console.ReadKey();
+ }
+ else if (userAnswer == "n")
+ {
+ System.Console.WriteLine("Habit input canceled!");
+ }
+ else
+ {
+ while (userAnswer != "y" || userAnswer != "n")
+ {
+ System.Console.WriteLine("Please input 'y' for yes and 'n' for no.");
+ userAnswer = Console.ReadLine().Trim().ToLower();
+ }
+ }
+ System.Console.WriteLine();
+}
+
+Main();
\ No newline at end of file
diff --git a/project/habits.db b/project/habits.db
new file mode 100644
index 00000000..d8b4dac7
Binary files /dev/null and b/project/habits.db differ
diff --git a/project/project.csproj b/project/project.csproj
new file mode 100644
index 00000000..f4d4be65
--- /dev/null
+++ b/project/project.csproj
@@ -0,0 +1,12 @@
+
+
+ Exe
+ net9.0
+ enable
+ enable
+
+
+
+
+
+
\ No newline at end of file
diff --git a/project/project.csproj.lscache b/project/project.csproj.lscache
new file mode 100644
index 00000000..46144be8
--- /dev/null
+++ b/project/project.csproj.lscache
@@ -0,0 +1,248 @@
+version=1
+
+# This file caches language service data to improve the performance of C# Dev Kit.
+# It is not intended for manual editing. It can safely be deleted and will be
+# regenerated automatically. For more information, see https://aka.ms/lscache
+#
+# To control where cache files are stored, use the following VS Code setting:
+# "dotnet.projectsystem.cacheInProjectFolder": true
+
+[project]
+language=C#
+primary
+lastDtbSucceeded
+
+[properties]
+AssemblyName=project
+CommandLineArgsForDesignTimeEvaluation=-langversion:13.0 -define:TRACE
+CompilerGeneratedFilesOutputPath=
+MaxSupportedLangVersion=13.0
+ProjectAssetsFile=obj/project.assets.json
+RootNamespace=project
+RunAnalyzers=
+RunAnalyzersDuringLiveAnalysis=
+SolutionPath=*Undefined*
+TargetFrameworkIdentifier=.NETCoreApp
+TargetPath=bin/Debug/net9.0/project.dll
+TargetRefPath=obj/Debug/net9.0/ref/project.dll
+TemporaryDependencyNodeTargetIdentifier=net9.0
+
+[commandLineArguments]
+/noconfig
+/unsafe-
+/checked-
+/nowarn:1701,1702,1701,1702
+/fullpaths
+/nostdlib+
+/errorreport:prompt
+/warn:9
+/define:TRACE;DEBUG;NET;NET9_0;NETCOREAPP;NET5_0_OR_GREATER;NET6_0_OR_GREATER;NET7_0_OR_GREATER;NET8_0_OR_GREATER;NET9_0_OR_GREATER;NETCOREAPP1_0_OR_GREATER;NETCOREAPP1_1_OR_GREATER;NETCOREAPP2_0_OR_GREATER;NETCOREAPP2_1_OR_GREATER;NETCOREAPP2_2_OR_GREATER;NETCOREAPP3_0_OR_GREATER;NETCOREAPP3_1_OR_GREATER
+/highentropyva+
+/nullable:enable
+/debug+
+/debug:portable
+/filealign:512
+/optimize-
+/out:obj\Debug\net9.0\project.dll
+/refout:obj\Debug\net9.0\refint\project.dll
+/target:exe
+/warnaserror-
+/utf8output
+/deterministic+
+/langversion:13.0
+/warnaserror+:NU1605,SYSLIB0011
+
+[sourceFiles]
+obj/Debug/net9.0/
+ .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
+ project.AssemblyInfo.cs
+ project.GlobalUsings.g.cs
+Program.cs
+
+[metadataReferences]
+/packs/Microsoft.NETCore.App.Ref/9.0.2/ref/net9.0/
+ Microsoft.CSharp.dll
+ Microsoft.VisualBasic.Core.dll
+ Microsoft.VisualBasic.dll
+ Microsoft.Win32.Primitives.dll
+ Microsoft.Win32.Registry.dll
+ mscorlib.dll
+ netstandard.dll
+ System.AppContext.dll
+ System.Buffers.dll
+ System.Collections.Concurrent.dll
+ System.Collections.dll
+ System.Collections.Immutable.dll
+ System.Collections.NonGeneric.dll
+ System.Collections.Specialized.dll
+ System.ComponentModel.Annotations.dll
+ System.ComponentModel.DataAnnotations.dll
+ System.ComponentModel.dll
+ System.ComponentModel.EventBasedAsync.dll
+ System.ComponentModel.Primitives.dll
+ System.ComponentModel.TypeConverter.dll
+ System.Configuration.dll
+ System.Console.dll
+ System.Core.dll
+ System.Data.Common.dll
+ System.Data.DataSetExtensions.dll
+ System.Data.dll
+ System.Diagnostics.Contracts.dll
+ System.Diagnostics.Debug.dll
+ System.Diagnostics.DiagnosticSource.dll
+ System.Diagnostics.FileVersionInfo.dll
+ System.Diagnostics.Process.dll
+ System.Diagnostics.StackTrace.dll
+ System.Diagnostics.TextWriterTraceListener.dll
+ System.Diagnostics.Tools.dll
+ System.Diagnostics.TraceSource.dll
+ System.Diagnostics.Tracing.dll
+ System.dll
+ System.Drawing.dll
+ System.Drawing.Primitives.dll
+ System.Dynamic.Runtime.dll
+ System.Formats.Asn1.dll
+ System.Formats.Tar.dll
+ System.Globalization.Calendars.dll
+ System.Globalization.dll
+ System.Globalization.Extensions.dll
+ System.IO.Compression.Brotli.dll
+ System.IO.Compression.dll
+ System.IO.Compression.FileSystem.dll
+ System.IO.Compression.ZipFile.dll
+ System.IO.dll
+ System.IO.FileSystem.AccessControl.dll
+ System.IO.FileSystem.dll
+ System.IO.FileSystem.DriveInfo.dll
+ System.IO.FileSystem.Primitives.dll
+ System.IO.FileSystem.Watcher.dll
+ System.IO.IsolatedStorage.dll
+ System.IO.MemoryMappedFiles.dll
+ System.IO.Pipelines.dll
+ System.IO.Pipes.AccessControl.dll
+ System.IO.Pipes.dll
+ System.IO.UnmanagedMemoryStream.dll
+ System.Linq.dll
+ System.Linq.Expressions.dll
+ System.Linq.Parallel.dll
+ System.Linq.Queryable.dll
+ System.Memory.dll
+ System.Net.dll
+ System.Net.Http.dll
+ System.Net.Http.Json.dll
+ System.Net.HttpListener.dll
+ System.Net.Mail.dll
+ System.Net.NameResolution.dll
+ System.Net.NetworkInformation.dll
+ System.Net.Ping.dll
+ System.Net.Primitives.dll
+ System.Net.Quic.dll
+ System.Net.Requests.dll
+ System.Net.Security.dll
+ System.Net.ServicePoint.dll
+ System.Net.Sockets.dll
+ System.Net.WebClient.dll
+ System.Net.WebHeaderCollection.dll
+ System.Net.WebProxy.dll
+ System.Net.WebSockets.Client.dll
+ System.Net.WebSockets.dll
+ System.Numerics.dll
+ System.Numerics.Vectors.dll
+ System.ObjectModel.dll
+ System.Reflection.DispatchProxy.dll
+ System.Reflection.dll
+ System.Reflection.Emit.dll
+ System.Reflection.Emit.ILGeneration.dll
+ System.Reflection.Emit.Lightweight.dll
+ System.Reflection.Extensions.dll
+ System.Reflection.Metadata.dll
+ System.Reflection.Primitives.dll
+ System.Reflection.TypeExtensions.dll
+ System.Resources.Reader.dll
+ System.Resources.ResourceManager.dll
+ System.Resources.Writer.dll
+ System.Runtime.CompilerServices.Unsafe.dll
+ System.Runtime.CompilerServices.VisualC.dll
+ System.Runtime.dll
+ System.Runtime.Extensions.dll
+ System.Runtime.Handles.dll
+ System.Runtime.InteropServices.dll
+ System.Runtime.InteropServices.JavaScript.dll
+ System.Runtime.InteropServices.RuntimeInformation.dll
+ System.Runtime.Intrinsics.dll
+ System.Runtime.Loader.dll
+ System.Runtime.Numerics.dll
+ System.Runtime.Serialization.dll
+ System.Runtime.Serialization.Formatters.dll
+ System.Runtime.Serialization.Json.dll
+ System.Runtime.Serialization.Primitives.dll
+ System.Runtime.Serialization.Xml.dll
+ System.Security.AccessControl.dll
+ System.Security.Claims.dll
+ System.Security.Cryptography.Algorithms.dll
+ System.Security.Cryptography.Cng.dll
+ System.Security.Cryptography.Csp.dll
+ System.Security.Cryptography.dll
+ System.Security.Cryptography.Encoding.dll
+ System.Security.Cryptography.OpenSsl.dll
+ System.Security.Cryptography.Primitives.dll
+ System.Security.Cryptography.X509Certificates.dll
+ System.Security.dll
+ System.Security.Principal.dll
+ System.Security.Principal.Windows.dll
+ System.Security.SecureString.dll
+ System.ServiceModel.Web.dll
+ System.ServiceProcess.dll
+ System.Text.Encoding.CodePages.dll
+ System.Text.Encoding.dll
+ System.Text.Encoding.Extensions.dll
+ System.Text.Encodings.Web.dll
+ System.Text.Json.dll
+ System.Text.RegularExpressions.dll
+ System.Threading.Channels.dll
+ System.Threading.dll
+ System.Threading.Overlapped.dll
+ System.Threading.Tasks.Dataflow.dll
+ System.Threading.Tasks.dll
+ System.Threading.Tasks.Extensions.dll
+ System.Threading.Tasks.Parallel.dll
+ System.Threading.Thread.dll
+ System.Threading.ThreadPool.dll
+ System.Threading.Timer.dll
+ System.Transactions.dll
+ System.Transactions.Local.dll
+ System.ValueTuple.dll
+ System.Web.dll
+ System.Web.HttpUtility.dll
+ System.Windows.dll
+ System.Xml.dll
+ System.Xml.Linq.dll
+ System.Xml.ReaderWriter.dll
+ System.Xml.Serialization.dll
+ System.Xml.XDocument.dll
+ System.Xml.XmlDocument.dll
+ System.Xml.XmlSerializer.dll
+ System.Xml.XPath.dll
+ System.Xml.XPath.XDocument.dll
+ WindowsBase.dll
+/
+ microsoft.data.sqlite.core/10.0.8/lib/net8.0/Microsoft.Data.Sqlite.dll
+ sqlitepclraw.config.e_sqlite3/3.0.3/lib/net8.0/SQLitePCLRaw.batteries_v2.dll
+ sqlitepclraw.core/3.0.3/lib/net8.0/SQLitePCLRaw.core.dll
+ sqlitepclraw.provider.e_sqlite3/3.0.3/lib/net8.0/SQLitePCLRaw.provider.e_sqlite3.dll
+
+[analyzerReferences]
+/packs/Microsoft.NETCore.App.Ref/9.0.2/analyzers/dotnet/cs/
+ Microsoft.Interop.ComInterfaceGenerator.dll
+ Microsoft.Interop.JavaScript.JSImportGenerator.dll
+ Microsoft.Interop.LibraryImportGenerator.dll
+ Microsoft.Interop.SourceGeneration.dll
+ System.Text.Json.SourceGeneration.dll
+ System.Text.RegularExpressions.Generator.dll
+/sdk/9.0.200/Sdks/Microsoft.NET.Sdk/analyzers/
+ Microsoft.CodeAnalysis.CSharp.NetAnalyzers.dll
+ Microsoft.CodeAnalysis.NetAnalyzers.dll
+
+[analyzerConfigFiles]
+/sdk/9.0.200/Sdks/Microsoft.NET.Sdk/analyzers/build/config/analysislevel_9_default.globalconfig
+obj/Debug/net9.0/project.GeneratedMSBuildEditorConfig.editorconfig