From d655039a46cc90d911663858935441cd29ab2e54 Mon Sep 17 00:00:00 2001 From: Dalton Soto Date: Thu, 27 Mar 2025 09:44:33 -0400 Subject: [PATCH 1/2] finished project --- FlashcardsApp/FlashcardsApp.sln | 22 ++ .../FlashcardsApp/DTOs/FlashcardDTO.cs | 17 + .../FlashcardsApp/FlashcardsApp.csproj | 24 ++ .../FlashcardsApp/Models/Flashcard.cs | 17 + FlashcardsApp/FlashcardsApp/Models/Stack.cs | 16 + .../FlashcardsApp/Models/StudySession.cs | 16 + FlashcardsApp/FlashcardsApp/Program.cs | 46 +++ .../FlashcardsApp/Services/DatabaseService.cs | 310 ++++++++++++++++ .../FlashcardsApp/Services/UserInput.cs | 340 ++++++++++++++++++ .../FlashcardsApp/UI/Core/InputValidator.cs | 94 +++++ .../FlashcardsApp/UI/Core/MenuHandler.cs | 70 ++++ .../FlashcardsApp/UI/Features/FlashcardUI.cs | 157 ++++++++ .../FlashcardsApp/UI/Features/StackUI.cs | 180 ++++++++++ .../FlashcardsApp/UI/Features/StudyUI.cs | 155 ++++++++ .../UI/Helpers/TableVisualization.cs | 101 ++++++ FlashcardsApp/FlashcardsApp/appsettings.json | 5 + 16 files changed, 1570 insertions(+) create mode 100644 FlashcardsApp/FlashcardsApp.sln create mode 100644 FlashcardsApp/FlashcardsApp/DTOs/FlashcardDTO.cs create mode 100644 FlashcardsApp/FlashcardsApp/FlashcardsApp.csproj create mode 100644 FlashcardsApp/FlashcardsApp/Models/Flashcard.cs create mode 100644 FlashcardsApp/FlashcardsApp/Models/Stack.cs create mode 100644 FlashcardsApp/FlashcardsApp/Models/StudySession.cs create mode 100644 FlashcardsApp/FlashcardsApp/Program.cs create mode 100644 FlashcardsApp/FlashcardsApp/Services/DatabaseService.cs create mode 100644 FlashcardsApp/FlashcardsApp/Services/UserInput.cs create mode 100644 FlashcardsApp/FlashcardsApp/UI/Core/InputValidator.cs create mode 100644 FlashcardsApp/FlashcardsApp/UI/Core/MenuHandler.cs create mode 100644 FlashcardsApp/FlashcardsApp/UI/Features/FlashcardUI.cs create mode 100644 FlashcardsApp/FlashcardsApp/UI/Features/StackUI.cs create mode 100644 FlashcardsApp/FlashcardsApp/UI/Features/StudyUI.cs create mode 100644 FlashcardsApp/FlashcardsApp/UI/Helpers/TableVisualization.cs create mode 100644 FlashcardsApp/FlashcardsApp/appsettings.json diff --git a/FlashcardsApp/FlashcardsApp.sln b/FlashcardsApp/FlashcardsApp.sln new file mode 100644 index 00000000..08b4e9af --- /dev/null +++ b/FlashcardsApp/FlashcardsApp.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}") = "FlashcardsApp", "FlashcardsApp\FlashcardsApp.csproj", "{E87AE218-DC73-4974-9E12-5FE3DE56D12B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E87AE218-DC73-4974-9E12-5FE3DE56D12B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E87AE218-DC73-4974-9E12-5FE3DE56D12B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E87AE218-DC73-4974-9E12-5FE3DE56D12B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E87AE218-DC73-4974-9E12-5FE3DE56D12B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/FlashcardsApp/FlashcardsApp/DTOs/FlashcardDTO.cs b/FlashcardsApp/FlashcardsApp/DTOs/FlashcardDTO.cs new file mode 100644 index 00000000..96a6131f --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/DTOs/FlashcardDTO.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FlashcardsApp.DTOs +{ + internal class FlashcardDTO + { + public int DisplayNumber { get; set; } + public int FlashcardId { get; set; } + public string Front { get; set; } + public string Back { get; set; } + public DateTime CreatedDate { get; set; } + } +} diff --git a/FlashcardsApp/FlashcardsApp/FlashcardsApp.csproj b/FlashcardsApp/FlashcardsApp/FlashcardsApp.csproj new file mode 100644 index 00000000..47fd89d8 --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/FlashcardsApp.csproj @@ -0,0 +1,24 @@ + + + + Exe + net9.0 + enable + enable + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/FlashcardsApp/FlashcardsApp/Models/Flashcard.cs b/FlashcardsApp/FlashcardsApp/Models/Flashcard.cs new file mode 100644 index 00000000..2f4bb5bd --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/Models/Flashcard.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FlashcardsApp.Models +{ + internal class Flashcard + { + public int FlashcardId { get; set; } + public int StackId { get; set; } + public string Front { get; set; } + public string Back { get; set; } + public DateTime CreatedDate { get; set; } + } +} diff --git a/FlashcardsApp/FlashcardsApp/Models/Stack.cs b/FlashcardsApp/FlashcardsApp/Models/Stack.cs new file mode 100644 index 00000000..6f5fd32b --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/Models/Stack.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FlashcardsApp.Models +{ + internal class Stack + { + public int StackId { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public DateTime CreatedDate { get; set; } + } +} diff --git a/FlashcardsApp/FlashcardsApp/Models/StudySession.cs b/FlashcardsApp/FlashcardsApp/Models/StudySession.cs new file mode 100644 index 00000000..c609c476 --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/Models/StudySession.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FlashcardsApp.Models +{ + internal class StudySession + { + public int SessionId { get; set; } + public int StackId { get; set; } + public string Score { get; set; } + public DateTime StudyDate { get; set; } + } +} diff --git a/FlashcardsApp/FlashcardsApp/Program.cs b/FlashcardsApp/FlashcardsApp/Program.cs new file mode 100644 index 00000000..4ff355f4 --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/Program.cs @@ -0,0 +1,46 @@ +using Microsoft.Extensions.Configuration; +using FlashcardsApp.Services; +using FlashcardsApp.UI.Core; + +namespace FlashcardsApp +{ + class Program + { + static IConfiguration? config; // a variable of type IConfiguration + static DatabaseService? databaseService; + static void Main(string[] args) + { + try + { + config = new ConfigurationBuilder() // Starting with an empty configuration but will return an IConfiguration object + .SetBasePath(Directory.GetCurrentDirectory()) // tells the builder where to look for configuration files (appsettings.json) + .AddJsonFile("appsettings.json") // what file it should be reading + .Build(); // creates the the IConfiguration object + + string? connectionString = config.GetConnectionString("Default"); //GetConnectionString("Default") specifically looks for "ConnectionString" in appsettings.json + // and return the value associated with "Default" + if (connectionString == null) + { + throw new Exception("Connection string not found\n"); + + } + + databaseService = new(connectionString); + databaseService.TestConnection(); + + Console.WriteLine("Successfully connected to server!\n"); + } + catch (Exception ex) + { + Console.WriteLine($"Error loading database: {ex.Message}\n"); + Console.WriteLine("Press Any Key to Exit..."); + Console.ReadKey(); + return; + } + + MenuHandler menuHandler = new(databaseService); + + menuHandler.MainMenu(); + } + } +} \ No newline at end of file diff --git a/FlashcardsApp/FlashcardsApp/Services/DatabaseService.cs b/FlashcardsApp/FlashcardsApp/Services/DatabaseService.cs new file mode 100644 index 00000000..7d0cc447 --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/Services/DatabaseService.cs @@ -0,0 +1,310 @@ +using Dapper; +using Microsoft.Data.SqlClient; //for sql server connection +using FlashcardsApp.Models; +using FlashcardsApp.DTOs; +using Spectre.Console; +using FlashcardsApp.UI.Helpers; + +namespace FlashcardsApp.Services +{ + internal class DatabaseService + { + private readonly string _connectionString; + + internal DatabaseService(string connectionString) + { + _connectionString = connectionString; + } + + public void TestConnection() + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + } + } + + internal void DeleteFlashcard(int stackId, int flashcardId) + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + var sql = "DELETE FROM Flashcards WHERE StackId = @StackId AND FlashcardId = @FlashcardId"; + + var rowsAffected = connection.Execute(sql, new { StackId = stackId, FlashcardId = flashcardId }); + + if (rowsAffected > 0) + { + Console.WriteLine("\nDeletion successful."); + Console.WriteLine($"\n{rowsAffected} row(s) deleted."); + } + else + { + Console.WriteLine("\nDeletion has failed"); + } + } + } + + internal void DeleteStack(int stackId) + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + var sql = "DELETE FROM Stacks WHERE StackId = @StackId"; + + var rowsAffected = connection.Execute(sql, new { StackId = stackId }); + + if (rowsAffected > 0) + { + Console.WriteLine("\nDeletion successful."); + Console.WriteLine($"\n{rowsAffected} row(s) deleted."); + } + else + { + Console.WriteLine("\nDeletion has failed"); + } + } + } + + + internal void GetAllStacks() + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + var sql = "SELECT * FROM Stacks"; + + var stacks = connection.Query(sql).ToList(); + + TableVisualization.ShowStacksTable(stacks); + } + } + + internal List GetAllStacksAsList() + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + var sql = "SELECT * FROM Stacks"; + + var stacks = connection.Query(sql).ToList(); + + return stacks; + } + } + + internal Flashcard? GetFlashcardByFlashcardId(int flashcardId, int stackId) + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + var sql = "SELECT FlashcardId, StackId, Front, Back, CreatedDate FROM Flashcards WHERE StackId = @StackId AND FlashcardId = @FlashcardId"; + + var flashcard = connection.QuerySingleOrDefault(sql, new { StackId = stackId, FlashcardId = flashcardId }); + + if (flashcard == null) + { + Console.WriteLine($"\nNo flashcard found with ID: {flashcardId} in stack {stackId}"); + return null; + } + + return flashcard; + } + } + + + internal List GetFlashcardsByID(int stackId) + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + var sql = @" + SELECT + ROW_NUMBER() OVER (ORDER BY FlashcardId) as DisplayNumber, + FlashcardId, + Front, + Back, + CreatedDate + FROM Flashcards + WHERE StackId = @StackId"; + + var flashcards = connection.Query(sql, new { StackId = stackId}).ToList(); + + TableVisualization.ShowFlashcardsTable(flashcards); + + return flashcards; + } + } + + internal List GetFlashcardsByStackID(int stackId) + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + var sql = @" + SELECT + FlashcardId, + StackId, + Front, + Back, + CreatedDate + FROM Flashcards + WHERE StackId = @StackId"; + + var flashcards = connection.Query(sql, new { StackId = stackId }).ToList(); + + return flashcards; + } + } + + internal void GetStudyHistory() + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + var sql = "SELECT * FROM StudySessions"; + + var sessions = connection.Query(sql).ToList(); + + var sql2 = "SELECT * FROM Stacks"; + + var stacks = connection.Query(sql2).ToList(); + + if (sessions.Count > 0) + { + TableVisualization.ShowStudySessionsTable(sessions, stacks); + } + else + { + Console.WriteLine("\nNo sessions to view!"); + } + } + } + + internal void Post(Stack stack) + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + var sql = "INSERT INTO Stacks (Name, Description, CreatedDate) VALUES (@Name, @Description, @CreatedDate)"; + + var rowsAffected = connection.Execute(sql, new + { + Name = stack.Name, + Description = stack.Description, + CreatedDate = stack.CreatedDate, + }); + + if (rowsAffected > 0) + { + Console.WriteLine("\nSuccessfully added stack!"); + Console.WriteLine($"\n{rowsAffected} row(s) inserted."); + } + else + { + Console.WriteLine("\nFailed to add stack!"); + } + } + } + + internal void PostFlashcard(Flashcard flashcard) + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + var checkSql = @"SELECT COUNT(1) + FROM Flashcards + WHERE StackId = @StackId + AND Front = @Front"; + + var exists = connection.ExecuteScalar(checkSql, new + { + StackId = flashcard.StackId, + Front = flashcard.Front + }) > 0; + + if (exists) + { + Console.WriteLine("\nA flashcard with this front already exists in this stack!"); + return; + } + + var sql = "INSERT INTO Flashcards (StackId, Front, Back, CreatedDate) VALUES (@StackId, @Front, @Back, @CreatedDate)"; + + var rowsAffected = connection.Execute(sql, new + { + StackId = flashcard.StackId, + Front = flashcard.Front, + Back = flashcard.Back, + CreatedDate = flashcard.CreatedDate + }); + + if (rowsAffected > 0) + { + Console.WriteLine("\nSuccessfully added flashcard to stack!"); + Console.WriteLine($"\n{rowsAffected} row(s) inserted."); + } + else + { + Console.WriteLine("\nFailed to add flashcard!"); + } + } + } + + internal void PostStudySession(StudySession session) + { + using (var connection = new SqlConnection( _connectionString)) + { + connection.Open(); + + var sql = "INSERT INTO StudySessions (StackId, Score, StudyDate) VALUES (@StackId, @Score, @StudyDate)"; + + var rowsAffected = connection.Execute(sql, new + { + StackId = session.StackId, + Score = session.Score, + StudyDate = session.StudyDate, + }); + + if (rowsAffected > 0) + { + Console.WriteLine("\nStudy Session was successfully uploaded!"); + Console.WriteLine($"\n{rowsAffected} row(s) inserted."); + } + else + { + Console.WriteLine("\nFailed to upload session!"); + } + } + } + + internal void UpdateFlashcard(int stackId, int flashcardId, Flashcard flashcard) + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + var sql = @"UPDATE Flashcards SET Front = @Front, Back = @Back, CreatedDate = @CreatedDate WHERE StackId = @StackId AND FlashcardId = @FlashcardId"; + + var rowsAffected = connection.Execute(sql, new + { + Front = flashcard.Front, + Back = flashcard.Back, + CreatedDate = flashcard.CreatedDate, + StackId = stackId, + FlashcardId = flashcardId + }); + } + } + } +} diff --git a/FlashcardsApp/FlashcardsApp/Services/UserInput.cs b/FlashcardsApp/FlashcardsApp/Services/UserInput.cs new file mode 100644 index 00000000..75d147f4 --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/Services/UserInput.cs @@ -0,0 +1,340 @@ +//using FlashcardsApp.DTOs; +//using FlashcardsApp.Models; +//using Spectre.Console; + +//namespace FlashcardsApp.Services +//{ +// internal class UserInput +// { +// private readonly DatabaseService _databaseService; + +// public UserInput(DatabaseService databaseService) +// { +// _databaseService = databaseService; +// } + +// internal void MainMenu() +// { +// Console.Clear(); +// bool closeApp = false; +// while (closeApp == false) +// { +// var choice = AnsiConsole.Prompt( +// new SelectionPrompt() +// .Title("MAIN MENU") +// .AddChoices(new[] { +// "View All Stacks", +// "Create New Stack", +// "Manage Stack", +// "Study a Stack", +// "View Study History", +// "Close Application" +// })); + +// switch (choice) +// { +// case "View All Stacks": +// _databaseService.GetAllStacks(); +// break; +// case "Create New Stack": +// CreateStack(); +// break; +// case "Manage Stack": +// StacksListMenu(); +// break; +// case "Study a Stack": +// break; +// case "View Study History": +// break; +// case "Close Application": +// closeApp = true; +// Environment.Exit(0); +// break; +// } +// } +// } + +// internal void StacksListMenu() +// { +// Console.Clear(); +// _databaseService.GetAllStacks(); + +// List stacks = _databaseService.GetAllStacksAsList(); +// List stackNames = stacks.Select(s => s.Name).ToList(); +// stackNames.Add("Return to Main Menu"); + +// var selectedStack = AnsiConsole.Prompt( +// new SelectionPrompt() +// .Title("Select a stack to manage.") +// .AddChoices(stackNames)); +// if (selectedStack == "Return to Main Menu") +// { +// MainMenu(); +// } + +// while (true) +// { +// Console.Clear(); + +// var action = AnsiConsole.Prompt( +// new SelectionPrompt() +// .Title($"Managing stack: {selectedStack}") +// .AddChoices(new[] +// { +// "View Cards", +// "Add Card", +// "Update Card", +// "Delete Card", +// "Delete this Stack", +// "Return to Stack Menu", +// "Return to Main Menu" +// })); + +// int stackId = GetStackId(selectedStack); + +// switch (action) +// { +// case "View Cards": +// _databaseService.GetFlashcardsByID(stackId); +// break; +// case "Add Card": +// CreateFlashcard(stackId); +// break; +// case "Update Card": +// UpdateFlashcard(stackId); +// break; +// case "Delete Card": +// DeleteFlashcard(stackId); +// break; +// case "Delete this Stack": +// DeleteStack(stackId, selectedStack); +// break; +// case "Return to Stack Menu": +// StacksListMenu(); +// return; +// case "Return to Main Menu": +// MainMenu(); +// return; +// } +// Console.WriteLine("\n\nPress Enter..."); +// Console.ReadLine(); +// } +// } + +// private void UpdateFlashcard(int stackId) +// { +// List flashcards = _databaseService.GetFlashcardsByID(stackId); + +// Dictionary cardMapping = flashcards.ToDictionary( +// f => $"Front: {f.Front}\t\t| Back: {f.Back}", +// f => f.FlashcardId); + +// var choices = cardMapping.Keys.ToList(); +// choices.Add("Return to Stack Menu"); + +// var selectedCard = AnsiConsole.Prompt( +// new SelectionPrompt() +// .Title("Select a card to update.") +// .AddChoices(choices)); +// if (selectedCard == "Return to Stack Menu") +// { +// StacksListMenu(); +// return; +// } + +// int flashcardId = cardMapping[selectedCard]; + +// Flashcard? flashcard = _databaseService.GetFlashcardByFlashcardId(flashcardId, stackId); +// if (flashcard == null) +// { +// return; +// } + +// bool finished = false; +// while (finished == false) +// { +// var choice = AnsiConsole.Prompt( +// new SelectionPrompt() +// .Title("Select what to update, save, or exit.") +// .AddChoices(new[] +// { +// "Front", +// "Back", +// "Save Changes", +// "Exit to Stack Menu", +// "Exit to Main Menu" +// })); + +// switch (choice) +// { +// case "Front": +// flashcard.Front = GetFrontFlashcard(); +// break; +// case "Back": +// flashcard.Back = GetBackFlashcard(); +// break; +// case "Save Changes": +// flashcard.CreatedDate = DateTime.Now; +// _databaseService.UpdateFlashcard(stackId, flashcardId, flashcard); +// finished = true; +// break; +// case "Exit to Stack Menu": +// StacksListMenu(); +// return; +// case "Exit to Main Menu": +// MainMenu(); +// return; +// } +// } + +// } + +// private void DeleteStack(int stackId, string selectedStack) +// { +// var action = AnsiConsole.Prompt( +// new SelectionPrompt() +// .Title($"\nAre you sure you want to delete '{selectedStack}' stack?") +// .AddChoices(new[] +// { +// "Yes", +// "No" +// })); + +// switch (action) +// { +// case "Yes": +// _databaseService.DeleteStack(stackId); +// Console.WriteLine("\n\nPress Enter..."); +// Console.ReadLine(); +// StacksListMenu(); +// return; +// case "No": +// return; +// } +// } + +// private void DeleteFlashcard(int stackId) +// { +// List flashcards = _databaseService.GetFlashcardsByID(stackId); + +// Dictionary cardMapping = flashcards.ToDictionary( +// f => $"Front: {f.Front}\t\t| Back: {f.Back}", +// f => f.FlashcardId +// ); +// var choices = cardMapping.Keys.ToList(); +// choices.Add("Return to Stack Menu"); + +// var selectedCard = AnsiConsole.Prompt( +// new SelectionPrompt() +// .Title("Select a card to delete.") +// .AddChoices(choices)); +// if (selectedCard == "Return to Stack Menu") +// { +// StacksListMenu(); +// return; +// } + +// int flashcardId = cardMapping[selectedCard]; +// _databaseService.DeleteFlashcard(stackId, flashcardId); +// } + +// private int GetStackId(string selectedStack) +// { +// List stacks = _databaseService.GetAllStacksAsList(); +// Stack stack = stacks.First(s => s.Name == selectedStack); +// return stack.StackId; +// } + +// private void CreateFlashcard(int stackId) +// { +// Flashcard flashcard = new(); + +// string front = GetFrontFlashcard(); + +// string back = GetBackFlashcard(); + +// flashcard.StackId = stackId; +// flashcard.Front = front; +// flashcard.Back = back; +// flashcard.CreatedDate = DateTime.Now; + +// _databaseService.PostFlashcard(flashcard); +// } + +// internal string GetFrontFlashcard() +// { +// Console.Write("\n\nEnter the content for the front of the card OR 0 to return to Stack Menu: "); +// string? front = Console.ReadLine(); + +// if (front == "0") StacksListMenu(); + +// while (string.IsNullOrEmpty(front) || front.Length > 500) +// { +// Console.WriteLine("\nFront cannot be empty or longer than 500 characcters."); +// Console.Write("\nEnter the front: "); +// front = Console.ReadLine(); +// } + +// return front; +// } + +// internal string GetBackFlashcard() +// { +// Console.Write("\n\nEnter the content for the back of the card OR 0 to return to Stack Menu: "); +// string? back = Console.ReadLine(); + +// if (back == "0") StacksListMenu(); + +// while (string.IsNullOrEmpty(back) || back.Length > 500) +// { +// Console.WriteLine("\nBack cannot be empty or longer than 500 characcters."); +// Console.Write("\nEnter the back: "); +// back = Console.ReadLine(); +// } + +// return back; +// } + +// private void CreateStack() +// { +// Stack stack = new(); + +// Console.Write("\nEnter a name for the stack of flashcards OR 0 to return to Main Menu: "); +// string? name = Console.ReadLine(); + +// if (name == "0") MainMenu(); + +// while (string.IsNullOrEmpty(name) || name.Length > 100) +// { +// Console.WriteLine("\nName cannot be empty or longer than 100 characters."); +// Console.Write("\n\nPlease enter a valid name: "); +// name = Console.ReadLine(); +// } + +// Console.Write("\nIf you would like to add a description type it here or press enter: "); +// string? description; + +// do +// { +// description = Console.ReadLine(); + +// if (string.IsNullOrWhiteSpace(description)) +// { +// description = "No description provided"; +// } + +// if (description.Length > 500) +// { +// Console.WriteLine("\nSorry description cannot be longer than 500 characters"); +// Console.Write("\nEnter description again: "); +// } +// } while (description.Length > 500); + +// stack.Name = name; +// stack.Description = description; +// stack.CreatedDate = DateTime.Now; + +// _databaseService.Post(stack); +// } +// } +//} \ No newline at end of file diff --git a/FlashcardsApp/FlashcardsApp/UI/Core/InputValidator.cs b/FlashcardsApp/FlashcardsApp/UI/Core/InputValidator.cs new file mode 100644 index 00000000..b9315b3e --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/UI/Core/InputValidator.cs @@ -0,0 +1,94 @@ +using Spectre.Console; + +namespace FlashcardsApp.UI.Core +{ + public class InputValidator + { + public string GetStackName() + { + while (true) + { + Console.Write("\nEnter a name for the stack of flashcards OR 0 to return: "); + string? name = Console.ReadLine(); + + if (name == "0") + return string.Empty; + + if (string.IsNullOrEmpty(name)) + { + Console.WriteLine("\nName cannot be empty."); + continue; + } + + if (name.Length > 100) + { + Console.WriteLine("\nName cannot be longer than 100 characters."); + continue; + } + + return name; + } + } + + public string GetStackDescription() + { + Console.Write("\nIf you would like to add a description type it here or press enter: "); + string? description; + + do + { + description = Console.ReadLine(); + + if (string.IsNullOrWhiteSpace(description)) + { + return "No description provided"; + } + + if (description.Length > 500) + { + Console.WriteLine("\nDescription cannot be longer than 500 characters"); + Console.Write("\nEnter description again: "); + } + } while (description.Length > 500); + + return description; + } + + public string GetFlashcardContent(string side) + { + while (true) + { + Console.Write($"\n\nEnter the content for the {side} of the card OR 0 to return: "); + string? content = Console.ReadLine(); + + if (content == "0") + return string.Empty; + + if (string.IsNullOrEmpty(content)) + { + Console.WriteLine($"\n{side} cannot be empty."); + continue; + } + + if (content.Length > 500) + { + Console.WriteLine($"\n{side} cannot be longer than 500 characters."); + continue; + } + + return content; + } + } + + public bool GetConfirmation(string message) + { + var choice = AnsiConsole.Prompt( + new SelectionPrompt() + .Title(message) + .AddChoices(new[] { "Yes", "No" })); + + return choice == "Yes"; + } + } +} + diff --git a/FlashcardsApp/FlashcardsApp/UI/Core/MenuHandler.cs b/FlashcardsApp/FlashcardsApp/UI/Core/MenuHandler.cs new file mode 100644 index 00000000..20b955bb --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/UI/Core/MenuHandler.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FlashcardsApp.Services; +using FlashcardsApp.UI.Features; +using Spectre.Console; + +namespace FlashcardsApp.UI.Core +{ + internal class MenuHandler + { + private readonly DatabaseService _databaseService; + private readonly StackUI _stackUI; + private readonly FlashcardUI _flashcardUI; + private readonly StudyUI _studyUI; + + internal MenuHandler(DatabaseService databaseService) + { + _databaseService = databaseService; + _stackUI = new StackUI(databaseService); + _flashcardUI = new FlashcardUI(databaseService); + _studyUI = new StudyUI(databaseService); + } + + internal void MainMenu() + { + Console.Clear(); + bool closeApp = false; + while (closeApp == false) + { + var choice = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("MAIN MENU") + .AddChoices(new[] { + "View All Stacks", + "Create New Stack", + "Manage Stack", + "Study a Stack", + "View Study History", + "Close Application" + })); + + switch (choice) + { + case "View All Stacks": + _databaseService.GetAllStacks(); + break; + case "Create New Stack": + _stackUI.CreateStack(); + break; + case "Manage Stack": + _stackUI.StacksListMenu(); + break; + case "Study a Stack": + _studyUI.StudyMain(); + break; + case "View Study History": + _databaseService.GetStudyHistory(); + break; + case "Close Application": + closeApp = true; + Environment.Exit(0); + break; + } + } + } + } +} diff --git a/FlashcardsApp/FlashcardsApp/UI/Features/FlashcardUI.cs b/FlashcardsApp/FlashcardsApp/UI/Features/FlashcardUI.cs new file mode 100644 index 00000000..a3859a32 --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/UI/Features/FlashcardUI.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FlashcardsApp.DTOs; +using FlashcardsApp.Models; +using FlashcardsApp.Services; +using FlashcardsApp.UI.Core; +using Spectre.Console; + +namespace FlashcardsApp.UI.Features +{ + internal class FlashcardUI + { + private readonly DatabaseService _databaseService; + private readonly InputValidator _validator; + + internal FlashcardUI(DatabaseService databaseService) + { + _databaseService = databaseService; + _validator = new InputValidator(); + } + + public void ViewCards(int stackId) + { + _databaseService.GetFlashcardsByID(stackId); + } + + public void CreateFlashcard(int stackId) + { + Flashcard flashcard = new(); + + string front = GetFrontContent(); + if (string.IsNullOrEmpty(front)) return; + + string back = GetBackContent(); + if (string.IsNullOrEmpty(back)) return; + + flashcard.StackId = stackId; + flashcard.Front = front; + flashcard.Back = back; + flashcard.CreatedDate = DateTime.Now; + + _databaseService.PostFlashcard(flashcard); + Console.WriteLine("\nFlashcard created successfully!"); + } + + public void UpdateFlashcard(int stackId) + { + List flashcards = _databaseService.GetFlashcardsByID(stackId); + + if (!flashcards.Any()) + { + Console.WriteLine("\nNo flashcards in this stack!"); + return; + } + + Dictionary cardMapping = flashcards.ToDictionary( + f => $"Front: {f.Front}\t\t| Back: {f.Back}", + f => f.FlashcardId); + + var choices = cardMapping.Keys.ToList(); + choices.Add("Return to Stack Menu"); + + var selectedCard = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select a card to update.") + .AddChoices(choices)); + + if (selectedCard == "Return to Stack Menu") + { + return; + } + + int flashcardId = cardMapping[selectedCard]; + + Flashcard? flashcard = _databaseService.GetFlashcardByFlashcardId(flashcardId, stackId); + if (flashcard == null) + { + return; + } + + bool finished = false; + while (!finished) + { + var choice = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select what to update, save, or exit.") + .AddChoices(new[] + { + "Front", + "Back", + "Save Changes", + "Return to Stack Menu" + })); + + switch (choice) + { + case "Front": + string newFront = GetFrontContent(); + if (!string.IsNullOrEmpty(newFront)) + flashcard.Front = newFront; + break; + case "Back": + string newBack = GetBackContent(); + if (!string.IsNullOrEmpty(newBack)) + flashcard.Back = newBack; + break; + case "Save Changes": + flashcard.CreatedDate = DateTime.Now; + _databaseService.UpdateFlashcard(stackId, flashcardId, flashcard); + finished = true; + break; + case "Return to Stack Menu": + return; + } + } + } + + public void DeleteFlashcard(int stackId) + { + List flashcards = _databaseService.GetFlashcardsByID(stackId); + + Dictionary cardMapping = flashcards.ToDictionary( + f => $"Front: {f.Front}\t\t| Back: {f.Back}", + f => f.FlashcardId); + + var choices = cardMapping.Keys.ToList(); + choices.Add("Return to Stack Menu"); + + var selectedCard = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select a card to delete.") + .AddChoices(choices)); + + if (selectedCard == "Return to Stack Menu") + { + return; + } + + int flashcardId = cardMapping[selectedCard]; + _databaseService.DeleteFlashcard(stackId, flashcardId); + } + + private string GetFrontContent() + { + return _validator.GetFlashcardContent("front"); + } + + private string GetBackContent() + { + return _validator.GetFlashcardContent("back"); + } + + } +} diff --git a/FlashcardsApp/FlashcardsApp/UI/Features/StackUI.cs b/FlashcardsApp/FlashcardsApp/UI/Features/StackUI.cs new file mode 100644 index 00000000..b3a33c3e --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/UI/Features/StackUI.cs @@ -0,0 +1,180 @@ +using FlashcardsApp.Models; +using FlashcardsApp.Services; +using FlashcardsApp.UI.Core; +using Spectre.Console; + +namespace FlashcardsApp.UI.Features +{ + internal class StackUI + { + private readonly DatabaseService _databaseService; + private readonly FlashcardUI _flashcardUI; + private readonly InputValidator _validator; + + internal StackUI(DatabaseService databaseService) + { + _databaseService = databaseService; + _flashcardUI = new FlashcardUI(databaseService); + _validator = new InputValidator(); + } + + public void StacksListMenu() + { + while (true) + { + Console.Clear(); + _databaseService.GetAllStacks(); + + List stacks = _databaseService.GetAllStacksAsList(); + if (!stacks.Any()) + { + Console.WriteLine("\nNo stacks found. Create a stack first!"); + Console.WriteLine("\nPress Enter to return to main menu..."); + Console.ReadLine(); + return; + } + + List stackNames = stacks.Select(s => s.Name).ToList(); + stackNames.Add("Return to Main Menu"); + + var selectedStack = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select a stack to manage.") + .AddChoices(stackNames)); + + if (selectedStack == "Return to Main Menu") + { + return; + } + + ManageStack(selectedStack); + } + } + + private void ManageStack(string selectedStack) + { + while (true) + { + Console.Clear(); + + var action = AnsiConsole.Prompt( + new SelectionPrompt() + .Title($"Managing stack: {selectedStack}") + .AddChoices(new[] + { + "View Cards", + "Add Card", + "Update Card", + "Delete Card", + "Delete this Stack", + "Return to Stack Menu", + "Return to Main Menu" + })); + + int stackId = GetStackId(selectedStack); + if (stackId == -1) + { + Console.WriteLine("\nError accessing stack. Returning to stack menu..."); + Console.WriteLine("\nPress Enter to continue..."); + Console.ReadLine(); + return; + } + + switch (action) + { + case "View Cards": + _flashcardUI.ViewCards(stackId); + break; + case "Add Card": + _flashcardUI.CreateFlashcard(stackId); + break; + case "Update Card": + _flashcardUI.UpdateFlashcard(stackId); + break; + case "Delete Card": + _flashcardUI.DeleteFlashcard(stackId); + break; + case "Delete this Stack": + if (DeleteStack(stackId, selectedStack)) + return; + break; + case "Return to Stack Menu": + return; + case "Return to Main Menu": + return; + } + + Console.WriteLine("\nPress Enter to continue..."); + Console.ReadLine(); + } + } + + public void CreateStack() + { + string name = _validator.GetStackName(); + if (string.IsNullOrEmpty(name)) + return; + + string description = _validator.GetStackDescription(); + + Stack stack = new() + { + Name = name, + Description = description, + CreatedDate = DateTime.Now + }; + + try + { + _databaseService.Post(stack); + Console.WriteLine("\nStack created successfully!"); + Console.WriteLine("\nPress Enter to continue..."); + Console.ReadLine(); + } + catch (Exception ex) + { + Console.WriteLine($"\nError creating stack: {ex.Message}"); + Console.WriteLine("\nPress Enter to continue..."); + Console.ReadLine(); + } + } + + private bool DeleteStack(int stackId, string selectedStack) + { + if (_validator.GetConfirmation($"\nAre you sure you want to delete '{selectedStack}' stack?")) + { + try + { + _databaseService.DeleteStack(stackId); + Console.WriteLine("\nStack deleted successfully!"); + Console.WriteLine("\nPress Enter to continue..."); + Console.ReadLine(); + return true; + } + catch (Exception ex) + { + Console.WriteLine($"\nError deleting stack: {ex.Message}"); + Console.WriteLine("\nPress Enter to continue..."); + Console.ReadLine(); + return false; + } + } + return false; + } + + private int GetStackId(string selectedStack) + { + try + { + List stacks = _databaseService.GetAllStacksAsList(); + Stack stack = stacks.First(s => s.Name == selectedStack); + return stack.StackId; + } + catch (Exception) + { + Console.WriteLine("\nError finding stack."); + return -1; + } + } + } +} diff --git a/FlashcardsApp/FlashcardsApp/UI/Features/StudyUI.cs b/FlashcardsApp/FlashcardsApp/UI/Features/StudyUI.cs new file mode 100644 index 00000000..243a5569 --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/UI/Features/StudyUI.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FlashcardsApp.Models; +using FlashcardsApp.Services; +using FlashcardsApp.UI.Core; +using Spectre.Console; + +namespace FlashcardsApp.UI.Features +{ + internal class StudyUI + { + private readonly DatabaseService _databaseService; + private readonly InputValidator _inputValidator; + + internal StudyUI(DatabaseService databaseService) + { + _databaseService = databaseService; + _inputValidator = new InputValidator(); + } + + internal void StudyMain() + { + bool continueStudy = true; + while (continueStudy) + { + if (!GetStackToStudy(out int stackId)) + { + return; + } + + if (RunStudySession(stackId, out string finalScore)) + { + AddStudySession(stackId, finalScore); + } + + continueStudy = _inputValidator.GetConfirmation("Would you like to study a stack again?"); + } + } + + private bool GetStackToStudy(out int stackId) + { + stackId = -1; + Console.Clear(); + _databaseService.GetAllStacks(); + + List stacks = _databaseService.GetAllStacksAsList(); + if (!stacks.Any()) + { + Console.WriteLine("\nNo stacks found. Create a stack first!"); + Console.WriteLine("\nPress Enter to return to main menu..."); + Console.ReadLine(); + return false; + } + + Dictionary stackMapping = stacks.ToDictionary( + s => $"Name: {s.Name} | {s.Description}", + s => s.StackId); + + var choices = stackMapping.Keys.ToList(); + choices.Add("Return to Main Menu"); + + var selectedStack = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select a stack to study.") + .AddChoices(choices)); + + if (selectedStack == "Return to Main Menu") + return false; + + stackId = stackMapping[selectedStack]; + return true; + } + + private bool RunStudySession(int stackId, out string finalScore) + { + finalScore = ""; + List flashcards = _databaseService.GetFlashcardsByStackID(stackId); + if (!flashcards.Any()) + { + Console.WriteLine("\nNo flashcards in this stack!"); + Console.WriteLine("\nPress Enter to continue..."); + Console.ReadLine(); + return false; + } + + var studyData = PrepareStudyData(flashcards); + int score = StudyFlashcards(studyData); + + finalScore = $"{score}/{studyData.Count}"; + Console.WriteLine($"\nYou got a score of {finalScore}"); + return true; + } + + private Dictionary PrepareStudyData(List flashcards) + { + return flashcards.ToDictionary( + f => $"Front: {f.Front}", + f => $"{f.Back}"); + } + + private int StudyFlashcards(Dictionary cardMapping) + { + int score = 0; + var flashcardFront = cardMapping.Keys.ToList(); + + Console.WriteLine($"\nPress Enter to Start"); + Console.ReadLine(); + + foreach (var front in flashcardFront) + { + score += ProcessFlashcard(front, cardMapping[front]); + } + + return score; + } + + private int ProcessFlashcard(string front, string correctAnswer) + { + Console.Clear(); + Console.WriteLine(front); + Console.Write("\nAnswer: "); + string? answer = Console.ReadLine()?.Trim().ToLower(); + + bool isCorrect = answer == correctAnswer.ToLower(); + ShowAnswerFeedback(answer, correctAnswer, isCorrect); + + return isCorrect ? 1 : 0; + } + + private void ShowAnswerFeedback(string userAnswer, string correctAnswer, bool isCorrect) + { + Console.WriteLine($"\nAnswer = {correctAnswer.ToLower()}\n" + + $"Your Answer: {userAnswer}\n"); + + AnsiConsole.MarkupLine(isCorrect ? "[green]Correct![/]" : "[red]Incorrect![/]"); + + Console.WriteLine("\nPress enter to Continue"); + Console.ReadLine(); + } + + private void AddStudySession(int stackId, string finalScore) + { + StudySession session = new StudySession(); + + session.StackId = stackId; + session.Score = finalScore; + session.StudyDate = DateTime.Now; + + _databaseService.PostStudySession(session); + } + } +} diff --git a/FlashcardsApp/FlashcardsApp/UI/Helpers/TableVisualization.cs b/FlashcardsApp/FlashcardsApp/UI/Helpers/TableVisualization.cs new file mode 100644 index 00000000..0ec3b0a2 --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/UI/Helpers/TableVisualization.cs @@ -0,0 +1,101 @@ +using Spectre.Console; +using FlashcardsApp.Models; +using FlashcardsApp.DTOs; +using FlashcardsApp.Services; + +namespace FlashcardsApp.UI.Helpers +{ + internal class TableVisualization + { + internal static void ShowStacksTable(List stacks) + { + Console.WriteLine("\n"); + + var table = new Table(); + + table.AddColumn("ID"); + table.AddColumn("Name"); + table.AddColumn("Description"); + table.AddColumn("Date Created"); + + foreach (var stack in stacks) + { + table.AddRow( + stack.StackId.ToString(), + stack.Name, + stack.Description, + stack.CreatedDate.ToString() + ); + } + + table.Border(TableBorder.Square); + table.BorderColor(Color.Blue); + + AnsiConsole.Write(table); + Console.WriteLine("\n"); + } + + internal static void ShowFlashcardsTable(List flashcards) + { + Console.WriteLine("\n"); + + var table = new Table(); + + table.AddColumn("ID"); + table.AddColumn("Front"); + table.AddColumn("Back"); + table.AddColumn("Date Created"); + + foreach (var card in flashcards) + { + var idPoperty = typeof(FlashcardDTO).GetProperty("DisplayNumber"); + var frontProperty = typeof(FlashcardDTO).GetProperty("Front"); + var backProperty = typeof(FlashcardDTO).GetProperty("Back"); + var createdDateProperty = typeof(FlashcardDTO).GetProperty("CreatedDate"); + + table.AddRow( + idPoperty?.GetValue(card)?.ToString() ?? "NULL", + frontProperty?.GetValue(card)?.ToString() ?? "NULL", + backProperty?.GetValue(card)?.ToString() ?? "NULL", + createdDateProperty?.GetValue(card)?.ToString() ?? "NULL" + ); + } + + table.Border(TableBorder.Square); + table.BorderColor(Color.Green); + + AnsiConsole.Write(table); + Console.WriteLine("\n"); + } + + internal static void ShowStudySessionsTable(List sessions, List stacks) + { + Console.Write("\n"); + + Dictionary stackDictionary = stacks.ToDictionary(s => s.StackId, s => s.Name); + + var table = new Table(); + + table.AddColumn("Stack Studied"); + table.AddColumn("Score"); + table.AddColumn("Study Date"); + + foreach (var session in sessions) + { + string stackName = stackDictionary.GetValueOrDefault(session.StackId, "NULL"); + + table.AddRow( + stackName, + session.Score?.ToString() ?? "NULL", + session.StudyDate.ToString() + ); + } + + table.Border(TableBorder.Square); + table.BorderColor(Color.Orange1); + + AnsiConsole.Write(table); + Console.WriteLine("\n"); + } + } +} diff --git a/FlashcardsApp/FlashcardsApp/appsettings.json b/FlashcardsApp/FlashcardsApp/appsettings.json new file mode 100644 index 00000000..11f20947 --- /dev/null +++ b/FlashcardsApp/FlashcardsApp/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "Default": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=FlashcardsDB;Integrated Security=True" + } +} From d646a968a532308aa75931c62505812726b8a4aa Mon Sep 17 00:00:00 2001 From: "Soto, Dalton" Date: Wed, 24 Sep 2025 14:26:01 -0400 Subject: [PATCH 2/2] code cleanup --- .../FlashcardsApp/DTOs/FlashcardDTO.cs | 21 +- .../FlashcardsApp/Models/Flashcard.cs | 21 +- FlashcardsApp/FlashcardsApp/Models/Stack.cs | 19 +- .../FlashcardsApp/Models/StudySession.cs | 19 +- FlashcardsApp/FlashcardsApp/Program.cs | 61 ++- .../FlashcardsApp/Services/DatabaseService.cs | 406 +++++++++--------- .../FlashcardsApp/Services/UserInput.cs | 340 --------------- .../FlashcardsApp/UI/Core/InputValidator.cs | 131 +++--- .../FlashcardsApp/UI/Core/MenuHandler.cs | 108 +++-- .../FlashcardsApp/UI/Features/FlashcardUI.cs | 232 +++++----- .../FlashcardsApp/UI/Features/StackUI.cs | 267 ++++++------ .../FlashcardsApp/UI/Features/StudyUI.cs | 226 +++++----- .../UI/Helpers/TableVisualization.cs | 162 ++++--- 13 files changed, 810 insertions(+), 1203 deletions(-) delete mode 100644 FlashcardsApp/FlashcardsApp/Services/UserInput.cs diff --git a/FlashcardsApp/FlashcardsApp/DTOs/FlashcardDTO.cs b/FlashcardsApp/FlashcardsApp/DTOs/FlashcardDTO.cs index 96a6131f..8c6a6888 100644 --- a/FlashcardsApp/FlashcardsApp/DTOs/FlashcardDTO.cs +++ b/FlashcardsApp/FlashcardsApp/DTOs/FlashcardDTO.cs @@ -1,17 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace FlashcardsApp.DTOs; -namespace FlashcardsApp.DTOs +internal class FlashcardDTO { - internal class FlashcardDTO - { - public int DisplayNumber { get; set; } - public int FlashcardId { get; set; } - public string Front { get; set; } - public string Back { get; set; } - public DateTime CreatedDate { get; set; } - } + public int DisplayNumber { get; set; } + public int FlashcardId { get; set; } + public string Front { get; set; } + public string Back { get; set; } + public DateTime CreatedDate { get; set; } } diff --git a/FlashcardsApp/FlashcardsApp/Models/Flashcard.cs b/FlashcardsApp/FlashcardsApp/Models/Flashcard.cs index 2f4bb5bd..c1342ff7 100644 --- a/FlashcardsApp/FlashcardsApp/Models/Flashcard.cs +++ b/FlashcardsApp/FlashcardsApp/Models/Flashcard.cs @@ -1,17 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace FlashcardsApp.Models; -namespace FlashcardsApp.Models +internal class Flashcard { - internal class Flashcard - { - public int FlashcardId { get; set; } - public int StackId { get; set; } - public string Front { get; set; } - public string Back { get; set; } - public DateTime CreatedDate { get; set; } - } + public int FlashcardId { get; set; } + public int StackId { get; set; } + public string Front { get; set; } + public string Back { get; set; } + public DateTime CreatedDate { get; set; } } diff --git a/FlashcardsApp/FlashcardsApp/Models/Stack.cs b/FlashcardsApp/FlashcardsApp/Models/Stack.cs index 6f5fd32b..d6dd572f 100644 --- a/FlashcardsApp/FlashcardsApp/Models/Stack.cs +++ b/FlashcardsApp/FlashcardsApp/Models/Stack.cs @@ -1,16 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace FlashcardsApp.Models; -namespace FlashcardsApp.Models +internal class Stack { - internal class Stack - { - public int StackId { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public DateTime CreatedDate { get; set; } - } + public int StackId { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public DateTime CreatedDate { get; set; } } diff --git a/FlashcardsApp/FlashcardsApp/Models/StudySession.cs b/FlashcardsApp/FlashcardsApp/Models/StudySession.cs index c609c476..75801bcd 100644 --- a/FlashcardsApp/FlashcardsApp/Models/StudySession.cs +++ b/FlashcardsApp/FlashcardsApp/Models/StudySession.cs @@ -1,16 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace FlashcardsApp.Models; -namespace FlashcardsApp.Models +internal class StudySession { - internal class StudySession - { - public int SessionId { get; set; } - public int StackId { get; set; } - public string Score { get; set; } - public DateTime StudyDate { get; set; } - } + public int SessionId { get; set; } + public int StackId { get; set; } + public string Score { get; set; } + public DateTime StudyDate { get; set; } } diff --git a/FlashcardsApp/FlashcardsApp/Program.cs b/FlashcardsApp/FlashcardsApp/Program.cs index 4ff355f4..8eb95405 100644 --- a/FlashcardsApp/FlashcardsApp/Program.cs +++ b/FlashcardsApp/FlashcardsApp/Program.cs @@ -2,45 +2,44 @@ using FlashcardsApp.Services; using FlashcardsApp.UI.Core; -namespace FlashcardsApp +namespace FlashcardsApp; + +class Program { - class Program + static IConfiguration? config; // a variable of type IConfiguration + static DatabaseService? databaseService; + static void Main(string[] args) { - static IConfiguration? config; // a variable of type IConfiguration - static DatabaseService? databaseService; - static void Main(string[] args) + try { - try - { - config = new ConfigurationBuilder() // Starting with an empty configuration but will return an IConfiguration object - .SetBasePath(Directory.GetCurrentDirectory()) // tells the builder where to look for configuration files (appsettings.json) - .AddJsonFile("appsettings.json") // what file it should be reading - .Build(); // creates the the IConfiguration object - - string? connectionString = config.GetConnectionString("Default"); //GetConnectionString("Default") specifically looks for "ConnectionString" in appsettings.json - // and return the value associated with "Default" - if (connectionString == null) - { - throw new Exception("Connection string not found\n"); - - } + config = new ConfigurationBuilder() // Starting with an empty configuration but will return an IConfiguration object + .SetBasePath(Directory.GetCurrentDirectory()) // tells the builder where to look for configuration files (appsettings.json) + .AddJsonFile("appsettings.json") // what file it should be reading + .Build(); // creates the the IConfiguration object - databaseService = new(connectionString); - databaseService.TestConnection(); - - Console.WriteLine("Successfully connected to server!\n"); - } - catch (Exception ex) + string? connectionString = config.GetConnectionString("Default"); //GetConnectionString("Default") specifically looks for "ConnectionString" in appsettings.json + // and return the value associated with "Default" + if (connectionString == null) { - Console.WriteLine($"Error loading database: {ex.Message}\n"); - Console.WriteLine("Press Any Key to Exit..."); - Console.ReadKey(); - return; + throw new Exception("Connection string not found\n"); + } - MenuHandler menuHandler = new(databaseService); + databaseService = new(connectionString); + databaseService.TestConnection(); - menuHandler.MainMenu(); + Console.WriteLine("Successfully connected to server!\n"); } + catch (Exception ex) + { + Console.WriteLine($"Error loading database: {ex.Message}\n"); + Console.WriteLine("Press Any Key to Exit..."); + Console.ReadKey(); + return; + } + + MenuHandler menuHandler = new(databaseService); + + menuHandler.MainMenu(); } } \ No newline at end of file diff --git a/FlashcardsApp/FlashcardsApp/Services/DatabaseService.cs b/FlashcardsApp/FlashcardsApp/Services/DatabaseService.cs index 7d0cc447..92eb4159 100644 --- a/FlashcardsApp/FlashcardsApp/Services/DatabaseService.cs +++ b/FlashcardsApp/FlashcardsApp/Services/DatabaseService.cs @@ -1,130 +1,129 @@ using Dapper; -using Microsoft.Data.SqlClient; //for sql server connection -using FlashcardsApp.Models; using FlashcardsApp.DTOs; -using Spectre.Console; +using FlashcardsApp.Models; using FlashcardsApp.UI.Helpers; +using Microsoft.Data.SqlClient; //for sql server connection + +namespace FlashcardsApp.Services; -namespace FlashcardsApp.Services +internal class DatabaseService { - internal class DatabaseService + private readonly string _connectionString; + + internal DatabaseService(string connectionString) { - private readonly string _connectionString; + _connectionString = connectionString; + } - internal DatabaseService(string connectionString) + public void TestConnection() + { + using (var connection = new SqlConnection(_connectionString)) { - _connectionString = connectionString; - } - - public void TestConnection() - { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); - } + connection.Open(); } + } - internal void DeleteFlashcard(int stackId, int flashcardId) + internal void DeleteFlashcard(int stackId, int flashcardId) + { + using (var connection = new SqlConnection(_connectionString)) { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + connection.Open(); - var sql = "DELETE FROM Flashcards WHERE StackId = @StackId AND FlashcardId = @FlashcardId"; + var sql = "DELETE FROM Flashcards WHERE StackId = @StackId AND FlashcardId = @FlashcardId"; - var rowsAffected = connection.Execute(sql, new { StackId = stackId, FlashcardId = flashcardId }); + var rowsAffected = connection.Execute(sql, new { StackId = stackId, FlashcardId = flashcardId }); - if (rowsAffected > 0) - { - Console.WriteLine("\nDeletion successful."); - Console.WriteLine($"\n{rowsAffected} row(s) deleted."); - } - else - { - Console.WriteLine("\nDeletion has failed"); - } + if (rowsAffected > 0) + { + Console.WriteLine("\nDeletion successful."); + Console.WriteLine($"\n{rowsAffected} row(s) deleted."); + } + else + { + Console.WriteLine("\nDeletion has failed"); } } + } - internal void DeleteStack(int stackId) + internal void DeleteStack(int stackId) + { + using (var connection = new SqlConnection(_connectionString)) { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + connection.Open(); - var sql = "DELETE FROM Stacks WHERE StackId = @StackId"; + var sql = "DELETE FROM Stacks WHERE StackId = @StackId"; - var rowsAffected = connection.Execute(sql, new { StackId = stackId }); + var rowsAffected = connection.Execute(sql, new { StackId = stackId }); - if (rowsAffected > 0) - { - Console.WriteLine("\nDeletion successful."); - Console.WriteLine($"\n{rowsAffected} row(s) deleted."); - } - else - { - Console.WriteLine("\nDeletion has failed"); - } + if (rowsAffected > 0) + { + Console.WriteLine("\nDeletion successful."); + Console.WriteLine($"\n{rowsAffected} row(s) deleted."); + } + else + { + Console.WriteLine("\nDeletion has failed"); } } + } - internal void GetAllStacks() + internal void GetAllStacks() + { + using (var connection = new SqlConnection(_connectionString)) { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + connection.Open(); - var sql = "SELECT * FROM Stacks"; + var sql = "SELECT * FROM Stacks"; - var stacks = connection.Query(sql).ToList(); + var stacks = connection.Query(sql).ToList(); - TableVisualization.ShowStacksTable(stacks); - } + TableVisualization.ShowStacksTable(stacks); } + } - internal List GetAllStacksAsList() + internal List GetAllStacksAsList() + { + using (var connection = new SqlConnection(_connectionString)) { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + connection.Open(); - var sql = "SELECT * FROM Stacks"; + var sql = "SELECT * FROM Stacks"; - var stacks = connection.Query(sql).ToList(); + var stacks = connection.Query(sql).ToList(); - return stacks; - } + return stacks; } + } - internal Flashcard? GetFlashcardByFlashcardId(int flashcardId, int stackId) + internal Flashcard? GetFlashcardByFlashcardId(int flashcardId, int stackId) + { + using (var connection = new SqlConnection(_connectionString)) { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); - - var sql = "SELECT FlashcardId, StackId, Front, Back, CreatedDate FROM Flashcards WHERE StackId = @StackId AND FlashcardId = @FlashcardId"; + connection.Open(); - var flashcard = connection.QuerySingleOrDefault(sql, new { StackId = stackId, FlashcardId = flashcardId }); + var sql = "SELECT FlashcardId, StackId, Front, Back, CreatedDate FROM Flashcards WHERE StackId = @StackId AND FlashcardId = @FlashcardId"; - if (flashcard == null) - { - Console.WriteLine($"\nNo flashcard found with ID: {flashcardId} in stack {stackId}"); - return null; - } + var flashcard = connection.QuerySingleOrDefault(sql, new { StackId = stackId, FlashcardId = flashcardId }); - return flashcard; + if (flashcard == null) + { + Console.WriteLine($"\nNo flashcard found with ID: {flashcardId} in stack {stackId}"); + return null; } + + return flashcard; } + } - internal List GetFlashcardsByID(int stackId) + internal List GetFlashcardsByID(int stackId) + { + using (var connection = new SqlConnection(_connectionString)) { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + connection.Open(); - var sql = @" + var sql = @" SELECT ROW_NUMBER() OVER (ORDER BY FlashcardId) as DisplayNumber, FlashcardId, @@ -134,21 +133,21 @@ internal List GetFlashcardsByID(int stackId) FROM Flashcards WHERE StackId = @StackId"; - var flashcards = connection.Query(sql, new { StackId = stackId}).ToList(); + var flashcards = connection.Query(sql, new { StackId = stackId }).ToList(); - TableVisualization.ShowFlashcardsTable(flashcards); + TableVisualization.ShowFlashcardsTable(flashcards); - return flashcards; - } + return flashcards; } + } - internal List GetFlashcardsByStackID(int stackId) + internal List GetFlashcardsByStackID(int stackId) + { + using (var connection = new SqlConnection(_connectionString)) { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + connection.Open(); - var sql = @" + var sql = @" SELECT FlashcardId, StackId, @@ -158,153 +157,152 @@ internal List GetFlashcardsByStackID(int stackId) FROM Flashcards WHERE StackId = @StackId"; - var flashcards = connection.Query(sql, new { StackId = stackId }).ToList(); + var flashcards = connection.Query(sql, new { StackId = stackId }).ToList(); - return flashcards; - } + return flashcards; } + } - internal void GetStudyHistory() + internal void GetStudyHistory() + { + using (var connection = new SqlConnection(_connectionString)) { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + connection.Open(); - var sql = "SELECT * FROM StudySessions"; + var sql = "SELECT * FROM StudySessions"; - var sessions = connection.Query(sql).ToList(); + var sessions = connection.Query(sql).ToList(); - var sql2 = "SELECT * FROM Stacks"; + var sql2 = "SELECT * FROM Stacks"; - var stacks = connection.Query(sql2).ToList(); + var stacks = connection.Query(sql2).ToList(); - if (sessions.Count > 0) - { - TableVisualization.ShowStudySessionsTable(sessions, stacks); - } - else - { - Console.WriteLine("\nNo sessions to view!"); - } + if (sessions.Count > 0) + { + TableVisualization.ShowStudySessionsTable(sessions, stacks); + } + else + { + Console.WriteLine("\nNo sessions to view!"); } } + } - internal void Post(Stack stack) + internal void Post(Stack stack) + { + using (var connection = new SqlConnection(_connectionString)) { - using (var connection = new SqlConnection(_connectionString)) + connection.Open(); + + var sql = "INSERT INTO Stacks (Name, Description, CreatedDate) VALUES (@Name, @Description, @CreatedDate)"; + + var rowsAffected = connection.Execute(sql, new + { + Name = stack.Name, + Description = stack.Description, + CreatedDate = stack.CreatedDate, + }); + + if (rowsAffected > 0) { - connection.Open(); - - var sql = "INSERT INTO Stacks (Name, Description, CreatedDate) VALUES (@Name, @Description, @CreatedDate)"; - - var rowsAffected = connection.Execute(sql, new - { - Name = stack.Name, - Description = stack.Description, - CreatedDate = stack.CreatedDate, - }); - - if (rowsAffected > 0) - { - Console.WriteLine("\nSuccessfully added stack!"); - Console.WriteLine($"\n{rowsAffected} row(s) inserted."); - } - else - { - Console.WriteLine("\nFailed to add stack!"); - } - } + Console.WriteLine("\nSuccessfully added stack!"); + Console.WriteLine($"\n{rowsAffected} row(s) inserted."); + } + else + { + Console.WriteLine("\nFailed to add stack!"); + } } + } - internal void PostFlashcard(Flashcard flashcard) + internal void PostFlashcard(Flashcard flashcard) + { + using (var connection = new SqlConnection(_connectionString)) { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + connection.Open(); - var checkSql = @"SELECT COUNT(1) + var checkSql = @"SELECT COUNT(1) FROM Flashcards WHERE StackId = @StackId AND Front = @Front"; - var exists = connection.ExecuteScalar(checkSql, new - { - StackId = flashcard.StackId, - Front = flashcard.Front - }) > 0; - - if (exists) - { - Console.WriteLine("\nA flashcard with this front already exists in this stack!"); - return; - } - - var sql = "INSERT INTO Flashcards (StackId, Front, Back, CreatedDate) VALUES (@StackId, @Front, @Back, @CreatedDate)"; - - var rowsAffected = connection.Execute(sql, new - { - StackId = flashcard.StackId, - Front = flashcard.Front, - Back = flashcard.Back, - CreatedDate = flashcard.CreatedDate - }); - - if (rowsAffected > 0) - { - Console.WriteLine("\nSuccessfully added flashcard to stack!"); - Console.WriteLine($"\n{rowsAffected} row(s) inserted."); - } - else - { - Console.WriteLine("\nFailed to add flashcard!"); - } + var exists = connection.ExecuteScalar(checkSql, new + { + StackId = flashcard.StackId, + Front = flashcard.Front + }) > 0; + + if (exists) + { + Console.WriteLine("\nA flashcard with this front already exists in this stack!"); + return; + } + + var sql = "INSERT INTO Flashcards (StackId, Front, Back, CreatedDate) VALUES (@StackId, @Front, @Back, @CreatedDate)"; + + var rowsAffected = connection.Execute(sql, new + { + StackId = flashcard.StackId, + Front = flashcard.Front, + Back = flashcard.Back, + CreatedDate = flashcard.CreatedDate + }); + + if (rowsAffected > 0) + { + Console.WriteLine("\nSuccessfully added flashcard to stack!"); + Console.WriteLine($"\n{rowsAffected} row(s) inserted."); + } + else + { + Console.WriteLine("\nFailed to add flashcard!"); } } + } - internal void PostStudySession(StudySession session) + internal void PostStudySession(StudySession session) + { + using (var connection = new SqlConnection(_connectionString)) { - using (var connection = new SqlConnection( _connectionString)) + connection.Open(); + + var sql = "INSERT INTO StudySessions (StackId, Score, StudyDate) VALUES (@StackId, @Score, @StudyDate)"; + + var rowsAffected = connection.Execute(sql, new + { + StackId = session.StackId, + Score = session.Score, + StudyDate = session.StudyDate, + }); + + if (rowsAffected > 0) + { + Console.WriteLine("\nStudy Session was successfully uploaded!"); + Console.WriteLine($"\n{rowsAffected} row(s) inserted."); + } + else { - connection.Open(); - - var sql = "INSERT INTO StudySessions (StackId, Score, StudyDate) VALUES (@StackId, @Score, @StudyDate)"; - - var rowsAffected = connection.Execute(sql, new - { - StackId = session.StackId, - Score = session.Score, - StudyDate = session.StudyDate, - }); - - if (rowsAffected > 0) - { - Console.WriteLine("\nStudy Session was successfully uploaded!"); - Console.WriteLine($"\n{rowsAffected} row(s) inserted."); - } - else - { - Console.WriteLine("\nFailed to upload session!"); - } + Console.WriteLine("\nFailed to upload session!"); } } + } - internal void UpdateFlashcard(int stackId, int flashcardId, Flashcard flashcard) + internal void UpdateFlashcard(int stackId, int flashcardId, Flashcard flashcard) + { + using (var connection = new SqlConnection(_connectionString)) { - using (var connection = new SqlConnection(_connectionString)) + connection.Open(); + + var sql = @"UPDATE Flashcards SET Front = @Front, Back = @Back, CreatedDate = @CreatedDate WHERE StackId = @StackId AND FlashcardId = @FlashcardId"; + + var rowsAffected = connection.Execute(sql, new { - connection.Open(); - - var sql = @"UPDATE Flashcards SET Front = @Front, Back = @Back, CreatedDate = @CreatedDate WHERE StackId = @StackId AND FlashcardId = @FlashcardId"; - - var rowsAffected = connection.Execute(sql, new - { - Front = flashcard.Front, - Back = flashcard.Back, - CreatedDate = flashcard.CreatedDate, - StackId = stackId, - FlashcardId = flashcardId - }); - } + Front = flashcard.Front, + Back = flashcard.Back, + CreatedDate = flashcard.CreatedDate, + StackId = stackId, + FlashcardId = flashcardId + }); } } } diff --git a/FlashcardsApp/FlashcardsApp/Services/UserInput.cs b/FlashcardsApp/FlashcardsApp/Services/UserInput.cs deleted file mode 100644 index 75d147f4..00000000 --- a/FlashcardsApp/FlashcardsApp/Services/UserInput.cs +++ /dev/null @@ -1,340 +0,0 @@ -//using FlashcardsApp.DTOs; -//using FlashcardsApp.Models; -//using Spectre.Console; - -//namespace FlashcardsApp.Services -//{ -// internal class UserInput -// { -// private readonly DatabaseService _databaseService; - -// public UserInput(DatabaseService databaseService) -// { -// _databaseService = databaseService; -// } - -// internal void MainMenu() -// { -// Console.Clear(); -// bool closeApp = false; -// while (closeApp == false) -// { -// var choice = AnsiConsole.Prompt( -// new SelectionPrompt() -// .Title("MAIN MENU") -// .AddChoices(new[] { -// "View All Stacks", -// "Create New Stack", -// "Manage Stack", -// "Study a Stack", -// "View Study History", -// "Close Application" -// })); - -// switch (choice) -// { -// case "View All Stacks": -// _databaseService.GetAllStacks(); -// break; -// case "Create New Stack": -// CreateStack(); -// break; -// case "Manage Stack": -// StacksListMenu(); -// break; -// case "Study a Stack": -// break; -// case "View Study History": -// break; -// case "Close Application": -// closeApp = true; -// Environment.Exit(0); -// break; -// } -// } -// } - -// internal void StacksListMenu() -// { -// Console.Clear(); -// _databaseService.GetAllStacks(); - -// List stacks = _databaseService.GetAllStacksAsList(); -// List stackNames = stacks.Select(s => s.Name).ToList(); -// stackNames.Add("Return to Main Menu"); - -// var selectedStack = AnsiConsole.Prompt( -// new SelectionPrompt() -// .Title("Select a stack to manage.") -// .AddChoices(stackNames)); -// if (selectedStack == "Return to Main Menu") -// { -// MainMenu(); -// } - -// while (true) -// { -// Console.Clear(); - -// var action = AnsiConsole.Prompt( -// new SelectionPrompt() -// .Title($"Managing stack: {selectedStack}") -// .AddChoices(new[] -// { -// "View Cards", -// "Add Card", -// "Update Card", -// "Delete Card", -// "Delete this Stack", -// "Return to Stack Menu", -// "Return to Main Menu" -// })); - -// int stackId = GetStackId(selectedStack); - -// switch (action) -// { -// case "View Cards": -// _databaseService.GetFlashcardsByID(stackId); -// break; -// case "Add Card": -// CreateFlashcard(stackId); -// break; -// case "Update Card": -// UpdateFlashcard(stackId); -// break; -// case "Delete Card": -// DeleteFlashcard(stackId); -// break; -// case "Delete this Stack": -// DeleteStack(stackId, selectedStack); -// break; -// case "Return to Stack Menu": -// StacksListMenu(); -// return; -// case "Return to Main Menu": -// MainMenu(); -// return; -// } -// Console.WriteLine("\n\nPress Enter..."); -// Console.ReadLine(); -// } -// } - -// private void UpdateFlashcard(int stackId) -// { -// List flashcards = _databaseService.GetFlashcardsByID(stackId); - -// Dictionary cardMapping = flashcards.ToDictionary( -// f => $"Front: {f.Front}\t\t| Back: {f.Back}", -// f => f.FlashcardId); - -// var choices = cardMapping.Keys.ToList(); -// choices.Add("Return to Stack Menu"); - -// var selectedCard = AnsiConsole.Prompt( -// new SelectionPrompt() -// .Title("Select a card to update.") -// .AddChoices(choices)); -// if (selectedCard == "Return to Stack Menu") -// { -// StacksListMenu(); -// return; -// } - -// int flashcardId = cardMapping[selectedCard]; - -// Flashcard? flashcard = _databaseService.GetFlashcardByFlashcardId(flashcardId, stackId); -// if (flashcard == null) -// { -// return; -// } - -// bool finished = false; -// while (finished == false) -// { -// var choice = AnsiConsole.Prompt( -// new SelectionPrompt() -// .Title("Select what to update, save, or exit.") -// .AddChoices(new[] -// { -// "Front", -// "Back", -// "Save Changes", -// "Exit to Stack Menu", -// "Exit to Main Menu" -// })); - -// switch (choice) -// { -// case "Front": -// flashcard.Front = GetFrontFlashcard(); -// break; -// case "Back": -// flashcard.Back = GetBackFlashcard(); -// break; -// case "Save Changes": -// flashcard.CreatedDate = DateTime.Now; -// _databaseService.UpdateFlashcard(stackId, flashcardId, flashcard); -// finished = true; -// break; -// case "Exit to Stack Menu": -// StacksListMenu(); -// return; -// case "Exit to Main Menu": -// MainMenu(); -// return; -// } -// } - -// } - -// private void DeleteStack(int stackId, string selectedStack) -// { -// var action = AnsiConsole.Prompt( -// new SelectionPrompt() -// .Title($"\nAre you sure you want to delete '{selectedStack}' stack?") -// .AddChoices(new[] -// { -// "Yes", -// "No" -// })); - -// switch (action) -// { -// case "Yes": -// _databaseService.DeleteStack(stackId); -// Console.WriteLine("\n\nPress Enter..."); -// Console.ReadLine(); -// StacksListMenu(); -// return; -// case "No": -// return; -// } -// } - -// private void DeleteFlashcard(int stackId) -// { -// List flashcards = _databaseService.GetFlashcardsByID(stackId); - -// Dictionary cardMapping = flashcards.ToDictionary( -// f => $"Front: {f.Front}\t\t| Back: {f.Back}", -// f => f.FlashcardId -// ); -// var choices = cardMapping.Keys.ToList(); -// choices.Add("Return to Stack Menu"); - -// var selectedCard = AnsiConsole.Prompt( -// new SelectionPrompt() -// .Title("Select a card to delete.") -// .AddChoices(choices)); -// if (selectedCard == "Return to Stack Menu") -// { -// StacksListMenu(); -// return; -// } - -// int flashcardId = cardMapping[selectedCard]; -// _databaseService.DeleteFlashcard(stackId, flashcardId); -// } - -// private int GetStackId(string selectedStack) -// { -// List stacks = _databaseService.GetAllStacksAsList(); -// Stack stack = stacks.First(s => s.Name == selectedStack); -// return stack.StackId; -// } - -// private void CreateFlashcard(int stackId) -// { -// Flashcard flashcard = new(); - -// string front = GetFrontFlashcard(); - -// string back = GetBackFlashcard(); - -// flashcard.StackId = stackId; -// flashcard.Front = front; -// flashcard.Back = back; -// flashcard.CreatedDate = DateTime.Now; - -// _databaseService.PostFlashcard(flashcard); -// } - -// internal string GetFrontFlashcard() -// { -// Console.Write("\n\nEnter the content for the front of the card OR 0 to return to Stack Menu: "); -// string? front = Console.ReadLine(); - -// if (front == "0") StacksListMenu(); - -// while (string.IsNullOrEmpty(front) || front.Length > 500) -// { -// Console.WriteLine("\nFront cannot be empty or longer than 500 characcters."); -// Console.Write("\nEnter the front: "); -// front = Console.ReadLine(); -// } - -// return front; -// } - -// internal string GetBackFlashcard() -// { -// Console.Write("\n\nEnter the content for the back of the card OR 0 to return to Stack Menu: "); -// string? back = Console.ReadLine(); - -// if (back == "0") StacksListMenu(); - -// while (string.IsNullOrEmpty(back) || back.Length > 500) -// { -// Console.WriteLine("\nBack cannot be empty or longer than 500 characcters."); -// Console.Write("\nEnter the back: "); -// back = Console.ReadLine(); -// } - -// return back; -// } - -// private void CreateStack() -// { -// Stack stack = new(); - -// Console.Write("\nEnter a name for the stack of flashcards OR 0 to return to Main Menu: "); -// string? name = Console.ReadLine(); - -// if (name == "0") MainMenu(); - -// while (string.IsNullOrEmpty(name) || name.Length > 100) -// { -// Console.WriteLine("\nName cannot be empty or longer than 100 characters."); -// Console.Write("\n\nPlease enter a valid name: "); -// name = Console.ReadLine(); -// } - -// Console.Write("\nIf you would like to add a description type it here or press enter: "); -// string? description; - -// do -// { -// description = Console.ReadLine(); - -// if (string.IsNullOrWhiteSpace(description)) -// { -// description = "No description provided"; -// } - -// if (description.Length > 500) -// { -// Console.WriteLine("\nSorry description cannot be longer than 500 characters"); -// Console.Write("\nEnter description again: "); -// } -// } while (description.Length > 500); - -// stack.Name = name; -// stack.Description = description; -// stack.CreatedDate = DateTime.Now; - -// _databaseService.Post(stack); -// } -// } -//} \ No newline at end of file diff --git a/FlashcardsApp/FlashcardsApp/UI/Core/InputValidator.cs b/FlashcardsApp/FlashcardsApp/UI/Core/InputValidator.cs index b9315b3e..af507d57 100644 --- a/FlashcardsApp/FlashcardsApp/UI/Core/InputValidator.cs +++ b/FlashcardsApp/FlashcardsApp/UI/Core/InputValidator.cs @@ -1,94 +1,93 @@ using Spectre.Console; -namespace FlashcardsApp.UI.Core +namespace FlashcardsApp.UI.Core; + +public class InputValidator { - public class InputValidator + public string GetStackName() { - public string GetStackName() + while (true) { - while (true) - { - Console.Write("\nEnter a name for the stack of flashcards OR 0 to return: "); - string? name = Console.ReadLine(); + Console.Write("\nEnter a name for the stack of flashcards OR 0 to return: "); + string? name = Console.ReadLine(); - if (name == "0") - return string.Empty; + if (name == "0") + return string.Empty; - if (string.IsNullOrEmpty(name)) - { - Console.WriteLine("\nName cannot be empty."); - continue; - } - - if (name.Length > 100) - { - Console.WriteLine("\nName cannot be longer than 100 characters."); - continue; - } + if (string.IsNullOrEmpty(name)) + { + Console.WriteLine("\nName cannot be empty."); + continue; + } - return name; + if (name.Length > 100) + { + Console.WriteLine("\nName cannot be longer than 100 characters."); + continue; } + + return name; } + } + + public string GetStackDescription() + { + Console.Write("\nIf you would like to add a description type it here or press enter: "); + string? description; - public string GetStackDescription() + do { - Console.Write("\nIf you would like to add a description type it here or press enter: "); - string? description; + description = Console.ReadLine(); - do + if (string.IsNullOrWhiteSpace(description)) { - description = Console.ReadLine(); - - if (string.IsNullOrWhiteSpace(description)) - { - return "No description provided"; - } + return "No description provided"; + } - if (description.Length > 500) - { - Console.WriteLine("\nDescription cannot be longer than 500 characters"); - Console.Write("\nEnter description again: "); - } - } while (description.Length > 500); + if (description.Length > 500) + { + Console.WriteLine("\nDescription cannot be longer than 500 characters"); + Console.Write("\nEnter description again: "); + } + } while (description.Length > 500); - return description; - } + return description; + } - public string GetFlashcardContent(string side) + public string GetFlashcardContent(string side) + { + while (true) { - while (true) - { - Console.Write($"\n\nEnter the content for the {side} of the card OR 0 to return: "); - string? content = Console.ReadLine(); + Console.Write($"\n\nEnter the content for the {side} of the card OR 0 to return: "); + string? content = Console.ReadLine(); - if (content == "0") - return string.Empty; + if (content == "0") + return string.Empty; - if (string.IsNullOrEmpty(content)) - { - Console.WriteLine($"\n{side} cannot be empty."); - continue; - } - - if (content.Length > 500) - { - Console.WriteLine($"\n{side} cannot be longer than 500 characters."); - continue; - } + if (string.IsNullOrEmpty(content)) + { + Console.WriteLine($"\n{side} cannot be empty."); + continue; + } - return content; + if (content.Length > 500) + { + Console.WriteLine($"\n{side} cannot be longer than 500 characters."); + continue; } + + return content; } + } - public bool GetConfirmation(string message) - { - var choice = AnsiConsole.Prompt( - new SelectionPrompt() - .Title(message) - .AddChoices(new[] { "Yes", "No" })); + public bool GetConfirmation(string message) + { + var choice = AnsiConsole.Prompt( + new SelectionPrompt() + .Title(message) + .AddChoices(new[] { "Yes", "No" })); - return choice == "Yes"; - } + return choice == "Yes"; } } diff --git a/FlashcardsApp/FlashcardsApp/UI/Core/MenuHandler.cs b/FlashcardsApp/FlashcardsApp/UI/Core/MenuHandler.cs index 20b955bb..c1ed0b9f 100644 --- a/FlashcardsApp/FlashcardsApp/UI/Core/MenuHandler.cs +++ b/FlashcardsApp/FlashcardsApp/UI/Core/MenuHandler.cs @@ -1,69 +1,63 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FlashcardsApp.Services; +using FlashcardsApp.Services; using FlashcardsApp.UI.Features; using Spectre.Console; -namespace FlashcardsApp.UI.Core +namespace FlashcardsApp.UI.Core; + +internal class MenuHandler { - internal class MenuHandler + private readonly DatabaseService _databaseService; + private readonly StackUI _stackUI; + private readonly FlashcardUI _flashcardUI; + private readonly StudyUI _studyUI; + + internal MenuHandler(DatabaseService databaseService) { - private readonly DatabaseService _databaseService; - private readonly StackUI _stackUI; - private readonly FlashcardUI _flashcardUI; - private readonly StudyUI _studyUI; + _databaseService = databaseService; + _stackUI = new StackUI(databaseService); + _flashcardUI = new FlashcardUI(databaseService); + _studyUI = new StudyUI(databaseService); + } - internal MenuHandler(DatabaseService databaseService) + internal void MainMenu() + { + Console.Clear(); + bool closeApp = false; + while (closeApp == false) { - _databaseService = databaseService; - _stackUI = new StackUI(databaseService); - _flashcardUI = new FlashcardUI(databaseService); - _studyUI = new StudyUI(databaseService); - } + var choice = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("MAIN MENU") + .AddChoices(new[] { + "View All Stacks", + "Create New Stack", + "Manage Stack", + "Study a Stack", + "View Study History", + "Close Application" + })); - internal void MainMenu() - { - Console.Clear(); - bool closeApp = false; - while (closeApp == false) + switch (choice) { - var choice = AnsiConsole.Prompt( - new SelectionPrompt() - .Title("MAIN MENU") - .AddChoices(new[] { - "View All Stacks", - "Create New Stack", - "Manage Stack", - "Study a Stack", - "View Study History", - "Close Application" - })); - - switch (choice) - { - case "View All Stacks": - _databaseService.GetAllStacks(); - break; - case "Create New Stack": - _stackUI.CreateStack(); - break; - case "Manage Stack": - _stackUI.StacksListMenu(); - break; - case "Study a Stack": - _studyUI.StudyMain(); - break; - case "View Study History": - _databaseService.GetStudyHistory(); - break; - case "Close Application": - closeApp = true; - Environment.Exit(0); - break; - } + case "View All Stacks": + _databaseService.GetAllStacks(); + break; + case "Create New Stack": + _stackUI.CreateStack(); + break; + case "Manage Stack": + _stackUI.StacksListMenu(); + break; + case "Study a Stack": + _studyUI.StudyMain(); + break; + case "View Study History": + _databaseService.GetStudyHistory(); + break; + case "Close Application": + closeApp = true; + Environment.Exit(0); + break; } } } diff --git a/FlashcardsApp/FlashcardsApp/UI/Features/FlashcardUI.cs b/FlashcardsApp/FlashcardsApp/UI/Features/FlashcardUI.cs index a3859a32..f9b552bd 100644 --- a/FlashcardsApp/FlashcardsApp/UI/Features/FlashcardUI.cs +++ b/FlashcardsApp/FlashcardsApp/UI/Features/FlashcardUI.cs @@ -1,157 +1,151 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FlashcardsApp.DTOs; +using FlashcardsApp.DTOs; using FlashcardsApp.Models; using FlashcardsApp.Services; using FlashcardsApp.UI.Core; using Spectre.Console; -namespace FlashcardsApp.UI.Features +namespace FlashcardsApp.UI.Features; + +internal class FlashcardUI { - internal class FlashcardUI + private readonly DatabaseService _databaseService; + private readonly InputValidator _validator; + + internal FlashcardUI(DatabaseService databaseService) { - private readonly DatabaseService _databaseService; - private readonly InputValidator _validator; + _databaseService = databaseService; + _validator = new InputValidator(); + } - internal FlashcardUI(DatabaseService databaseService) - { - _databaseService = databaseService; - _validator = new InputValidator(); - } + public void ViewCards(int stackId) + { + _databaseService.GetFlashcardsByID(stackId); + } - public void ViewCards(int stackId) - { - _databaseService.GetFlashcardsByID(stackId); - } + public void CreateFlashcard(int stackId) + { + Flashcard flashcard = new(); - public void CreateFlashcard(int stackId) - { - Flashcard flashcard = new(); + string front = GetFrontContent(); + if (string.IsNullOrEmpty(front)) return; - string front = GetFrontContent(); - if (string.IsNullOrEmpty(front)) return; + string back = GetBackContent(); + if (string.IsNullOrEmpty(back)) return; - string back = GetBackContent(); - if (string.IsNullOrEmpty(back)) return; + flashcard.StackId = stackId; + flashcard.Front = front; + flashcard.Back = back; + flashcard.CreatedDate = DateTime.Now; - flashcard.StackId = stackId; - flashcard.Front = front; - flashcard.Back = back; - flashcard.CreatedDate = DateTime.Now; + _databaseService.PostFlashcard(flashcard); + Console.WriteLine("\nFlashcard created successfully!"); + } - _databaseService.PostFlashcard(flashcard); - Console.WriteLine("\nFlashcard created successfully!"); - } + public void UpdateFlashcard(int stackId) + { + List flashcards = _databaseService.GetFlashcardsByID(stackId); - public void UpdateFlashcard(int stackId) + if (!flashcards.Any()) { - List flashcards = _databaseService.GetFlashcardsByID(stackId); + Console.WriteLine("\nNo flashcards in this stack!"); + return; + } - if (!flashcards.Any()) - { - Console.WriteLine("\nNo flashcards in this stack!"); - return; - } + Dictionary cardMapping = flashcards.ToDictionary( + f => $"Front: {f.Front}\t\t| Back: {f.Back}", + f => f.FlashcardId); - Dictionary cardMapping = flashcards.ToDictionary( - f => $"Front: {f.Front}\t\t| Back: {f.Back}", - f => f.FlashcardId); + var choices = cardMapping.Keys.ToList(); + choices.Add("Return to Stack Menu"); - var choices = cardMapping.Keys.ToList(); - choices.Add("Return to Stack Menu"); + var selectedCard = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select a card to update.") + .AddChoices(choices)); - var selectedCard = AnsiConsole.Prompt( - new SelectionPrompt() - .Title("Select a card to update.") - .AddChoices(choices)); + if (selectedCard == "Return to Stack Menu") + { + return; + } - if (selectedCard == "Return to Stack Menu") - { - return; - } + int flashcardId = cardMapping[selectedCard]; - int flashcardId = cardMapping[selectedCard]; + Flashcard? flashcard = _databaseService.GetFlashcardByFlashcardId(flashcardId, stackId); + if (flashcard == null) + { + return; + } - Flashcard? flashcard = _databaseService.GetFlashcardByFlashcardId(flashcardId, stackId); - if (flashcard == null) - { - return; - } + bool finished = false; + while (!finished) + { + var choice = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select what to update, save, or exit.") + .AddChoices(new[] + { + "Front", + "Back", + "Save Changes", + "Return to Stack Menu" + })); - bool finished = false; - while (!finished) + switch (choice) { - var choice = AnsiConsole.Prompt( - new SelectionPrompt() - .Title("Select what to update, save, or exit.") - .AddChoices(new[] - { - "Front", - "Back", - "Save Changes", - "Return to Stack Menu" - })); - - switch (choice) - { - case "Front": - string newFront = GetFrontContent(); - if (!string.IsNullOrEmpty(newFront)) - flashcard.Front = newFront; - break; - case "Back": - string newBack = GetBackContent(); - if (!string.IsNullOrEmpty(newBack)) - flashcard.Back = newBack; - break; - case "Save Changes": - flashcard.CreatedDate = DateTime.Now; - _databaseService.UpdateFlashcard(stackId, flashcardId, flashcard); - finished = true; - break; - case "Return to Stack Menu": - return; - } + case "Front": + string newFront = GetFrontContent(); + if (!string.IsNullOrEmpty(newFront)) + flashcard.Front = newFront; + break; + case "Back": + string newBack = GetBackContent(); + if (!string.IsNullOrEmpty(newBack)) + flashcard.Back = newBack; + break; + case "Save Changes": + flashcard.CreatedDate = DateTime.Now; + _databaseService.UpdateFlashcard(stackId, flashcardId, flashcard); + finished = true; + break; + case "Return to Stack Menu": + return; } } + } - public void DeleteFlashcard(int stackId) - { - List flashcards = _databaseService.GetFlashcardsByID(stackId); + public void DeleteFlashcard(int stackId) + { + List flashcards = _databaseService.GetFlashcardsByID(stackId); - Dictionary cardMapping = flashcards.ToDictionary( - f => $"Front: {f.Front}\t\t| Back: {f.Back}", - f => f.FlashcardId); + Dictionary cardMapping = flashcards.ToDictionary( + f => $"Front: {f.Front}\t\t| Back: {f.Back}", + f => f.FlashcardId); - var choices = cardMapping.Keys.ToList(); - choices.Add("Return to Stack Menu"); + var choices = cardMapping.Keys.ToList(); + choices.Add("Return to Stack Menu"); - var selectedCard = AnsiConsole.Prompt( - new SelectionPrompt() - .Title("Select a card to delete.") - .AddChoices(choices)); + var selectedCard = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select a card to delete.") + .AddChoices(choices)); - if (selectedCard == "Return to Stack Menu") - { - return; - } - - int flashcardId = cardMapping[selectedCard]; - _databaseService.DeleteFlashcard(stackId, flashcardId); - } - - private string GetFrontContent() + if (selectedCard == "Return to Stack Menu") { - return _validator.GetFlashcardContent("front"); + return; } - private string GetBackContent() - { - return _validator.GetFlashcardContent("back"); - } + int flashcardId = cardMapping[selectedCard]; + _databaseService.DeleteFlashcard(stackId, flashcardId); + } + private string GetFrontContent() + { + return _validator.GetFlashcardContent("front"); } + + private string GetBackContent() + { + return _validator.GetFlashcardContent("back"); + } + } diff --git a/FlashcardsApp/FlashcardsApp/UI/Features/StackUI.cs b/FlashcardsApp/FlashcardsApp/UI/Features/StackUI.cs index b3a33c3e..0f5d5f7a 100644 --- a/FlashcardsApp/FlashcardsApp/UI/Features/StackUI.cs +++ b/FlashcardsApp/FlashcardsApp/UI/Features/StackUI.cs @@ -3,178 +3,177 @@ using FlashcardsApp.UI.Core; using Spectre.Console; -namespace FlashcardsApp.UI.Features +namespace FlashcardsApp.UI.Features; + +internal class StackUI { - internal class StackUI + private readonly DatabaseService _databaseService; + private readonly FlashcardUI _flashcardUI; + private readonly InputValidator _validator; + + internal StackUI(DatabaseService databaseService) { - private readonly DatabaseService _databaseService; - private readonly FlashcardUI _flashcardUI; - private readonly InputValidator _validator; + _databaseService = databaseService; + _flashcardUI = new FlashcardUI(databaseService); + _validator = new InputValidator(); + } - internal StackUI(DatabaseService databaseService) + public void StacksListMenu() + { + while (true) { - _databaseService = databaseService; - _flashcardUI = new FlashcardUI(databaseService); - _validator = new InputValidator(); - } + Console.Clear(); + _databaseService.GetAllStacks(); - public void StacksListMenu() - { - while (true) + List stacks = _databaseService.GetAllStacksAsList(); + if (!stacks.Any()) { - Console.Clear(); - _databaseService.GetAllStacks(); - - List stacks = _databaseService.GetAllStacksAsList(); - if (!stacks.Any()) - { - Console.WriteLine("\nNo stacks found. Create a stack first!"); - Console.WriteLine("\nPress Enter to return to main menu..."); - Console.ReadLine(); - return; - } - - List stackNames = stacks.Select(s => s.Name).ToList(); - stackNames.Add("Return to Main Menu"); + Console.WriteLine("\nNo stacks found. Create a stack first!"); + Console.WriteLine("\nPress Enter to return to main menu..."); + Console.ReadLine(); + return; + } - var selectedStack = AnsiConsole.Prompt( - new SelectionPrompt() - .Title("Select a stack to manage.") - .AddChoices(stackNames)); + List stackNames = stacks.Select(s => s.Name).ToList(); + stackNames.Add("Return to Main Menu"); - if (selectedStack == "Return to Main Menu") - { - return; - } + var selectedStack = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select a stack to manage.") + .AddChoices(stackNames)); - ManageStack(selectedStack); + if (selectedStack == "Return to Main Menu") + { + return; } + + ManageStack(selectedStack); } + } - private void ManageStack(string selectedStack) + private void ManageStack(string selectedStack) + { + while (true) { - while (true) - { - Console.Clear(); - - var action = AnsiConsole.Prompt( - new SelectionPrompt() - .Title($"Managing stack: {selectedStack}") - .AddChoices(new[] - { - "View Cards", - "Add Card", - "Update Card", - "Delete Card", - "Delete this Stack", - "Return to Stack Menu", - "Return to Main Menu" - })); - - int stackId = GetStackId(selectedStack); - if (stackId == -1) - { - Console.WriteLine("\nError accessing stack. Returning to stack menu..."); - Console.WriteLine("\nPress Enter to continue..."); - Console.ReadLine(); - return; - } + Console.Clear(); - switch (action) + var action = AnsiConsole.Prompt( + new SelectionPrompt() + .Title($"Managing stack: {selectedStack}") + .AddChoices(new[] { - case "View Cards": - _flashcardUI.ViewCards(stackId); - break; - case "Add Card": - _flashcardUI.CreateFlashcard(stackId); - break; - case "Update Card": - _flashcardUI.UpdateFlashcard(stackId); - break; - case "Delete Card": - _flashcardUI.DeleteFlashcard(stackId); - break; - case "Delete this Stack": - if (DeleteStack(stackId, selectedStack)) - return; - break; - case "Return to Stack Menu": - return; - case "Return to Main Menu": - return; - } - + "View Cards", + "Add Card", + "Update Card", + "Delete Card", + "Delete this Stack", + "Return to Stack Menu", + "Return to Main Menu" + })); + + int stackId = GetStackId(selectedStack); + if (stackId == -1) + { + Console.WriteLine("\nError accessing stack. Returning to stack menu..."); Console.WriteLine("\nPress Enter to continue..."); Console.ReadLine(); + return; } + + switch (action) + { + case "View Cards": + _flashcardUI.ViewCards(stackId); + break; + case "Add Card": + _flashcardUI.CreateFlashcard(stackId); + break; + case "Update Card": + _flashcardUI.UpdateFlashcard(stackId); + break; + case "Delete Card": + _flashcardUI.DeleteFlashcard(stackId); + break; + case "Delete this Stack": + if (DeleteStack(stackId, selectedStack)) + return; + break; + case "Return to Stack Menu": + return; + case "Return to Main Menu": + return; + } + + Console.WriteLine("\nPress Enter to continue..."); + Console.ReadLine(); } + } - public void CreateStack() - { - string name = _validator.GetStackName(); - if (string.IsNullOrEmpty(name)) - return; + public void CreateStack() + { + string name = _validator.GetStackName(); + if (string.IsNullOrEmpty(name)) + return; - string description = _validator.GetStackDescription(); + string description = _validator.GetStackDescription(); - Stack stack = new() - { - Name = name, - Description = description, - CreatedDate = DateTime.Now - }; + Stack stack = new() + { + Name = name, + Description = description, + CreatedDate = DateTime.Now + }; + + try + { + _databaseService.Post(stack); + Console.WriteLine("\nStack created successfully!"); + Console.WriteLine("\nPress Enter to continue..."); + Console.ReadLine(); + } + catch (Exception ex) + { + Console.WriteLine($"\nError creating stack: {ex.Message}"); + Console.WriteLine("\nPress Enter to continue..."); + Console.ReadLine(); + } + } + private bool DeleteStack(int stackId, string selectedStack) + { + if (_validator.GetConfirmation($"\nAre you sure you want to delete '{selectedStack}' stack?")) + { try { - _databaseService.Post(stack); - Console.WriteLine("\nStack created successfully!"); + _databaseService.DeleteStack(stackId); + Console.WriteLine("\nStack deleted successfully!"); Console.WriteLine("\nPress Enter to continue..."); Console.ReadLine(); + return true; } catch (Exception ex) { - Console.WriteLine($"\nError creating stack: {ex.Message}"); + Console.WriteLine($"\nError deleting stack: {ex.Message}"); Console.WriteLine("\nPress Enter to continue..."); Console.ReadLine(); + return false; } } + return false; + } - private bool DeleteStack(int stackId, string selectedStack) + private int GetStackId(string selectedStack) + { + try { - if (_validator.GetConfirmation($"\nAre you sure you want to delete '{selectedStack}' stack?")) - { - try - { - _databaseService.DeleteStack(stackId); - Console.WriteLine("\nStack deleted successfully!"); - Console.WriteLine("\nPress Enter to continue..."); - Console.ReadLine(); - return true; - } - catch (Exception ex) - { - Console.WriteLine($"\nError deleting stack: {ex.Message}"); - Console.WriteLine("\nPress Enter to continue..."); - Console.ReadLine(); - return false; - } - } - return false; + List stacks = _databaseService.GetAllStacksAsList(); + Stack stack = stacks.First(s => s.Name == selectedStack); + return stack.StackId; } - - private int GetStackId(string selectedStack) + catch (Exception) { - try - { - List stacks = _databaseService.GetAllStacksAsList(); - Stack stack = stacks.First(s => s.Name == selectedStack); - return stack.StackId; - } - catch (Exception) - { - Console.WriteLine("\nError finding stack."); - return -1; - } + Console.WriteLine("\nError finding stack."); + return -1; } } } diff --git a/FlashcardsApp/FlashcardsApp/UI/Features/StudyUI.cs b/FlashcardsApp/FlashcardsApp/UI/Features/StudyUI.cs index 243a5569..edf7f071 100644 --- a/FlashcardsApp/FlashcardsApp/UI/Features/StudyUI.cs +++ b/FlashcardsApp/FlashcardsApp/UI/Features/StudyUI.cs @@ -1,155 +1,149 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FlashcardsApp.Models; +using FlashcardsApp.Models; using FlashcardsApp.Services; using FlashcardsApp.UI.Core; using Spectre.Console; -namespace FlashcardsApp.UI.Features +namespace FlashcardsApp.UI.Features; + +internal class StudyUI { - internal class StudyUI - { - private readonly DatabaseService _databaseService; - private readonly InputValidator _inputValidator; + private readonly DatabaseService _databaseService; + private readonly InputValidator _inputValidator; - internal StudyUI(DatabaseService databaseService) - { - _databaseService = databaseService; - _inputValidator = new InputValidator(); - } + internal StudyUI(DatabaseService databaseService) + { + _databaseService = databaseService; + _inputValidator = new InputValidator(); + } - internal void StudyMain() + internal void StudyMain() + { + bool continueStudy = true; + while (continueStudy) { - bool continueStudy = true; - while (continueStudy) + if (!GetStackToStudy(out int stackId)) { - if (!GetStackToStudy(out int stackId)) - { - return; - } - - if (RunStudySession(stackId, out string finalScore)) - { - AddStudySession(stackId, finalScore); - } - - continueStudy = _inputValidator.GetConfirmation("Would you like to study a stack again?"); + return; } - } - private bool GetStackToStudy(out int stackId) - { - stackId = -1; - Console.Clear(); - _databaseService.GetAllStacks(); - - List stacks = _databaseService.GetAllStacksAsList(); - if (!stacks.Any()) + if (RunStudySession(stackId, out string finalScore)) { - Console.WriteLine("\nNo stacks found. Create a stack first!"); - Console.WriteLine("\nPress Enter to return to main menu..."); - Console.ReadLine(); - return false; + AddStudySession(stackId, finalScore); } - Dictionary stackMapping = stacks.ToDictionary( - s => $"Name: {s.Name} | {s.Description}", - s => s.StackId); + continueStudy = _inputValidator.GetConfirmation("Would you like to study a stack again?"); + } + } - var choices = stackMapping.Keys.ToList(); - choices.Add("Return to Main Menu"); + private bool GetStackToStudy(out int stackId) + { + stackId = -1; + Console.Clear(); + _databaseService.GetAllStacks(); - var selectedStack = AnsiConsole.Prompt( - new SelectionPrompt() - .Title("Select a stack to study.") - .AddChoices(choices)); + List stacks = _databaseService.GetAllStacksAsList(); + if (!stacks.Any()) + { + Console.WriteLine("\nNo stacks found. Create a stack first!"); + Console.WriteLine("\nPress Enter to return to main menu..."); + Console.ReadLine(); + return false; + } - if (selectedStack == "Return to Main Menu") - return false; + Dictionary stackMapping = stacks.ToDictionary( + s => $"Name: {s.Name} | {s.Description}", + s => s.StackId); - stackId = stackMapping[selectedStack]; - return true; - } + var choices = stackMapping.Keys.ToList(); + choices.Add("Return to Main Menu"); - private bool RunStudySession(int stackId, out string finalScore) - { - finalScore = ""; - List flashcards = _databaseService.GetFlashcardsByStackID(stackId); - if (!flashcards.Any()) - { - Console.WriteLine("\nNo flashcards in this stack!"); - Console.WriteLine("\nPress Enter to continue..."); - Console.ReadLine(); - return false; - } + var selectedStack = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select a stack to study.") + .AddChoices(choices)); - var studyData = PrepareStudyData(flashcards); - int score = StudyFlashcards(studyData); + if (selectedStack == "Return to Main Menu") + return false; - finalScore = $"{score}/{studyData.Count}"; - Console.WriteLine($"\nYou got a score of {finalScore}"); - return true; - } + stackId = stackMapping[selectedStack]; + return true; + } - private Dictionary PrepareStudyData(List flashcards) + private bool RunStudySession(int stackId, out string finalScore) + { + finalScore = ""; + List flashcards = _databaseService.GetFlashcardsByStackID(stackId); + if (!flashcards.Any()) { - return flashcards.ToDictionary( - f => $"Front: {f.Front}", - f => $"{f.Back}"); + Console.WriteLine("\nNo flashcards in this stack!"); + Console.WriteLine("\nPress Enter to continue..."); + Console.ReadLine(); + return false; } - private int StudyFlashcards(Dictionary cardMapping) - { - int score = 0; - var flashcardFront = cardMapping.Keys.ToList(); + var studyData = PrepareStudyData(flashcards); + int score = StudyFlashcards(studyData); - Console.WriteLine($"\nPress Enter to Start"); - Console.ReadLine(); + finalScore = $"{score}/{studyData.Count}"; + Console.WriteLine($"\nYou got a score of {finalScore}"); + return true; + } - foreach (var front in flashcardFront) - { - score += ProcessFlashcard(front, cardMapping[front]); - } + private Dictionary PrepareStudyData(List flashcards) + { + return flashcards.ToDictionary( + f => $"Front: {f.Front}", + f => $"{f.Back}"); + } - return score; - } + private int StudyFlashcards(Dictionary cardMapping) + { + int score = 0; + var flashcardFront = cardMapping.Keys.ToList(); + + Console.WriteLine($"\nPress Enter to Start"); + Console.ReadLine(); - private int ProcessFlashcard(string front, string correctAnswer) + foreach (var front in flashcardFront) { - Console.Clear(); - Console.WriteLine(front); - Console.Write("\nAnswer: "); - string? answer = Console.ReadLine()?.Trim().ToLower(); + score += ProcessFlashcard(front, cardMapping[front]); + } - bool isCorrect = answer == correctAnswer.ToLower(); - ShowAnswerFeedback(answer, correctAnswer, isCorrect); + return score; + } - return isCorrect ? 1 : 0; - } + private int ProcessFlashcard(string front, string correctAnswer) + { + Console.Clear(); + Console.WriteLine(front); + Console.Write("\nAnswer: "); + string? answer = Console.ReadLine()?.Trim().ToLower(); - private void ShowAnswerFeedback(string userAnswer, string correctAnswer, bool isCorrect) - { - Console.WriteLine($"\nAnswer = {correctAnswer.ToLower()}\n" + - $"Your Answer: {userAnswer}\n"); + bool isCorrect = answer == correctAnswer.ToLower(); + ShowAnswerFeedback(answer, correctAnswer, isCorrect); - AnsiConsole.MarkupLine(isCorrect ? "[green]Correct![/]" : "[red]Incorrect![/]"); - - Console.WriteLine("\nPress enter to Continue"); - Console.ReadLine(); - } + return isCorrect ? 1 : 0; + } - private void AddStudySession(int stackId, string finalScore) - { - StudySession session = new StudySession(); + private void ShowAnswerFeedback(string userAnswer, string correctAnswer, bool isCorrect) + { + Console.WriteLine($"\nAnswer = {correctAnswer.ToLower()}\n" + + $"Your Answer: {userAnswer}\n"); - session.StackId = stackId; - session.Score = finalScore; - session.StudyDate = DateTime.Now; + AnsiConsole.MarkupLine(isCorrect ? "[green]Correct![/]" : "[red]Incorrect![/]"); - _databaseService.PostStudySession(session); - } + Console.WriteLine("\nPress enter to Continue"); + Console.ReadLine(); + } + + private void AddStudySession(int stackId, string finalScore) + { + StudySession session = new StudySession(); + + session.StackId = stackId; + session.Score = finalScore; + session.StudyDate = DateTime.Now; + + _databaseService.PostStudySession(session); } } diff --git a/FlashcardsApp/FlashcardsApp/UI/Helpers/TableVisualization.cs b/FlashcardsApp/FlashcardsApp/UI/Helpers/TableVisualization.cs index 0ec3b0a2..48f7af57 100644 --- a/FlashcardsApp/FlashcardsApp/UI/Helpers/TableVisualization.cs +++ b/FlashcardsApp/FlashcardsApp/UI/Helpers/TableVisualization.cs @@ -1,101 +1,99 @@ -using Spectre.Console; +using FlashcardsApp.DTOs; using FlashcardsApp.Models; -using FlashcardsApp.DTOs; -using FlashcardsApp.Services; +using Spectre.Console; -namespace FlashcardsApp.UI.Helpers +namespace FlashcardsApp.UI.Helpers; + +internal class TableVisualization { - internal class TableVisualization + internal static void ShowStacksTable(List stacks) { - internal static void ShowStacksTable(List stacks) + Console.WriteLine("\n"); + + var table = new Table(); + + table.AddColumn("ID"); + table.AddColumn("Name"); + table.AddColumn("Description"); + table.AddColumn("Date Created"); + + foreach (var stack in stacks) { - Console.WriteLine("\n"); - - var table = new Table(); - - table.AddColumn("ID"); - table.AddColumn("Name"); - table.AddColumn("Description"); - table.AddColumn("Date Created"); - - foreach (var stack in stacks) - { - table.AddRow( - stack.StackId.ToString(), - stack.Name, - stack.Description, - stack.CreatedDate.ToString() - ); - } - - table.Border(TableBorder.Square); - table.BorderColor(Color.Blue); - - AnsiConsole.Write(table); - Console.WriteLine("\n"); + table.AddRow( + stack.StackId.ToString(), + stack.Name, + stack.Description, + stack.CreatedDate.ToString() + ); } - internal static void ShowFlashcardsTable(List flashcards) + table.Border(TableBorder.Square); + table.BorderColor(Color.Blue); + + AnsiConsole.Write(table); + Console.WriteLine("\n"); + } + + internal static void ShowFlashcardsTable(List flashcards) + { + Console.WriteLine("\n"); + + var table = new Table(); + + table.AddColumn("ID"); + table.AddColumn("Front"); + table.AddColumn("Back"); + table.AddColumn("Date Created"); + + foreach (var card in flashcards) { - Console.WriteLine("\n"); - - var table = new Table(); - - table.AddColumn("ID"); - table.AddColumn("Front"); - table.AddColumn("Back"); - table.AddColumn("Date Created"); - - foreach (var card in flashcards) - { - var idPoperty = typeof(FlashcardDTO).GetProperty("DisplayNumber"); - var frontProperty = typeof(FlashcardDTO).GetProperty("Front"); - var backProperty = typeof(FlashcardDTO).GetProperty("Back"); - var createdDateProperty = typeof(FlashcardDTO).GetProperty("CreatedDate"); - - table.AddRow( - idPoperty?.GetValue(card)?.ToString() ?? "NULL", - frontProperty?.GetValue(card)?.ToString() ?? "NULL", - backProperty?.GetValue(card)?.ToString() ?? "NULL", - createdDateProperty?.GetValue(card)?.ToString() ?? "NULL" - ); - } - - table.Border(TableBorder.Square); - table.BorderColor(Color.Green); - - AnsiConsole.Write(table); - Console.WriteLine("\n"); + var idPoperty = typeof(FlashcardDTO).GetProperty("DisplayNumber"); + var frontProperty = typeof(FlashcardDTO).GetProperty("Front"); + var backProperty = typeof(FlashcardDTO).GetProperty("Back"); + var createdDateProperty = typeof(FlashcardDTO).GetProperty("CreatedDate"); + + table.AddRow( + idPoperty?.GetValue(card)?.ToString() ?? "NULL", + frontProperty?.GetValue(card)?.ToString() ?? "NULL", + backProperty?.GetValue(card)?.ToString() ?? "NULL", + createdDateProperty?.GetValue(card)?.ToString() ?? "NULL" + ); } - internal static void ShowStudySessionsTable(List sessions, List stacks) - { - Console.Write("\n"); + table.Border(TableBorder.Square); + table.BorderColor(Color.Green); - Dictionary stackDictionary = stacks.ToDictionary(s => s.StackId, s => s.Name); + AnsiConsole.Write(table); + Console.WriteLine("\n"); + } - var table = new Table(); + internal static void ShowStudySessionsTable(List sessions, List stacks) + { + Console.Write("\n"); - table.AddColumn("Stack Studied"); - table.AddColumn("Score"); - table.AddColumn("Study Date"); + Dictionary stackDictionary = stacks.ToDictionary(s => s.StackId, s => s.Name); - foreach (var session in sessions) - { - string stackName = stackDictionary.GetValueOrDefault(session.StackId, "NULL"); - - table.AddRow( - stackName, - session.Score?.ToString() ?? "NULL", - session.StudyDate.ToString() - ); - } + var table = new Table(); - table.Border(TableBorder.Square); - table.BorderColor(Color.Orange1); + table.AddColumn("Stack Studied"); + table.AddColumn("Score"); + table.AddColumn("Study Date"); - AnsiConsole.Write(table); - Console.WriteLine("\n"); + foreach (var session in sessions) + { + string stackName = stackDictionary.GetValueOrDefault(session.StackId, "NULL"); + + table.AddRow( + stackName, + session.Score?.ToString() ?? "NULL", + session.StudyDate.ToString() + ); } + + table.Border(TableBorder.Square); + table.BorderColor(Color.Orange1); + + AnsiConsole.Write(table); + Console.WriteLine("\n"); } }