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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions LabFiles/02-analyze-document-code/AccelerateDevGHCopilot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Library App

## Description

Library App is a .NET console application for managing library operations such as patron search, loan tracking, membership renewals, and loan status updates. The application follows a layered architecture with separate domain, infrastructure, and console presentation components, and uses JSON files as its data store.

## Project Structure

- `AccelerateDevGHCopilot/`
- `src/`
- `Library.ApplicationCore/`
- `Entities/` - Domain models such as `Author`, `Book`, `BookItem`, `Loan`, and `Patron`.
- `Enums/` - Status enums used across the application.
- `Interfaces/` - Contracts for repositories and services.
- `Services/` - Business logic for library workflows.
- `Library.ApplicationCore.csproj` - Project file for the application core layer.
- `Library.Console/`
- `Program.cs` - Application startup and dependency injection wiring.
- `ConsoleApp.cs` - Main console flow and interaction logic.
- `CommonActions.cs` - Shared action options for the console UI.
- `ConsoleState.cs` - State management for the console app.
- `appSettings.json` - Runtime configuration.
- `Json/` - JSON seed data used by the sample app.
- `Library.Console.csproj` - Project file for the console application.
- `Library.Infrastructure/`
- `Data/` - JSON-backed repository implementations.
- `Library.Infrastructure.csproj` - Project file for the infrastructure layer.
- `tests/`
- `UnitTests/` - Unit tests that validate application behavior.
- `UnitTests.csproj` - Test project file.

## Key Classes and Interfaces

- `Patron` - Represents a library patron and membership information.
- `Loan` - Represents a loan transaction and associated dates.
- `Book` - Represents a book in the library catalog.
- `BookItem` - Represents an individual physical copy of a book.
- `Author` - Represents a book author.
- `IPatronRepository` - Defines patron data access operations.
- `ILoanRepository` - Defines loan data access operations.
- `IPatronService` - Defines patron business services.
- `ILoanService` - Defines loan business services.
- `PatronService` - Implements patron-related logic.
- `LoanService` - Implements loan-related logic.
- `JsonData` - Loads and saves JSON data and builds populated object graphs.
- `JsonPatronRepository` - Accesses patron records from JSON-backed storage.
- `JsonLoanRepository` - Accesses loan records from JSON-backed storage.
- `ConsoleApp` - Controls the main console user experience.

## Usage

1. Open the solution in Visual Studio Code.
2. Restore dependencies and build the solution:
```bash
dotnet build
```
3. Run the console application:
```bash
dotnet run --project src/Library.Console/Library.Console.csproj
```
4. Follow the interactive prompts to search for patrons, inspect loans, renew memberships, extend loans, and return books.
5. Run the unit tests:
```bash
dotnet test tests/UnitTests/UnitTests.csproj
```

## License

This project is licensed under the MIT License. See the `LICENSE` file for details.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ public enum CommonActions
Select = 1,
Quit = 2,
SearchPatrons = 4,
RenewPatronMembership = 8,
ReturnLoanedBook = 16,
ExtendLoanedBook = 32
SearchBooks = 8,
RenewPatronMembership = 16,
ReturnLoanedBook = 32,
ExtendLoanedBook = 64
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Library.ApplicationCore.Entities;
using Library.ApplicationCore.Enums;
using Library.Console;
using Library.Infrastructure.Data;

public class ConsoleApp
{
Expand All @@ -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()
Expand Down Expand Up @@ -136,6 +139,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,
Expand Down Expand Up @@ -170,6 +174,10 @@ static void WriteInputOptions(CommonActions options)
{
Console.WriteLine(" - \"s\" for new search");
}
if (options.HasFlag(CommonActions.SearchBooks))
{
Console.WriteLine(" - \"b\" to check if a book is available for loan");
}
if (options.HasFlag(CommonActions.Quit))
{
Console.WriteLine(" - \"q\" to quit");
Expand All @@ -193,7 +201,7 @@ async Task<ConsoleState> PatronDetails()
loanNumber++;
}

CommonActions options = CommonActions.SearchPatrons | CommonActions.Quit | CommonActions.Select | CommonActions.RenewPatronMembership;
CommonActions options = CommonActions.SearchPatrons | CommonActions.SearchBooks | CommonActions.Quit | CommonActions.Select | CommonActions.RenewPatronMembership;
CommonActions action = ReadInputOptions(options, out int selectedLoanNumber);
if (action == CommonActions.Select)
{
Expand All @@ -217,6 +225,10 @@ async Task<ConsoleState> PatronDetails()
{
return ConsoleState.PatronSearch;
}
else if (action == CommonActions.SearchBooks)
{
return await SearchBooks();
}
else if (action == CommonActions.RenewPatronMembership)
{
var status = await _patronService.RenewMembership(selectedPatronDetails.Id);
Expand All @@ -229,6 +241,52 @@ async Task<ConsoleState> PatronDetails()
throw new InvalidOperationException("An input option is not handled.");
}

async Task<ConsoleState> SearchBooks()
{
Console.Write("Enter a book title to search for: ");
string? searchInput = Console.ReadLine();

if (string.IsNullOrWhiteSpace(searchInput))
{
Console.WriteLine("Please enter a valid title.");
return ConsoleState.PatronDetails;
}

await _jsonData.EnsureDataLoaded();

var requestedBook = _jsonData.Books?
.FirstOrDefault(book => book.Title?.Contains(searchInput, StringComparison.OrdinalIgnoreCase) == true);

if (requestedBook == null)
{
Console.WriteLine($"No matching book found for '{searchInput}'.");
return ConsoleState.PatronDetails;
}

var matchingBookItem = _jsonData.BookItems?
.FirstOrDefault(bookItem => bookItem.BookId == requestedBook.Id);

if (matchingBookItem == null)
{
Console.WriteLine($"{requestedBook.Title} is available for loan.");
return ConsoleState.PatronDetails;
}

var activeLoan = _jsonData.Loans?
.FirstOrDefault(loan => loan.BookItemId == matchingBookItem.Id && loan.ReturnDate == null);

if (activeLoan == null)
{
Console.WriteLine($"{requestedBook.Title} is available for loan.");
}
else
{
Console.WriteLine($"{requestedBook.Title} is on loan to another patron. The return due date is {activeLoan.DueDate}.");
}

return ConsoleState.PatronDetails;
}

async Task<ConsoleState> LoanDetails()
{
Console.WriteLine($"Book title: {selectedLoanDetails.BookItem!.Book!.Title}");
Expand Down