diff --git a/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.ApplicationCore/Interfaces/IBookRepository.cs b/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.ApplicationCore/Interfaces/IBookRepository.cs new file mode 100644 index 0000000..93e363b --- /dev/null +++ b/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.ApplicationCore/Interfaces/IBookRepository.cs @@ -0,0 +1,9 @@ +using Library.ApplicationCore.Entities; + +namespace Library.ApplicationCore; + +public interface IBookRepository +{ + Task SearchBookByTitle(string title); + Task> GetLoansByBookId(int bookId); +} diff --git a/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Console/CommonActions.cs b/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Console/CommonActions.cs index 681f95c..a002da6 100644 --- a/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Console/CommonActions.cs +++ b/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Console/CommonActions.cs @@ -9,5 +9,6 @@ public enum CommonActions SearchPatrons = 4, RenewPatronMembership = 8, ReturnLoanedBook = 16, - ExtendLoanedBook = 32 + ExtendLoanedBook = 32, + SearchBooks = 64 } diff --git a/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Console/ConsoleApp.cs b/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Console/ConsoleApp.cs index 9fc9750..f26fc9b 100644 --- a/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Console/ConsoleApp.cs +++ b/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Console/ConsoleApp.cs @@ -2,6 +2,7 @@ using Library.ApplicationCore.Entities; using Library.ApplicationCore.Enums; using Library.Console; +using Library.Infrastructure.Data; public class ConsoleApp { @@ -16,13 +17,15 @@ public class ConsoleApp ILoanRepository _loanRepository; ILoanService _loanService; IPatronService _patronService; + JsonData _jsonData; - public ConsoleApp(ILoanService loanService, IPatronService patronService, IPatronRepository patronRepository, ILoanRepository loanRepository) + public ConsoleApp(ILoanService loanService, IPatronService patronService, IPatronRepository patronRepository, ILoanRepository loanRepository, JsonData jsonData) { _patronRepository = patronRepository; _loanRepository = loanRepository; _loanService = loanService; _patronService = patronService; + _jsonData = jsonData; } public async Task Run() @@ -94,7 +97,7 @@ static void PrintPatronsList(List matchingPatrons) async Task PatronSearchResults() { - CommonActions options = CommonActions.Select | CommonActions.SearchPatrons | CommonActions.Quit; + CommonActions options = CommonActions.Select | CommonActions.SearchPatrons | CommonActions.SearchBooks | CommonActions.Quit; CommonActions action = ReadInputOptions(options, out int selectedPatronNumber); if (action == CommonActions.Select) { @@ -110,6 +113,10 @@ async Task PatronSearchResults() return ConsoleState.PatronSearchResults; } } + else if (action == CommonActions.SearchBooks) + { + return ConsoleState.PatronSearchResults; + } else if (action == CommonActions.Quit) { return ConsoleState.Quit; @@ -124,6 +131,7 @@ async Task PatronSearchResults() static CommonActions ReadInputOptions(CommonActions options, out int optionNumber) { + CommonActions action; optionNumber = 0; do @@ -136,6 +144,7 @@ static CommonActions ReadInputOptions(CommonActions options, out int optionNumbe { "q" when options.HasFlag(CommonActions.Quit) => CommonActions.Quit, "s" when options.HasFlag(CommonActions.SearchPatrons) => CommonActions.SearchPatrons, + "b" when options.HasFlag(CommonActions.SearchBooks) => CommonActions.SearchBooks, "m" when options.HasFlag(CommonActions.RenewPatronMembership) => CommonActions.RenewPatronMembership, "e" when options.HasFlag(CommonActions.ExtendLoanedBook) => CommonActions.ExtendLoanedBook, "r" when options.HasFlag(CommonActions.ReturnLoanedBook) => CommonActions.ReturnLoanedBook, @@ -153,6 +162,7 @@ _ when int.TryParse(userInput, out optionNumber) => CommonActions.Select, static void WriteInputOptions(CommonActions options) { + Console.WriteLine("Input Options:"); if (options.HasFlag(CommonActions.ReturnLoanedBook)) { @@ -170,6 +180,10 @@ static void WriteInputOptions(CommonActions options) { Console.WriteLine(" - \"s\" for new search"); } + if (options.HasFlag(CommonActions.SearchBooks)) + { + Console.WriteLine(" - \"b\" to check for book availability"); + } if (options.HasFlag(CommonActions.Quit)) { Console.WriteLine(" - \"q\" to quit"); @@ -193,7 +207,7 @@ async Task PatronDetails() loanNumber++; } - CommonActions options = CommonActions.SearchPatrons | CommonActions.Quit | CommonActions.Select | CommonActions.RenewPatronMembership; + CommonActions options = CommonActions.SearchPatrons | CommonActions.Quit | CommonActions.Select | CommonActions.RenewPatronMembership | CommonActions.SearchBooks; CommonActions action = ReadInputOptions(options, out int selectedLoanNumber); if (action == CommonActions.Select) { @@ -225,10 +239,67 @@ async Task PatronDetails() selectedPatronDetails = (await _patronRepository.GetPatron(selectedPatronDetails.Id))!; return ConsoleState.PatronDetails; } + else if (action == CommonActions.SearchBooks) + { + return await SearchBooks(); + } throw new InvalidOperationException("An input option is not handled."); } + async Task SearchBooks() + { + // Ensure data is loaded + await _jsonData.EnsureDataLoaded(); + + string? bookTitle = null; + while (String.IsNullOrWhiteSpace(bookTitle)) + { + Console.Write("Enter a book title to search for: "); + bookTitle = Console.ReadLine(); + } + + // Use FirstOrDefault to find a book in Books.json (case-insensitive) + Book? foundBook = _jsonData.Books?.FirstOrDefault(b => + b.Title.Contains(bookTitle, StringComparison.OrdinalIgnoreCase)); + + if (foundBook == null) + { + Console.WriteLine($"No book found with title: {bookTitle}"); + return ConsoleState.PatronDetails; + } + + // Retrieve the corresponding BookItem using the BookId from BookItems.json + var bookItems = _jsonData.BookItems?.Where(bi => bi.BookId == foundBook.Id).ToList(); + + // Check Loans.json for an active loan (loan.ReturnDate == null) for the BookItem + Loan? activeLoan = null; + if (bookItems != null && bookItems.Count > 0) + { + foreach (var bookItem in bookItems) + { + activeLoan = _jsonData.Loans?.FirstOrDefault(l => + l.BookItemId == bookItem.Id && l.ReturnDate == null); + if (activeLoan != null) + { + break; + } + } + } + + // Display whether the book is available for loan or currently on loan with the due date + if (activeLoan == null) + { + Console.WriteLine($"\"{foundBook.Title}\" is available for loan"); + } + else + { + Console.WriteLine($"\"{foundBook.Title}\" is on loan to another patron. The return due date is {activeLoan.DueDate}"); + } + + return ConsoleState.PatronDetails; + } + async Task LoanDetails() { Console.WriteLine($"Book title: {selectedLoanDetails.BookItem!.Book!.Title}"); diff --git a/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Console/Program.cs b/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Console/Program.cs index 1a21671..dda7826 100644 --- a/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Console/Program.cs +++ b/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Console/Program.cs @@ -10,6 +10,7 @@ .AddJsonFile("appSettings.json") .Build(); + services.AddSingleton(configuration); services.AddScoped(); diff --git a/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Infrastructure/Data/JsonBookRepository.cs b/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Infrastructure/Data/JsonBookRepository.cs new file mode 100644 index 0000000..882cd70 --- /dev/null +++ b/LabFiles/03-develop-code-features/AccelerateDevGHCopilot/src/Library.Infrastructure/Data/JsonBookRepository.cs @@ -0,0 +1,39 @@ +using Library.ApplicationCore; +using Library.ApplicationCore.Entities; + +namespace Library.Infrastructure.Data; + +public class JsonBookRepository : IBookRepository +{ + private readonly JsonData _jsonData; + + public JsonBookRepository(JsonData jsonData) + { + _jsonData = jsonData; + } + + public async Task SearchBookByTitle(string title) + { + await _jsonData.EnsureDataLoaded(); + + // Case-insensitive search + return _jsonData.Books?.FirstOrDefault(b => + b.Title.Contains(title, StringComparison.OrdinalIgnoreCase)); + } + + public async Task> GetLoansByBookId(int bookId) + { + await _jsonData.EnsureDataLoaded(); + + var loans = new List(); + foreach (var loan in _jsonData.Loans!) + { + var bookItem = _jsonData.BookItems?.FirstOrDefault(bi => bi.Id == loan.BookItemId); + if (bookItem?.BookId == bookId) + { + loans.Add(loan); + } + } + return loans; + } +}