mirror of
https://github.com/claunia/marechai.git
synced 2026-07-08 17:57:08 +00:00
feat: Implement book filtering and retrieval features
- Added BooksListFilterContext to manage book filtering criteria. - Enhanced BooksService with methods to get book counts, minimum and maximum publication years, and retrieve books by letter and year. - Created new API endpoints in BooksController for counting books, fetching minimum and maximum years, and retrieving books by letter and year. - Introduced new request builders for handling API requests related to books by letter and year. - Updated kiota-lock.json to reflect new API description location. - Added localized strings for new book-related UI elements.
This commit is contained in:
@@ -189,6 +189,7 @@ public partial class App : PrismApplication
|
||||
containerRegistry.RegisterSingleton<SoftwareReleasesService>();
|
||||
containerRegistry.RegisterSingleton<IComputersListFilterContext, ComputersListFilterContext>();
|
||||
containerRegistry.RegisterSingleton<IConsolesListFilterContext, ConsolesListFilterContext>();
|
||||
containerRegistry.RegisterSingleton<IBooksListFilterContext, BooksListFilterContext>();
|
||||
|
||||
// Register ViewModels explicitly — RegisterForNavigation creates conditional
|
||||
// (keyed) registrations that the ViewModelLocator can't resolve by type alone
|
||||
@@ -201,6 +202,9 @@ public partial class App : PrismApplication
|
||||
containerRegistry.Register<ConsolesListViewModel>();
|
||||
containerRegistry.Register<CompaniesViewModel>();
|
||||
containerRegistry.Register<CompanyDetailViewModel>();
|
||||
containerRegistry.Register<BooksViewModel>();
|
||||
containerRegistry.Register<BooksListViewModel>();
|
||||
containerRegistry.Register<BookViewViewModel>();
|
||||
containerRegistry.Register<MachineViewViewModel>();
|
||||
containerRegistry.Register<PhotoDetailViewModel>();
|
||||
containerRegistry.Register<GpusListViewModel>();
|
||||
@@ -245,6 +249,9 @@ public partial class App : PrismApplication
|
||||
containerRegistry.RegisterForNavigation<ConsolesListPage, ConsolesListViewModel>();
|
||||
containerRegistry.RegisterForNavigation<CompaniesPage, CompaniesViewModel>();
|
||||
containerRegistry.RegisterForNavigation<CompanyDetailPage, CompanyDetailViewModel>();
|
||||
containerRegistry.RegisterForNavigation<BooksPage, BooksViewModel>();
|
||||
containerRegistry.RegisterForNavigation<BooksListPage, BooksListViewModel>();
|
||||
containerRegistry.RegisterForNavigation<BookViewPage, BookViewViewModel>();
|
||||
containerRegistry.RegisterForNavigation<MachineViewPage, MachineViewViewModel>();
|
||||
containerRegistry.RegisterForNavigation<PhotoDetailPage, PhotoDetailViewModel>();
|
||||
containerRegistry.RegisterForNavigation<GpuListPage, GpusListViewModel>();
|
||||
|
||||
18
Marechai.App/Presentation/Models/BookListItem.cs
Normal file
18
Marechai.App/Presentation/Models/BookListItem.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
|
||||
namespace Marechai.App.Presentation.Models;
|
||||
|
||||
[Bindable]
|
||||
public partial class BookListItem : ObservableObject
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public int? Year { get; set; }
|
||||
public string? Authors { get; set; }
|
||||
public Guid? CoverGuid { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
private ImageSource? _coverThumbnailSource;
|
||||
}
|
||||
385
Marechai.App/Presentation/ViewModels/BookViewViewModel.cs
Normal file
385
Marechai.App/Presentation/ViewModels/BookViewViewModel.cs
Normal file
@@ -0,0 +1,385 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Marechai.App.Navigation;
|
||||
using Marechai.App.Presentation.Views;
|
||||
using Marechai.App.Services;
|
||||
using Marechai.App.Services.Caching;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
|
||||
namespace Marechai.App.Presentation.ViewModels;
|
||||
|
||||
[Bindable]
|
||||
public partial class BookViewViewModel : ObservableObject, IRegionAware
|
||||
{
|
||||
private readonly BookCoverCache _coverCache;
|
||||
private readonly BooksService _booksService;
|
||||
private readonly ImageSourceFactory _imageSourceFactory;
|
||||
private readonly IStringLocalizer _localizer;
|
||||
private readonly ILogger<BookViewViewModel> _logger;
|
||||
private readonly IRegionManager _regionManager;
|
||||
|
||||
private string? _navigationSource;
|
||||
private long _currentBookId;
|
||||
private long? _sourceNavigationBookId;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _bookTitle = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? _nativeTitle;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? _publishedDisplay;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? _country;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? _isbn;
|
||||
|
||||
[ObservableProperty]
|
||||
private short? _pages;
|
||||
|
||||
[ObservableProperty]
|
||||
private int? _edition;
|
||||
|
||||
[ObservableProperty]
|
||||
private ImageSource? _coverImageSource;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _hasCover;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? _synopsisText;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? _previousBookTitle;
|
||||
|
||||
[ObservableProperty]
|
||||
private long? _previousBookId;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? _sourceBookTitle;
|
||||
|
||||
[ObservableProperty]
|
||||
private long? _sourceBookId;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _errorMessage = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _hasError;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isDataLoaded;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isLoading;
|
||||
|
||||
// Visibility flags
|
||||
[ObservableProperty]
|
||||
private Visibility _showNativeTitle = Visibility.Collapsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _showPublished = Visibility.Collapsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _showCountry = Visibility.Collapsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _showIsbn = Visibility.Collapsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _showPages = Visibility.Collapsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _showEdition = Visibility.Collapsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _showSynopsis = Visibility.Collapsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _showPeople = Visibility.Collapsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _showCompanies = Visibility.Collapsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _showMachines = Visibility.Collapsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _showMachineFamilies = Visibility.Collapsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _showPreviousBook = Visibility.Collapsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _showSourceBook = Visibility.Collapsed;
|
||||
|
||||
public BookViewViewModel(ILogger<BookViewViewModel> logger, IRegionManager regionManager,
|
||||
BooksService booksService, BookCoverCache coverCache,
|
||||
IStringLocalizer localizer, ImageSourceFactory imageSourceFactory)
|
||||
{
|
||||
_logger = logger;
|
||||
_regionManager = regionManager;
|
||||
_booksService = booksService;
|
||||
_coverCache = coverCache;
|
||||
_localizer = localizer;
|
||||
_imageSourceFactory = imageSourceFactory;
|
||||
}
|
||||
|
||||
public ObservableCollection<string> People { get; } = [];
|
||||
public ObservableCollection<string> Companies { get; } = [];
|
||||
public ObservableCollection<string> Machines { get; } = [];
|
||||
public ObservableCollection<string> MachineFamilies { get; } = [];
|
||||
|
||||
public bool IsNavigationTarget(NavigationContext navigationContext) => false;
|
||||
|
||||
public void OnNavigatedFrom(NavigationContext navigationContext) { }
|
||||
|
||||
public void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
if(navigationContext.Parameters.TryGetValue<string>(NavParamKeys.NavigationSource, out string? source))
|
||||
_navigationSource = source;
|
||||
|
||||
if(navigationContext.Parameters.TryGetValue<long>("SourceNavigationBookId", out long sourceBookNavId))
|
||||
_sourceNavigationBookId = sourceBookNavId;
|
||||
|
||||
if(navigationContext.Parameters.TryGetValue<long>(NavParamKeys.BookId, out long bookId))
|
||||
{
|
||||
_currentBookId = bookId;
|
||||
_ = LoadBookAsync(bookId);
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public Task GoBack()
|
||||
{
|
||||
switch(_navigationSource)
|
||||
{
|
||||
case nameof(BooksListViewModel):
|
||||
_regionManager.RequestNavigate(RegionNames.Content, nameof(BooksListPage));
|
||||
|
||||
break;
|
||||
|
||||
case nameof(BookViewViewModel):
|
||||
{
|
||||
// Going back from a book-to-book navigation — return to the source book
|
||||
if(_sourceNavigationBookId.HasValue)
|
||||
{
|
||||
var parameters = new NavigationParameters
|
||||
{
|
||||
{ NavParamKeys.BookId, _sourceNavigationBookId.Value },
|
||||
{ NavParamKeys.NavigationSource, nameof(BooksListViewModel) }
|
||||
};
|
||||
|
||||
_regionManager.RequestNavigate(RegionNames.Content, nameof(BookViewPage), parameters);
|
||||
}
|
||||
else
|
||||
_regionManager.RequestNavigate(RegionNames.Content, nameof(BooksListPage));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
_regionManager.RequestNavigate(RegionNames.Content, nameof(BooksPage));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public Task NavigateToPreviousBook()
|
||||
{
|
||||
if(PreviousBookId is null) return Task.CompletedTask;
|
||||
|
||||
var parameters = new NavigationParameters
|
||||
{
|
||||
{ NavParamKeys.BookId, PreviousBookId.Value },
|
||||
{ NavParamKeys.NavigationSource, nameof(BookViewViewModel) },
|
||||
{ "SourceNavigationBookId", _currentBookId }
|
||||
};
|
||||
|
||||
_regionManager.RequestNavigate(RegionNames.Content, nameof(BookViewPage), parameters);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public Task NavigateToSourceBook()
|
||||
{
|
||||
if(SourceBookId is null) return Task.CompletedTask;
|
||||
|
||||
var parameters = new NavigationParameters
|
||||
{
|
||||
{ NavParamKeys.BookId, SourceBookId.Value },
|
||||
{ NavParamKeys.NavigationSource, nameof(BookViewViewModel) },
|
||||
{ "SourceNavigationBookId", _currentBookId }
|
||||
};
|
||||
|
||||
_regionManager.RequestNavigate(RegionNames.Content, nameof(BookViewPage), parameters);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public Task LoadData()
|
||||
{
|
||||
HasError = false;
|
||||
ErrorMessage = string.Empty;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task LoadBookAsync(long bookId)
|
||||
{
|
||||
try
|
||||
{
|
||||
IsLoading = true;
|
||||
IsDataLoaded = false;
|
||||
HasError = false;
|
||||
ErrorMessage = string.Empty;
|
||||
People.Clear();
|
||||
Companies.Clear();
|
||||
Machines.Clear();
|
||||
MachineFamilies.Clear();
|
||||
|
||||
BookDto? book = await _booksService.GetBookAsync(bookId);
|
||||
|
||||
if(book is null)
|
||||
{
|
||||
HasError = true;
|
||||
ErrorMessage = _localizer["Book not found"];
|
||||
IsLoading = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate basic information (no SortTitle)
|
||||
BookTitle = book.Title ?? string.Empty;
|
||||
NativeTitle = book.NativeTitle;
|
||||
Country = book.Country;
|
||||
Isbn = book.Isbn;
|
||||
Pages = (short?)book.Pages;
|
||||
Edition = book.Edition;
|
||||
|
||||
if(book.Published.HasValue)
|
||||
PublishedDisplay = book.Published.Value.ToString("MMMM d, yyyy");
|
||||
|
||||
// Load cover image
|
||||
HasCover = book.CoverGuid.HasValue;
|
||||
|
||||
if(book.CoverGuid.HasValue)
|
||||
_ = LoadCoverAsync(book.CoverGuid.Value);
|
||||
|
||||
// Load synopsis
|
||||
DocumentSynopsisDto? synopsis = await _booksService.GetBookSynopsisAsync(bookId);
|
||||
|
||||
if(synopsis is not null)
|
||||
SynopsisText = synopsis.Text;
|
||||
|
||||
// Load people (by role)
|
||||
List<PersonByBookDto> people = await _booksService.GetPeopleByBookAsync(bookId);
|
||||
|
||||
foreach(PersonByBookDto person in people)
|
||||
{
|
||||
string name = person.DisplayName ?? person.Alias ?? $"{person.Name} {person.Surname}".Trim();
|
||||
string? roleStr = person.Role;
|
||||
string display = !string.IsNullOrEmpty(roleStr) ? $"{name} ({roleStr})" : name;
|
||||
People.Add(display);
|
||||
}
|
||||
|
||||
// Load companies (by role)
|
||||
List<CompanyByBookDto> companies = await _booksService.GetCompaniesByBookAsync(bookId);
|
||||
|
||||
foreach(CompanyByBookDto company in companies)
|
||||
{
|
||||
string name = company.Company ?? string.Empty;
|
||||
string? roleStr = company.Role;
|
||||
string display = !string.IsNullOrEmpty(roleStr) ? $"{name} ({roleStr})" : name;
|
||||
Companies.Add(display);
|
||||
}
|
||||
|
||||
// Load machines
|
||||
List<BookByMachineDto> machines = await _booksService.GetMachinesByBookAsync(bookId);
|
||||
|
||||
foreach(BookByMachineDto machine in machines)
|
||||
Machines.Add(machine.Machine ?? string.Empty);
|
||||
|
||||
// Load machine families
|
||||
List<BookByMachineFamilyDto> families = await _booksService.GetMachineFamiliesByBookAsync(bookId);
|
||||
|
||||
foreach(BookByMachineFamilyDto family in families)
|
||||
MachineFamilies.Add(family.MachineFamily ?? string.Empty);
|
||||
|
||||
// Load previous book title
|
||||
PreviousBookId = book.PreviousId;
|
||||
|
||||
if(book.PreviousId.HasValue)
|
||||
{
|
||||
BookDto? prev = await _booksService.GetBookAsync(book.PreviousId.Value);
|
||||
PreviousBookTitle = prev?.Title;
|
||||
}
|
||||
|
||||
// Load source book title
|
||||
SourceBookId = book.SourceId;
|
||||
|
||||
if(book.SourceId.HasValue)
|
||||
{
|
||||
BookDto? src = await _booksService.GetBookAsync(book.SourceId.Value);
|
||||
SourceBookTitle = src?.Title;
|
||||
}
|
||||
|
||||
UpdateVisibilities();
|
||||
IsDataLoaded = true;
|
||||
IsLoading = false;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error loading book {BookId}", bookId);
|
||||
HasError = true;
|
||||
ErrorMessage = ex.Message;
|
||||
IsLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVisibilities()
|
||||
{
|
||||
ShowNativeTitle = !string.IsNullOrEmpty(NativeTitle) ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowPublished = !string.IsNullOrEmpty(PublishedDisplay) ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowCountry = !string.IsNullOrEmpty(Country) ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowIsbn = !string.IsNullOrEmpty(Isbn) ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowPages = Pages.HasValue ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowEdition = Edition.HasValue ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowSynopsis = !string.IsNullOrEmpty(SynopsisText) ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowPeople = People.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowCompanies = Companies.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowMachines = Machines.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowMachineFamilies = MachineFamilies.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowPreviousBook = PreviousBookId.HasValue ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowSourceBook = SourceBookId.HasValue ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private async Task LoadCoverAsync(Guid coverGuid)
|
||||
{
|
||||
try
|
||||
{
|
||||
Stream stream = await _coverCache.GetCoverAsync(coverGuid);
|
||||
CoverImageSource = await _imageSourceFactory.CreateBitmapImageSourceAsync(stream);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error loading cover for book {BookId}", _currentBookId);
|
||||
}
|
||||
}
|
||||
}
|
||||
224
Marechai.App/Presentation/ViewModels/BooksListViewModel.cs
Normal file
224
Marechai.App/Presentation/ViewModels/BooksListViewModel.cs
Normal file
@@ -0,0 +1,224 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Marechai.App.Navigation;
|
||||
using Marechai.App.Presentation.Models;
|
||||
using Marechai.App.Presentation.Views;
|
||||
using Marechai.App.Services;
|
||||
using Marechai.App.Services.Caching;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace Marechai.App.Presentation.ViewModels;
|
||||
|
||||
[Bindable]
|
||||
public partial class BooksListViewModel : ObservableObject
|
||||
{
|
||||
private readonly BookCoverCache _coverCache;
|
||||
private readonly BooksService _booksService;
|
||||
private readonly IBooksListFilterContext _filterContext;
|
||||
private readonly ImageSourceFactory _imageSourceFactory;
|
||||
private readonly IStringLocalizer _localizer;
|
||||
private readonly ILogger<BooksListViewModel> _logger;
|
||||
private readonly IRegionManager _regionManager;
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<BookListItem> _booksList = [];
|
||||
|
||||
[ObservableProperty]
|
||||
private string _errorMessage = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _filterDescription = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _hasError;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isDataLoaded;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isLoading;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _pageTitle = string.Empty;
|
||||
|
||||
public BooksListViewModel(BooksService booksService, IStringLocalizer localizer,
|
||||
ILogger<BooksListViewModel> logger, IRegionManager regionManager,
|
||||
IBooksListFilterContext filterContext,
|
||||
BookCoverCache coverCache,
|
||||
ImageSourceFactory imageSourceFactory)
|
||||
{
|
||||
_booksService = booksService;
|
||||
_localizer = localizer;
|
||||
_logger = logger;
|
||||
_regionManager = regionManager;
|
||||
_filterContext = filterContext;
|
||||
_coverCache = coverCache;
|
||||
_imageSourceFactory = imageSourceFactory;
|
||||
LoadData = new AsyncRelayCommand(LoadDataAsync);
|
||||
GoBackCommand = new AsyncRelayCommand(GoBackAsync);
|
||||
NavigateToBookCommand = new AsyncRelayCommand<BookListItem>(NavigateToBookAsync);
|
||||
}
|
||||
|
||||
public IAsyncRelayCommand LoadData { get; }
|
||||
public ICommand GoBackCommand { get; }
|
||||
public IAsyncRelayCommand<BookListItem> NavigateToBookCommand { get; }
|
||||
|
||||
public BookListFilterType FilterType
|
||||
{
|
||||
get => _filterContext.FilterType;
|
||||
set => _filterContext.FilterType = value;
|
||||
}
|
||||
|
||||
public string FilterValue
|
||||
{
|
||||
get => _filterContext.FilterValue;
|
||||
set => _filterContext.FilterValue = value;
|
||||
}
|
||||
|
||||
private async Task LoadDataAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
IsLoading = true;
|
||||
ErrorMessage = string.Empty;
|
||||
HasError = false;
|
||||
IsDataLoaded = false;
|
||||
BooksList.Clear();
|
||||
|
||||
UpdateFilterDescription();
|
||||
|
||||
await LoadBooksFromApiAsync();
|
||||
|
||||
if(BooksList.Count == 0)
|
||||
{
|
||||
ErrorMessage = _localizer["No books found for this filter"].Value;
|
||||
HasError = true;
|
||||
}
|
||||
else
|
||||
IsDataLoaded = true;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error loading books: {Exception}", ex.Message);
|
||||
ErrorMessage = _localizer["Failed to load books. Please try again later."].Value;
|
||||
HasError = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateFilterDescription()
|
||||
{
|
||||
switch(FilterType)
|
||||
{
|
||||
case BookListFilterType.All:
|
||||
PageTitle = _localizer["All Books"];
|
||||
FilterDescription = _localizer["Browsing all books in the database"];
|
||||
|
||||
break;
|
||||
|
||||
case BookListFilterType.Letter:
|
||||
if(!string.IsNullOrEmpty(FilterValue) && FilterValue.Length == 1)
|
||||
{
|
||||
PageTitle = $"{_localizer["Books Starting with"]} {FilterValue}";
|
||||
FilterDescription = $"{_localizer["Showing books that start with"]} {FilterValue}";
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BookListFilterType.Year:
|
||||
if(!string.IsNullOrEmpty(FilterValue) && int.TryParse(FilterValue, out int year))
|
||||
{
|
||||
PageTitle = $"{_localizer["Books from"]} {year}";
|
||||
FilterDescription = $"{_localizer["Showing books published in"]} {year}";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadBooksFromApiAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
List<BookDto> books = FilterType switch
|
||||
{
|
||||
BookListFilterType.Letter when FilterValue.Length == 1 =>
|
||||
await _booksService.GetBooksByLetterAsync(FilterValue[0]),
|
||||
|
||||
BookListFilterType.Year when int.TryParse(FilterValue, out int year) =>
|
||||
await _booksService.GetBooksByYearAsync(year),
|
||||
|
||||
_ => await _booksService.GetAllBooksAsync()
|
||||
};
|
||||
|
||||
foreach(BookDto book in books)
|
||||
{
|
||||
long id = book.Id ?? 0;
|
||||
int? year = book.Published?.Year;
|
||||
|
||||
var item = new BookListItem
|
||||
{
|
||||
Id = id,
|
||||
Title = book.Title ?? string.Empty,
|
||||
Year = year,
|
||||
CoverGuid = book.CoverGuid
|
||||
};
|
||||
|
||||
// Fire-and-forget cover thumbnail loading
|
||||
if(book.CoverGuid.HasValue)
|
||||
_ = LoadCoverThumbnailAsync(item, book.CoverGuid.Value);
|
||||
|
||||
BooksList.Add(item);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error loading books from API");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadCoverThumbnailAsync(BookListItem item, Guid coverGuid)
|
||||
{
|
||||
try
|
||||
{
|
||||
Stream stream = await _coverCache.GetThumbnailAsync(coverGuid);
|
||||
item.CoverThumbnailSource = await _imageSourceFactory.CreateBitmapImageSourceAsync(stream);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error loading cover thumbnail for book {BookId}", item.Id);
|
||||
}
|
||||
}
|
||||
|
||||
private Task GoBackAsync()
|
||||
{
|
||||
_regionManager.RequestNavigate(RegionNames.Content, nameof(BooksPage));
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task NavigateToBookAsync(BookListItem? book)
|
||||
{
|
||||
if(book is null) return Task.CompletedTask;
|
||||
|
||||
var parameters = new NavigationParameters
|
||||
{
|
||||
{ NavParamKeys.BookId, book.Id },
|
||||
{ NavParamKeys.NavigationSource, nameof(BooksListViewModel) }
|
||||
};
|
||||
|
||||
_regionManager.RequestNavigate(RegionNames.Content, nameof(BookViewPage), parameters);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
194
Marechai.App/Presentation/ViewModels/BooksViewModel.cs
Normal file
194
Marechai.App/Presentation/ViewModels/BooksViewModel.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Marechai.App.Navigation;
|
||||
using Marechai.App.Presentation.Views;
|
||||
using Marechai.App.Services;
|
||||
|
||||
namespace Marechai.App.Presentation.ViewModels;
|
||||
|
||||
public partial class BooksViewModel : ObservableObject
|
||||
{
|
||||
private readonly BooksService _booksService;
|
||||
private readonly IBooksListFilterContext _filterContext;
|
||||
private readonly IStringLocalizer _localizer;
|
||||
private readonly ILogger<BooksViewModel> _logger;
|
||||
private readonly IRegionManager _regionManager;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _bookCount;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _bookCountText = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _errorMessage = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _hasError;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isDataLoaded;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isLoading;
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<char> _lettersList = [];
|
||||
|
||||
[ObservableProperty]
|
||||
private int _maximumYear;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _minimumYear;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _yearsGridTitle = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<int> _yearsList = [];
|
||||
|
||||
public BooksViewModel(BooksService booksService, IStringLocalizer localizer,
|
||||
ILogger<BooksViewModel> logger, IRegionManager regionManager,
|
||||
IBooksListFilterContext filterContext)
|
||||
{
|
||||
_booksService = booksService;
|
||||
_localizer = localizer;
|
||||
_logger = logger;
|
||||
_regionManager = regionManager;
|
||||
_filterContext = filterContext;
|
||||
LoadData = new AsyncRelayCommand(LoadDataAsync);
|
||||
GoBackCommand = new AsyncRelayCommand(GoBackAsync);
|
||||
NavigateByLetterCommand = new AsyncRelayCommand<char>(NavigateByLetterAsync);
|
||||
NavigateByYearCommand = new AsyncRelayCommand<int>(NavigateByYearAsync);
|
||||
NavigateAllBooksCommand = new AsyncRelayCommand(NavigateAllBooksAsync);
|
||||
Title = _localizer["Books"];
|
||||
|
||||
InitializeLetters();
|
||||
}
|
||||
|
||||
public IAsyncRelayCommand LoadData { get; }
|
||||
public ICommand GoBackCommand { get; }
|
||||
public IAsyncRelayCommand<char> NavigateByLetterCommand { get; }
|
||||
public IAsyncRelayCommand<int> NavigateByYearCommand { get; }
|
||||
public IAsyncRelayCommand NavigateAllBooksCommand { get; }
|
||||
public string Title { get; }
|
||||
|
||||
private void InitializeLetters()
|
||||
{
|
||||
LettersList.Clear();
|
||||
|
||||
for(var c = 'A'; c <= 'Z'; c++) LettersList.Add(c);
|
||||
}
|
||||
|
||||
private async Task LoadDataAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
IsLoading = true;
|
||||
ErrorMessage = string.Empty;
|
||||
HasError = false;
|
||||
IsDataLoaded = false;
|
||||
YearsList.Clear();
|
||||
|
||||
Task<int> countTask = _booksService.GetBooksCountAsync();
|
||||
Task<int> minYearTask = _booksService.GetMinimumYearAsync();
|
||||
Task<int> maxYearTask = _booksService.GetMaximumYearAsync();
|
||||
await Task.WhenAll(countTask, minYearTask, maxYearTask);
|
||||
|
||||
BookCount = countTask.Result;
|
||||
MinimumYear = minYearTask.Result;
|
||||
MaximumYear = maxYearTask.Result;
|
||||
|
||||
BookCountText = _localizer["Books in the database"];
|
||||
|
||||
if(MinimumYear > 0 && MaximumYear > 0)
|
||||
{
|
||||
for(int year = MinimumYear; year <= MaximumYear; year++) YearsList.Add(year);
|
||||
|
||||
YearsGridTitle = string.Format(_localizer["Browse by Year ({0} - {1})"], MinimumYear, MaximumYear);
|
||||
}
|
||||
|
||||
if(BookCount == 0)
|
||||
{
|
||||
ErrorMessage = _localizer["No books found"].Value;
|
||||
HasError = true;
|
||||
}
|
||||
else
|
||||
IsDataLoaded = true;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError("Error loading books data: {Exception}", ex.Message);
|
||||
ErrorMessage = _localizer["Failed to load books data. Please try again later."].Value;
|
||||
HasError = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task GoBackAsync()
|
||||
{
|
||||
_regionManager.RequestNavigate(RegionNames.Content, nameof(NewsPage));
|
||||
}
|
||||
|
||||
private Task NavigateByLetterAsync(char letter)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("Navigating to books by letter: {Letter}", letter);
|
||||
_filterContext.FilterType = BookListFilterType.Letter;
|
||||
_filterContext.FilterValue = letter.ToString();
|
||||
_regionManager.RequestNavigate(RegionNames.Content, nameof(BooksListPage));
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError("Error navigating to letter books: {Exception}", ex.Message);
|
||||
ErrorMessage = _localizer["Failed to navigate. Please try again."].Value;
|
||||
HasError = true;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task NavigateByYearAsync(int year)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("Navigating to books by year: {Year}", year);
|
||||
_filterContext.FilterType = BookListFilterType.Year;
|
||||
_filterContext.FilterValue = year.ToString();
|
||||
_regionManager.RequestNavigate(RegionNames.Content, nameof(BooksListPage));
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError("Error navigating to year books: {Exception}", ex.Message);
|
||||
ErrorMessage = _localizer["Failed to navigate. Please try again."].Value;
|
||||
HasError = true;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task NavigateAllBooksAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("Navigating to all books");
|
||||
_filterContext.FilterType = BookListFilterType.All;
|
||||
_filterContext.FilterValue = string.Empty;
|
||||
_regionManager.RequestNavigate(RegionNames.Content, nameof(BooksListPage));
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError("Error navigating to all books: {Exception}", ex.Message);
|
||||
ErrorMessage = _localizer["Failed to navigate. Please try again."].Value;
|
||||
HasError = true;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public partial class MainViewModel : ObservableObject
|
||||
|
||||
// Initialize commands
|
||||
NavigateToNewsCommand = new RelayCommand(() => NavigateTo(nameof(NewsPage)));
|
||||
NavigateToBooksCommand = new RelayCommand(() => NavigateTo("books"));
|
||||
NavigateToBooksCommand = new RelayCommand(() => NavigateTo(nameof(BooksPage)));
|
||||
NavigateToCompaniesCommand = new RelayCommand(() => NavigateTo(nameof(CompaniesPage)));
|
||||
NavigateToComputersCommand = new RelayCommand(() => NavigateTo(nameof(ComputersPage)));
|
||||
NavigateToConsolesCommand = new RelayCommand(() => NavigateTo(nameof(ConsolesPage)));
|
||||
|
||||
425
Marechai.App/Presentation/Views/BookViewPage.xaml
Normal file
425
Marechai.App/Presentation/Views/BookViewPage.xaml
Normal file
@@ -0,0 +1,425 @@
|
||||
<?xml version="1.0"
|
||||
encoding="utf-8"?>
|
||||
|
||||
<Page x:Class="Marechai.App.Presentation.Views.BookViewPage"
|
||||
x:Name="PageRoot"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:loc="using:Marechai.App.Presentation.Converters"
|
||||
NavigationCacheMode="Disabled"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid RowSpacing="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header with Back Button -->
|
||||
<Grid Grid.Row="0"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,0,1"
|
||||
Padding="12,12,16,12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Grid.Column="0"
|
||||
Command="{Binding GoBackCommand}"
|
||||
Style="{ThemeResource AlternateButtonStyle}"
|
||||
ToolTipService.ToolTip="Go back"
|
||||
Padding="8"
|
||||
MinWidth="44"
|
||||
MinHeight="44"
|
||||
VerticalAlignment="Center">
|
||||
<FontIcon Glyph=""
|
||||
FontSize="16" />
|
||||
</Button>
|
||||
|
||||
<StackPanel Grid.Column="1"
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding BookTitle}"
|
||||
FontSize="20"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextControlForeground}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Main Content -->
|
||||
<Grid Grid.Row="1">
|
||||
|
||||
<!-- Loading State -->
|
||||
<StackPanel Visibility="{Binding IsLoading}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
Padding="32"
|
||||
Spacing="16">
|
||||
<ProgressRing IsActive="True"
|
||||
IsIndeterminate="True"
|
||||
Height="64"
|
||||
Width="64"
|
||||
Foreground="{ThemeResource SystemAccentColor}" />
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=LoadingText}"
|
||||
FontSize="14"
|
||||
TextAlignment="Center"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Error State -->
|
||||
<StackPanel Visibility="{Binding HasError}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
Padding="24"
|
||||
Spacing="16"
|
||||
MaxWidth="400">
|
||||
<InfoBar IsOpen="True"
|
||||
Severity="Error"
|
||||
Title="{Binding Source={StaticResource Strings}, Path=BooksErrorInfoBar_Title}"
|
||||
Message="{Binding ErrorMessage}"
|
||||
IsClosable="False" />
|
||||
<Button
|
||||
Content="{Binding Source={StaticResource Strings}, Path=RetryButton}"
|
||||
Command="{Binding LoadDataCommand}"
|
||||
HorizontalAlignment="Center"
|
||||
Style="{ThemeResource AccentButtonStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Book Details -->
|
||||
<ScrollViewer Visibility="{Binding IsDataLoaded}"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Disabled">
|
||||
<StackPanel Padding="16"
|
||||
Spacing="24">
|
||||
|
||||
<!-- Cover Image or Placeholder -->
|
||||
<Grid HorizontalAlignment="Center"
|
||||
MaxWidth="300"
|
||||
MaxHeight="400">
|
||||
<!-- Placeholder FontIcon (behind image) -->
|
||||
<FontIcon Glyph=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="96"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
<!-- Cover image overlays when loaded -->
|
||||
<Image Source="{Binding CoverImageSource}"
|
||||
Stretch="Uniform"
|
||||
MaxWidth="300"
|
||||
MaxHeight="400" />
|
||||
</Grid>
|
||||
|
||||
<!-- Native Title -->
|
||||
<StackPanel Visibility="{Binding ShowNativeTitle}"
|
||||
Spacing="8">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookNativeTitleLabel}"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
Padding="16,12">
|
||||
<TextBlock Text="{Binding NativeTitle}"
|
||||
FontSize="16"
|
||||
Foreground="{ThemeResource TextControlForeground}"
|
||||
TextWrapping="Wrap" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Published Date and Country -->
|
||||
<Grid ColumnSpacing="16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Grid.Column="0"
|
||||
Visibility="{Binding ShowPublished}"
|
||||
Spacing="8">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookPublishedLabel}"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
Padding="16,12">
|
||||
<TextBlock Text="{Binding PublishedDisplay}"
|
||||
FontSize="14"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1"
|
||||
Visibility="{Binding ShowCountry}"
|
||||
Spacing="8">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookCountryLabel}"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
Padding="16,12">
|
||||
<TextBlock Text="{Binding Country}"
|
||||
FontSize="14"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- ISBN, Pages, Edition -->
|
||||
<Grid ColumnSpacing="16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Grid.Column="0"
|
||||
Visibility="{Binding ShowIsbn}"
|
||||
Spacing="8">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookIsbnLabel}"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
Padding="16,12">
|
||||
<TextBlock Text="{Binding Isbn}"
|
||||
FontSize="14"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1"
|
||||
Visibility="{Binding ShowPages}"
|
||||
Spacing="8">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookPagesLabel}"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
Padding="16,12">
|
||||
<TextBlock Text="{Binding Pages}"
|
||||
FontSize="14"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="2"
|
||||
Visibility="{Binding ShowEdition}"
|
||||
Spacing="8">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookEditionLabel}"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
Padding="16,12">
|
||||
<TextBlock Text="{Binding Edition}"
|
||||
FontSize="14"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Synopsis -->
|
||||
<StackPanel Visibility="{Binding ShowSynopsis}"
|
||||
Spacing="8">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookSynopsisLabel}"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
Padding="16,12">
|
||||
<TextBlock Text="{Binding SynopsisText}"
|
||||
FontSize="14"
|
||||
Foreground="{ThemeResource TextControlForeground}"
|
||||
TextWrapping="Wrap" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<!-- People / Authors -->
|
||||
<StackPanel Visibility="{Binding ShowPeople}"
|
||||
Spacing="12">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookAuthorsLabel}"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
<ItemsControl ItemsSource="{Binding People}"
|
||||
HorizontalAlignment="Stretch">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical"
|
||||
Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
Padding="16,8">
|
||||
<TextBlock Text="{Binding}"
|
||||
FontSize="14"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Companies / Publishers -->
|
||||
<StackPanel Visibility="{Binding ShowCompanies}"
|
||||
Spacing="12">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookCompaniesLabel}"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
<ItemsControl ItemsSource="{Binding Companies}"
|
||||
HorizontalAlignment="Stretch">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical"
|
||||
Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
Padding="16,8">
|
||||
<TextBlock Text="{Binding}"
|
||||
FontSize="14"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Related Machines -->
|
||||
<StackPanel Visibility="{Binding ShowMachines}"
|
||||
Spacing="12">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookMachinesLabel}"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
<ItemsControl ItemsSource="{Binding Machines}"
|
||||
HorizontalAlignment="Stretch">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical"
|
||||
Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
Padding="16,8">
|
||||
<TextBlock Text="{Binding}"
|
||||
FontSize="14"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Related Machine Families -->
|
||||
<StackPanel Visibility="{Binding ShowMachineFamilies}"
|
||||
Spacing="12">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookMachineFamiliesLabel}"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
<ItemsControl ItemsSource="{Binding MachineFamilies}"
|
||||
HorizontalAlignment="Stretch">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical"
|
||||
Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
Padding="16,8">
|
||||
<TextBlock Text="{Binding}"
|
||||
FontSize="14"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Previous Edition -->
|
||||
<StackPanel Visibility="{Binding ShowPreviousBook}"
|
||||
Spacing="8">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookPreviousEditionLabel}"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<HyperlinkButton Content="{Binding PreviousBookTitle}"
|
||||
Command="{Binding NavigateToPreviousBookCommand}"
|
||||
FontSize="14" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Source Book -->
|
||||
<StackPanel Visibility="{Binding ShowSourceBook}"
|
||||
Spacing="8">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BookSourceLabel}"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<HyperlinkButton Content="{Binding SourceBookTitle}"
|
||||
Command="{Binding NavigateToSourceBookCommand}"
|
||||
FontSize="14" />
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Page>
|
||||
13
Marechai.App/Presentation/Views/BookViewPage.xaml.cs
Normal file
13
Marechai.App/Presentation/Views/BookViewPage.xaml.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
#nullable enable
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Marechai.App.Presentation.Views;
|
||||
|
||||
public sealed partial class BookViewPage : Page
|
||||
{
|
||||
public BookViewPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
257
Marechai.App/Presentation/Views/BooksListPage.xaml
Normal file
257
Marechai.App/Presentation/Views/BooksListPage.xaml
Normal file
@@ -0,0 +1,257 @@
|
||||
<?xml version="1.0"
|
||||
encoding="utf-8"?>
|
||||
|
||||
<Page x:Class="Marechai.App.Presentation.Views.BooksListPage"
|
||||
x:Name="PageRoot"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:loc="using:Marechai.App.Presentation.Converters"
|
||||
NavigationCacheMode="Required"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid RowSpacing="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header with Back Button and Title -->
|
||||
<Grid Grid.Row="0"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,0,1"
|
||||
Padding="16,12,16,12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Grid.Column="0"
|
||||
Command="{Binding GoBackCommand}"
|
||||
Style="{ThemeResource AlternateButtonStyle}"
|
||||
ToolTipService.ToolTip="Go back"
|
||||
Padding="8"
|
||||
MinWidth="44"
|
||||
MinHeight="44"
|
||||
VerticalAlignment="Center">
|
||||
<FontIcon Glyph=""
|
||||
FontSize="16" />
|
||||
</Button>
|
||||
|
||||
<StackPanel Grid.Column="1"
|
||||
Margin="16,0,0,0"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding PageTitle}"
|
||||
FontSize="20"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextControlForeground}" />
|
||||
<TextBlock Text="{Binding FilterDescription}"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}"
|
||||
Margin="0,4,0,0" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Main Content -->
|
||||
<Grid Grid.Row="1">
|
||||
|
||||
<!-- Loading State -->
|
||||
<StackPanel Visibility="{Binding IsLoading}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
Padding="32"
|
||||
Spacing="16">
|
||||
<ProgressRing IsActive="True"
|
||||
IsIndeterminate="True"
|
||||
Height="64"
|
||||
Width="64"
|
||||
Foreground="{ThemeResource SystemAccentColor}" />
|
||||
<TextBlock Text="{Binding Source={StaticResource Strings}, Path=LoadingText}"
|
||||
FontSize="14"
|
||||
TextAlignment="Center"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Error State -->
|
||||
<StackPanel Visibility="{Binding HasError}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
Padding="24"
|
||||
Spacing="16"
|
||||
MaxWidth="400">
|
||||
<InfoBar IsOpen="True"
|
||||
Severity="Error"
|
||||
Title="{Binding Source={StaticResource Strings}, Path=BooksErrorInfoBar_Title}"
|
||||
Message="{Binding ErrorMessage}"
|
||||
IsClosable="False" />
|
||||
<Button Content="{Binding Source={StaticResource Strings}, Path=RetryButton}"
|
||||
Command="{Binding LoadData}"
|
||||
HorizontalAlignment="Center"
|
||||
Style="{ThemeResource AccentButtonStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Books List -->
|
||||
<Grid Visibility="{Binding IsDataLoaded}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Disabled">
|
||||
<Grid Padding="8">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Count Header -->
|
||||
<StackPanel Grid.Row="0"
|
||||
Padding="16,12"
|
||||
Orientation="Horizontal"
|
||||
Spacing="4">
|
||||
<TextBlock FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}"
|
||||
Text="{Binding Source={StaticResource Strings}, Path=ResultsText}" />
|
||||
<TextBlock FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}"
|
||||
Text="{Binding BooksList.Count}" />
|
||||
<TextBlock FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}"
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BooksLabel}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Books List -->
|
||||
<ItemsControl Grid.Row="1"
|
||||
ItemsSource="{Binding BooksList}"
|
||||
Padding="0"
|
||||
Margin="0,8,0,0"
|
||||
HorizontalAlignment="Stretch">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical"
|
||||
Spacing="0"
|
||||
HorizontalAlignment="Stretch" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Button Padding="0"
|
||||
Margin="0,0,0,8"
|
||||
MinHeight="80"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding DataContext.NavigateToBookCommand, ElementName=PageRoot}"
|
||||
CommandParameter="{Binding}"
|
||||
Background="Transparent"
|
||||
BorderThickness="0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Grid MinHeight="80"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Border x:Name="ShadowBorder"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
Padding="16,12"
|
||||
Translation="0, 0, 4"
|
||||
VerticalAlignment="Stretch">
|
||||
<Border.Shadow>
|
||||
<ThemeShadow />
|
||||
</Border.Shadow>
|
||||
|
||||
<Grid ColumnSpacing="16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Cover Thumbnail or Book Icon Placeholder -->
|
||||
<Grid Grid.Column="0"
|
||||
Width="48"
|
||||
Height="64"
|
||||
VerticalAlignment="Center">
|
||||
<!-- Placeholder shown behind image -->
|
||||
<FontIcon Glyph=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="32"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
<!-- Cover thumbnail overlays placeholder when loaded -->
|
||||
<Image Source="{Binding CoverThumbnailSource}"
|
||||
Stretch="Uniform"
|
||||
MaxWidth="48"
|
||||
MaxHeight="64" />
|
||||
</Grid>
|
||||
|
||||
<!-- Book Info -->
|
||||
<StackPanel Grid.Column="1"
|
||||
Spacing="8"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="{Binding Title}"
|
||||
FontSize="16"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextControlForeground}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Spacing="6"
|
||||
VerticalAlignment="Center">
|
||||
<FontIcon Glyph=""
|
||||
FontSize="14"
|
||||
Foreground="{ThemeResource SystemAccentColor}" />
|
||||
<TextBlock FontSize="13"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}">
|
||||
<Run Text="{Binding Year}" />
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Navigation Arrow -->
|
||||
<StackPanel Grid.Column="2"
|
||||
VerticalAlignment="Center">
|
||||
<FontIcon Glyph=""
|
||||
FontSize="18"
|
||||
Foreground="{ThemeResource SystemAccentColor}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="PointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ShadowBorder.Background"
|
||||
Value="{ThemeResource CardBackgroundFillColorSecondaryBrush}" />
|
||||
<Setter Target="ShadowBorder.Translation"
|
||||
Value="0, -2, 8" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ShadowBorder.Background"
|
||||
Value="{ThemeResource CardBackgroundFillColorTertiaryBrush}" />
|
||||
<Setter Target="ShadowBorder.Translation"
|
||||
Value="0, 0, 2" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Page>
|
||||
20
Marechai.App/Presentation/Views/BooksListPage.xaml.cs
Normal file
20
Marechai.App/Presentation/Views/BooksListPage.xaml.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Marechai.App.Presentation.ViewModels;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Marechai.App.Presentation.Views;
|
||||
|
||||
public sealed partial class BooksListPage : Page
|
||||
{
|
||||
public BooksListPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContextChanged += BooksListPage_DataContextChanged;
|
||||
}
|
||||
|
||||
private void BooksListPage_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
|
||||
{
|
||||
if(args.NewValue is BooksListViewModel vm)
|
||||
vm.LoadData.Execute(null);
|
||||
}
|
||||
}
|
||||
311
Marechai.App/Presentation/Views/BooksPage.xaml
Normal file
311
Marechai.App/Presentation/Views/BooksPage.xaml
Normal file
@@ -0,0 +1,311 @@
|
||||
<?xml version="1.0"
|
||||
encoding="utf-8"?>
|
||||
|
||||
<Page x:Class="Marechai.App.Presentation.Views.BooksPage"
|
||||
x:Name="PageRoot"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:loc="using:Marechai.App.Presentation.Converters"
|
||||
xmlns:utu="using:Uno.Toolkit.UI"
|
||||
NavigationCacheMode="Required"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid utu:SafeArea.Insets="VisibleBounds">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header -->
|
||||
<utu:NavigationBar Grid.Row="0"
|
||||
Content="{Binding Path=Title}">
|
||||
<utu:NavigationBar.MainCommand>
|
||||
<AppBarButton Label="{Binding Source={StaticResource Strings}, Path=BackButton}" Icon="Back"
|
||||
Command="{Binding GoBackCommand}"
|
||||
AutomationProperties.Name="Go back" />
|
||||
</utu:NavigationBar.MainCommand>
|
||||
</utu:NavigationBar>
|
||||
|
||||
<!-- Content -->
|
||||
<ScrollViewer Grid.Row="1">
|
||||
<StackPanel Padding="16"
|
||||
Spacing="24">
|
||||
|
||||
<!-- Book Count Display -->
|
||||
<StackPanel HorizontalAlignment="Center"
|
||||
Spacing="8">
|
||||
<TextBlock Text="{Binding BookCountText}"
|
||||
TextAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<TextBlock Text="{Binding BookCount}"
|
||||
TextAlignment="Center"
|
||||
FontSize="48"
|
||||
FontWeight="Bold"
|
||||
Foreground="{ThemeResource SystemAccentColor}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Loading State -->
|
||||
<StackPanel Visibility="{Binding IsLoading}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
Padding="32"
|
||||
Spacing="16">
|
||||
<ProgressRing IsActive="True"
|
||||
IsIndeterminate="True"
|
||||
Height="48"
|
||||
Width="48" />
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=LoadingText}"
|
||||
TextAlignment="Center"
|
||||
FontSize="14" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Error State -->
|
||||
<StackPanel Visibility="{Binding HasError}"
|
||||
Padding="16"
|
||||
Background="{ThemeResource SystemErrorBackgroundColor}"
|
||||
CornerRadius="8"
|
||||
Spacing="8">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=ErrorTitle}"
|
||||
FontWeight="Bold"
|
||||
Foreground="{ThemeResource SystemErrorTextForegroundColor}" />
|
||||
<TextBlock Text="{Binding ErrorMessage}"
|
||||
Foreground="{ThemeResource SystemErrorTextForegroundColor}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Main Content (visible when loaded and no error) -->
|
||||
<StackPanel Visibility="{Binding IsDataLoaded}"
|
||||
Spacing="24">
|
||||
|
||||
<!-- Letters Grid Section -->
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock
|
||||
Text="{Binding Source={StaticResource Strings}, Path=BrowseByLetterText}"
|
||||
FontSize="16"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<ItemsRepeater ItemsSource="{Binding LettersList}"
|
||||
Layout="{StaticResource LettersGridLayout}">
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Button Content="{Binding}"
|
||||
Command="{Binding DataContext.NavigateByLetterCommand, ElementName=PageRoot}"
|
||||
CommandParameter="{Binding}"
|
||||
Style="{StaticResource KeyboardKeyButtonStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Years Grid Section -->
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="{Binding YearsGridTitle}"
|
||||
FontSize="16"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<ItemsRepeater ItemsSource="{Binding YearsList}"
|
||||
Layout="{StaticResource YearsGridLayout}">
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Button Content="{Binding}"
|
||||
Command="{Binding DataContext.NavigateByYearCommand, ElementName=PageRoot}"
|
||||
CommandParameter="{Binding}"
|
||||
Style="{StaticResource KeyboardKeyButtonStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</StackPanel>
|
||||
|
||||
<!-- All Books Button -->
|
||||
<StackPanel Spacing="12">
|
||||
<Button
|
||||
Content="{Binding Source={StaticResource Strings}, Path=AllBooksButton}"
|
||||
Padding="16,12"
|
||||
HorizontalAlignment="Stretch"
|
||||
FontSize="16"
|
||||
FontWeight="SemiBold"
|
||||
Command="{Binding NavigateAllBooksCommand}"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
|
||||
<!-- Search Field (placeholder for future implementation) -->
|
||||
<TextBox
|
||||
PlaceholderText="{Binding Source={StaticResource Strings}, Path=BooksSearchBox_Placeholder}"
|
||||
Padding="12"
|
||||
IsEnabled="False"
|
||||
Opacity="0.5" />
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</Grid>
|
||||
|
||||
<Page.Resources>
|
||||
<!-- Keyboard Key Button Style -->
|
||||
<Style x:Key="KeyboardKeyButtonStyle"
|
||||
TargetType="Button">
|
||||
<Setter Property="Foreground"
|
||||
Value="#1A1A1A" />
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>
|
||||
<LinearGradientBrush StartPoint="0,0"
|
||||
EndPoint="0,1">
|
||||
<GradientStop Color="#D6D6D6"
|
||||
Offset="0" />
|
||||
<GradientStop Color="#C2C2C2"
|
||||
Offset="0.55" />
|
||||
<GradientStop Color="#B0B0B0"
|
||||
Offset="1" />
|
||||
</LinearGradientBrush>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="BorderBrush"
|
||||
Value="#7A7A7A" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="CornerRadius"
|
||||
Value="6" />
|
||||
<Setter Property="Padding"
|
||||
Value="14,12" />
|
||||
<Setter Property="Margin"
|
||||
Value="4" />
|
||||
<Setter Property="FontFamily"
|
||||
Value="Segoe UI" />
|
||||
<Setter Property="FontWeight"
|
||||
Value="SemiBold" />
|
||||
<Setter Property="FontSize"
|
||||
Value="15" />
|
||||
<Setter Property="HorizontalAlignment"
|
||||
Value="Stretch" />
|
||||
<Setter Property="VerticalAlignment"
|
||||
Value="Stretch" />
|
||||
<Setter Property="HorizontalContentAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="MinWidth"
|
||||
Value="52" />
|
||||
<Setter Property="MinHeight"
|
||||
Value="52" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Grid>
|
||||
<Border x:Name="Shadow"
|
||||
CornerRadius="6"
|
||||
Background="#33000000"
|
||||
Margin="2,4,4,2" />
|
||||
<Border x:Name="KeyBorder"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid>
|
||||
<Border CornerRadius="{TemplateBinding CornerRadius}"
|
||||
BorderBrush="#60FFFFFF"
|
||||
BorderThickness="1,1,0,0" />
|
||||
<Border CornerRadius="{TemplateBinding CornerRadius}"
|
||||
BorderBrush="#30000000"
|
||||
BorderThickness="0,0,1,1" />
|
||||
<ContentPresenter x:Name="ContentPresenter"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Margin="0"
|
||||
TextWrapping="NoWrap" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="PointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyBorder.Background">
|
||||
<Setter.Value>
|
||||
<LinearGradientBrush StartPoint="0,0"
|
||||
EndPoint="0,1">
|
||||
<GradientStop Color="#E0E0E0"
|
||||
Offset="0" />
|
||||
<GradientStop Color="#CFCFCF"
|
||||
Offset="0.55" />
|
||||
<GradientStop Color="#BDBDBD"
|
||||
Offset="1" />
|
||||
</LinearGradientBrush>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Target="KeyBorder.BorderBrush"
|
||||
Value="#5F5F5F" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyBorder.Background">
|
||||
<Setter.Value>
|
||||
<LinearGradientBrush StartPoint="0,0"
|
||||
EndPoint="0,1">
|
||||
<GradientStop Color="#9C9C9C"
|
||||
Offset="0" />
|
||||
<GradientStop Color="#A8A8A8"
|
||||
Offset="0.55" />
|
||||
<GradientStop Color="#B4B4B4"
|
||||
Offset="1" />
|
||||
</LinearGradientBrush>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Target="KeyBorder.BorderBrush"
|
||||
Value="#4A4A4A" />
|
||||
<Setter Target="KeyBorder.RenderTransform">
|
||||
<Setter.Value>
|
||||
<TranslateTransform Y="2" />
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Target="Shadow.Opacity"
|
||||
Value="0.15" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyBorder.Opacity"
|
||||
Value="0.45" />
|
||||
<Setter Target="ContentPresenter.Foreground"
|
||||
Value="#777777" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="FocusStates">
|
||||
<VisualState x:Name="Focused">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyBorder.BorderBrush"
|
||||
Value="#3A7AFE" />
|
||||
<Setter Target="KeyBorder.BorderThickness"
|
||||
Value="2" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Unfocused" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<UniformGridLayout x:Key="LettersGridLayout"
|
||||
ItemsStretch="Fill"
|
||||
MinItemWidth="44"
|
||||
MinItemHeight="44"
|
||||
MaximumRowsOrColumns="13" />
|
||||
|
||||
<UniformGridLayout x:Key="YearsGridLayout"
|
||||
ItemsStretch="Fill"
|
||||
MinItemWidth="54"
|
||||
MinItemHeight="44"
|
||||
MaximumRowsOrColumns="10" />
|
||||
|
||||
</Page.Resources>
|
||||
|
||||
</Page>
|
||||
37
Marechai.App/Presentation/Views/BooksPage.xaml.cs
Normal file
37
Marechai.App/Presentation/Views/BooksPage.xaml.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using Marechai.App.Presentation.ViewModels;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
|
||||
namespace Marechai.App.Presentation.Views;
|
||||
|
||||
public sealed partial class BooksPage : Page
|
||||
{
|
||||
public BooksPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContextChanged += BooksPage_DataContextChanged;
|
||||
Loaded += BooksPage_Loaded;
|
||||
}
|
||||
|
||||
private void BooksPage_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if(DataContext is not BooksViewModel viewModel) return;
|
||||
|
||||
_ = viewModel.LoadData.ExecuteAsync(null);
|
||||
}
|
||||
|
||||
private void BooksPage_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
|
||||
{
|
||||
if(args.NewValue is BooksViewModel viewModel)
|
||||
_ = viewModel.LoadData.ExecuteAsync(null);
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedTo(e);
|
||||
|
||||
if(DataContext is BooksViewModel viewModel)
|
||||
_ = viewModel.LoadData.ExecuteAsync(null);
|
||||
}
|
||||
}
|
||||
@@ -1752,4 +1752,27 @@
|
||||
<data name="FailedToLoadSoftwareReleases" xml:space="preserve"><value>Software-Veröffentlichungen konnten nicht geladen werden.</value></data>
|
||||
<data name="FailedToDeleteSoftwareRelease" xml:space="preserve"><value>Software-Veröffentlichung konnte nicht gelöscht werden.</value></data>
|
||||
<data name="FailedToSaveSoftwareRelease" xml:space="preserve"><value>Software-Veröffentlichung konnte nicht gespeichert werden.</value></data>
|
||||
<data name="AllBooksButton" xml:space="preserve"><value>Alle Bücher</value></data>
|
||||
<data name="BooksSearchBox_Placeholder" xml:space="preserve"><value>Bücher suchen...</value></data>
|
||||
<data name="BooksErrorInfoBar_Title" xml:space="preserve"><value>Fehler beim Laden der Bücher</value></data>
|
||||
<data name="BooksLabel" xml:space="preserve"><value>Bücher</value></data>
|
||||
<data name="BookSynopsisLabel" xml:space="preserve"><value>Zusammenfassung</value></data>
|
||||
<data name="BookAuthorsLabel" xml:space="preserve"><value>Autoren und Mitwirkende</value></data>
|
||||
<data name="BookCompaniesLabel" xml:space="preserve"><value>Verlage und Unternehmen</value></data>
|
||||
<data name="BookMachinesLabel" xml:space="preserve"><value>Zugehörige Maschinen</value></data>
|
||||
<data name="BookMachineFamiliesLabel" xml:space="preserve"><value>Zugehörige Maschinenfamilien</value></data>
|
||||
<data name="BookPreviousEditionLabel" xml:space="preserve"><value>Vorherige Ausgabe</value></data>
|
||||
<data name="Books" xml:space="preserve"><value>Bücher</value></data>
|
||||
<data name="Books in the database" xml:space="preserve"><value>Bücher in der Datenbank</value></data>
|
||||
<data name="No books found" xml:space="preserve"><value>Keine Bücher gefunden</value></data>
|
||||
<data name="Failed to load books data. Please try again later." xml:space="preserve"><value>Fehler beim Laden der Bücherdaten. Bitte versuchen Sie es später erneut.</value></data>
|
||||
<data name="All Books" xml:space="preserve"><value>Alle Bücher</value></data>
|
||||
<data name="Browsing all books in the database" xml:space="preserve"><value>Alle Bücher in der Datenbank durchsuchen</value></data>
|
||||
<data name="Books Starting with" xml:space="preserve"><value>Bücher beginnend mit</value></data>
|
||||
<data name="Showing books that start with" xml:space="preserve"><value>Bücher anzeigen, die beginnen mit</value></data>
|
||||
<data name="Books from" xml:space="preserve"><value>Bücher aus</value></data>
|
||||
<data name="Showing books published in" xml:space="preserve"><value>Bücher anzeigen, veröffentlicht in</value></data>
|
||||
<data name="No books found for this filter" xml:space="preserve"><value>Keine Bücher für diesen Filter gefunden</value></data>
|
||||
<data name="Failed to load books. Please try again later." xml:space="preserve"><value>Fehler beim Laden der Bücher. Bitte versuchen Sie es später erneut.</value></data>
|
||||
<data name="Book not found" xml:space="preserve"><value>Buch nicht gefunden</value></data>
|
||||
</root>
|
||||
|
||||
@@ -1892,4 +1892,27 @@
|
||||
<data name="FailedToLoadSoftwareReleases" xml:space="preserve"><value>Error al cargar lanzamientos de software.</value></data>
|
||||
<data name="FailedToDeleteSoftwareRelease" xml:space="preserve"><value>Error al eliminar lanzamiento de software.</value></data>
|
||||
<data name="FailedToSaveSoftwareRelease" xml:space="preserve"><value>Error al guardar lanzamiento de software.</value></data>
|
||||
<data name="AllBooksButton" xml:space="preserve"><value>Todos los libros</value></data>
|
||||
<data name="BooksSearchBox_Placeholder" xml:space="preserve"><value>Buscar libros...</value></data>
|
||||
<data name="BooksErrorInfoBar_Title" xml:space="preserve"><value>Error al cargar libros</value></data>
|
||||
<data name="BooksLabel" xml:space="preserve"><value>libros</value></data>
|
||||
<data name="BookSynopsisLabel" xml:space="preserve"><value>Sinopsis</value></data>
|
||||
<data name="BookAuthorsLabel" xml:space="preserve"><value>Autores y colaboradores</value></data>
|
||||
<data name="BookCompaniesLabel" xml:space="preserve"><value>Editoriales y empresas</value></data>
|
||||
<data name="BookMachinesLabel" xml:space="preserve"><value>Máquinas relacionadas</value></data>
|
||||
<data name="BookMachineFamiliesLabel" xml:space="preserve"><value>Familias de máquinas relacionadas</value></data>
|
||||
<data name="BookPreviousEditionLabel" xml:space="preserve"><value>Edición anterior</value></data>
|
||||
<data name="Books" xml:space="preserve"><value>Libros</value></data>
|
||||
<data name="Books in the database" xml:space="preserve"><value>Libros en la base de datos</value></data>
|
||||
<data name="No books found" xml:space="preserve"><value>No se encontraron libros</value></data>
|
||||
<data name="Failed to load books data. Please try again later." xml:space="preserve"><value>Error al cargar los datos de libros. Por favor, inténtelo de nuevo más tarde.</value></data>
|
||||
<data name="All Books" xml:space="preserve"><value>Todos los libros</value></data>
|
||||
<data name="Browsing all books in the database" xml:space="preserve"><value>Explorando todos los libros en la base de datos</value></data>
|
||||
<data name="Books Starting with" xml:space="preserve"><value>Libros que empiezan con</value></data>
|
||||
<data name="Showing books that start with" xml:space="preserve"><value>Mostrando libros que empiezan con</value></data>
|
||||
<data name="Books from" xml:space="preserve"><value>Libros de</value></data>
|
||||
<data name="Showing books published in" xml:space="preserve"><value>Mostrando libros publicados en</value></data>
|
||||
<data name="No books found for this filter" xml:space="preserve"><value>No se encontraron libros para este filtro</value></data>
|
||||
<data name="Failed to load books. Please try again later." xml:space="preserve"><value>Error al cargar los libros. Por favor, inténtelo de nuevo más tarde.</value></data>
|
||||
<data name="Book not found" xml:space="preserve"><value>Libro no encontrado</value></data>
|
||||
</root>
|
||||
@@ -1856,4 +1856,27 @@
|
||||
<data name="FailedToLoadSoftwareReleases" xml:space="preserve"><value>Échec du chargement des sorties de logiciels.</value></data>
|
||||
<data name="FailedToDeleteSoftwareRelease" xml:space="preserve"><value>Échec de la suppression de la sortie du logiciel.</value></data>
|
||||
<data name="FailedToSaveSoftwareRelease" xml:space="preserve"><value>Échec de l'enregistrement de la sortie du logiciel.</value></data>
|
||||
<data name="AllBooksButton" xml:space="preserve"><value>Tous les livres</value></data>
|
||||
<data name="BooksSearchBox_Placeholder" xml:space="preserve"><value>Rechercher des livres...</value></data>
|
||||
<data name="BooksErrorInfoBar_Title" xml:space="preserve"><value>Erreur de chargement des livres</value></data>
|
||||
<data name="BooksLabel" xml:space="preserve"><value>livres</value></data>
|
||||
<data name="BookSynopsisLabel" xml:space="preserve"><value>Synopsis</value></data>
|
||||
<data name="BookAuthorsLabel" xml:space="preserve"><value>Auteurs et contributeurs</value></data>
|
||||
<data name="BookCompaniesLabel" xml:space="preserve"><value>Éditeurs et entreprises</value></data>
|
||||
<data name="BookMachinesLabel" xml:space="preserve"><value>Machines associées</value></data>
|
||||
<data name="BookMachineFamiliesLabel" xml:space="preserve"><value>Familles de machines associées</value></data>
|
||||
<data name="BookPreviousEditionLabel" xml:space="preserve"><value>Édition précédente</value></data>
|
||||
<data name="Books" xml:space="preserve"><value>Livres</value></data>
|
||||
<data name="Books in the database" xml:space="preserve"><value>Livres dans la base de données</value></data>
|
||||
<data name="No books found" xml:space="preserve"><value>Aucun livre trouvé</value></data>
|
||||
<data name="Failed to load books data. Please try again later." xml:space="preserve"><value>Erreur de chargement des données des livres. Veuillez réessayer plus tard.</value></data>
|
||||
<data name="All Books" xml:space="preserve"><value>Tous les livres</value></data>
|
||||
<data name="Browsing all books in the database" xml:space="preserve"><value>Parcourir tous les livres dans la base de données</value></data>
|
||||
<data name="Books Starting with" xml:space="preserve"><value>Livres commençant par</value></data>
|
||||
<data name="Showing books that start with" xml:space="preserve"><value>Affichage des livres commençant par</value></data>
|
||||
<data name="Books from" xml:space="preserve"><value>Livres de</value></data>
|
||||
<data name="Showing books published in" xml:space="preserve"><value>Affichage des livres publiés en</value></data>
|
||||
<data name="No books found for this filter" xml:space="preserve"><value>Aucun livre trouvé pour ce filtre</value></data>
|
||||
<data name="Failed to load books. Please try again later." xml:space="preserve"><value>Erreur de chargement des livres. Veuillez réessayer plus tard.</value></data>
|
||||
<data name="Book not found" xml:space="preserve"><value>Livre non trouvé</value></data>
|
||||
</root>
|
||||
@@ -1752,4 +1752,27 @@
|
||||
<data name="FailedToLoadSoftwareReleases" xml:space="preserve"><value>Editiones programmatum onerare non potuit.</value></data>
|
||||
<data name="FailedToDeleteSoftwareRelease" xml:space="preserve"><value>Editionem programmatis delere non potuit.</value></data>
|
||||
<data name="FailedToSaveSoftwareRelease" xml:space="preserve"><value>Editionem programmatis servare non potuit.</value></data>
|
||||
<data name="AllBooksButton" xml:space="preserve"><value>Omnes libri</value></data>
|
||||
<data name="BooksSearchBox_Placeholder" xml:space="preserve"><value>Libros quaerere...</value></data>
|
||||
<data name="BooksErrorInfoBar_Title" xml:space="preserve"><value>Error in libris onerandis</value></data>
|
||||
<data name="BooksLabel" xml:space="preserve"><value>libri</value></data>
|
||||
<data name="BookSynopsisLabel" xml:space="preserve"><value>Synopsis</value></data>
|
||||
<data name="BookAuthorsLabel" xml:space="preserve"><value>Auctores et contributores</value></data>
|
||||
<data name="BookCompaniesLabel" xml:space="preserve"><value>Editores et societates</value></data>
|
||||
<data name="BookMachinesLabel" xml:space="preserve"><value>Machinae pertinentes</value></data>
|
||||
<data name="BookMachineFamiliesLabel" xml:space="preserve"><value>Familiae machinarum pertinentes</value></data>
|
||||
<data name="BookPreviousEditionLabel" xml:space="preserve"><value>Editio prior</value></data>
|
||||
<data name="Books" xml:space="preserve"><value>Libri</value></data>
|
||||
<data name="Books in the database" xml:space="preserve"><value>Libri in basi datorum</value></data>
|
||||
<data name="No books found" xml:space="preserve"><value>Nulli libri inventi</value></data>
|
||||
<data name="Failed to load books data. Please try again later." xml:space="preserve"><value>Error in datis librorum onerandis. Quaeso, iterum posterius tempta.</value></data>
|
||||
<data name="All Books" xml:space="preserve"><value>Omnes libri</value></data>
|
||||
<data name="Browsing all books in the database" xml:space="preserve"><value>Omnes libros in basi datorum perlustrare</value></data>
|
||||
<data name="Books Starting with" xml:space="preserve"><value>Libri incipientes ab</value></data>
|
||||
<data name="Showing books that start with" xml:space="preserve"><value>Libri ostenduntur qui incipiunt ab</value></data>
|
||||
<data name="Books from" xml:space="preserve"><value>Libri ab anno</value></data>
|
||||
<data name="Showing books published in" xml:space="preserve"><value>Libri ostenduntur editi anno</value></data>
|
||||
<data name="No books found for this filter" xml:space="preserve"><value>Nulli libri inventi pro hoc filtro</value></data>
|
||||
<data name="Failed to load books. Please try again later." xml:space="preserve"><value>Error in libris onerandis. Quaeso, iterum posterius tempta.</value></data>
|
||||
<data name="Book not found" xml:space="preserve"><value>Liber non inventus</value></data>
|
||||
</root>
|
||||
|
||||
@@ -1752,4 +1752,27 @@
|
||||
<data name="FailedToLoadSoftwareReleases" xml:space="preserve"><value>Falha ao carregar lançamentos de software.</value></data>
|
||||
<data name="FailedToDeleteSoftwareRelease" xml:space="preserve"><value>Falha ao excluir lançamento de software.</value></data>
|
||||
<data name="FailedToSaveSoftwareRelease" xml:space="preserve"><value>Falha ao salvar lançamento de software.</value></data>
|
||||
<data name="AllBooksButton" xml:space="preserve"><value>Todos os livros</value></data>
|
||||
<data name="BooksSearchBox_Placeholder" xml:space="preserve"><value>Pesquisar livros...</value></data>
|
||||
<data name="BooksErrorInfoBar_Title" xml:space="preserve"><value>Erro ao carregar livros</value></data>
|
||||
<data name="BooksLabel" xml:space="preserve"><value>livros</value></data>
|
||||
<data name="BookSynopsisLabel" xml:space="preserve"><value>Sinopse</value></data>
|
||||
<data name="BookAuthorsLabel" xml:space="preserve"><value>Autores e colaboradores</value></data>
|
||||
<data name="BookCompaniesLabel" xml:space="preserve"><value>Editoras e empresas</value></data>
|
||||
<data name="BookMachinesLabel" xml:space="preserve"><value>Máquinas relacionadas</value></data>
|
||||
<data name="BookMachineFamiliesLabel" xml:space="preserve"><value>Famílias de máquinas relacionadas</value></data>
|
||||
<data name="BookPreviousEditionLabel" xml:space="preserve"><value>Edição anterior</value></data>
|
||||
<data name="Books" xml:space="preserve"><value>Livros</value></data>
|
||||
<data name="Books in the database" xml:space="preserve"><value>Livros no banco de dados</value></data>
|
||||
<data name="No books found" xml:space="preserve"><value>Nenhum livro encontrado</value></data>
|
||||
<data name="Failed to load books data. Please try again later." xml:space="preserve"><value>Erro ao carregar os dados dos livros. Por favor, tente novamente mais tarde.</value></data>
|
||||
<data name="All Books" xml:space="preserve"><value>Todos os livros</value></data>
|
||||
<data name="Browsing all books in the database" xml:space="preserve"><value>Navegando por todos os livros no banco de dados</value></data>
|
||||
<data name="Books Starting with" xml:space="preserve"><value>Livros começando com</value></data>
|
||||
<data name="Showing books that start with" xml:space="preserve"><value>Mostrando livros que começam com</value></data>
|
||||
<data name="Books from" xml:space="preserve"><value>Livros de</value></data>
|
||||
<data name="Showing books published in" xml:space="preserve"><value>Mostrando livros publicados em</value></data>
|
||||
<data name="No books found for this filter" xml:space="preserve"><value>Nenhum livro encontrado para este filtro</value></data>
|
||||
<data name="Failed to load books. Please try again later." xml:space="preserve"><value>Erro ao carregar os livros. Por favor, tente novamente mais tarde.</value></data>
|
||||
<data name="Book not found" xml:space="preserve"><value>Livro não encontrado</value></data>
|
||||
</root>
|
||||
@@ -2098,4 +2098,27 @@
|
||||
<data name="FailedToLoadSoftwareReleases" xml:space="preserve"><value>Failed to load software releases.</value></data>
|
||||
<data name="FailedToDeleteSoftwareRelease" xml:space="preserve"><value>Failed to delete software release.</value></data>
|
||||
<data name="FailedToSaveSoftwareRelease" xml:space="preserve"><value>Failed to save software release.</value></data>
|
||||
<data name="AllBooksButton" xml:space="preserve"><value>All Books</value></data>
|
||||
<data name="BooksSearchBox_Placeholder" xml:space="preserve"><value>Search books...</value></data>
|
||||
<data name="BooksErrorInfoBar_Title" xml:space="preserve"><value>Error loading books</value></data>
|
||||
<data name="BooksLabel" xml:space="preserve"><value>books</value></data>
|
||||
<data name="BookSynopsisLabel" xml:space="preserve"><value>Synopsis</value></data>
|
||||
<data name="BookAuthorsLabel" xml:space="preserve"><value>Authors & Contributors</value></data>
|
||||
<data name="BookCompaniesLabel" xml:space="preserve"><value>Publishers & Companies</value></data>
|
||||
<data name="BookMachinesLabel" xml:space="preserve"><value>Related Machines</value></data>
|
||||
<data name="BookMachineFamiliesLabel" xml:space="preserve"><value>Related Machine Families</value></data>
|
||||
<data name="BookPreviousEditionLabel" xml:space="preserve"><value>Previous Edition</value></data>
|
||||
<data name="Books" xml:space="preserve"><value>Books</value></data>
|
||||
<data name="Books in the database" xml:space="preserve"><value>Books in the database</value></data>
|
||||
<data name="No books found" xml:space="preserve"><value>No books found</value></data>
|
||||
<data name="Failed to load books data. Please try again later." xml:space="preserve"><value>Failed to load books data. Please try again later.</value></data>
|
||||
<data name="All Books" xml:space="preserve"><value>All Books</value></data>
|
||||
<data name="Browsing all books in the database" xml:space="preserve"><value>Browsing all books in the database</value></data>
|
||||
<data name="Books Starting with" xml:space="preserve"><value>Books Starting with</value></data>
|
||||
<data name="Showing books that start with" xml:space="preserve"><value>Showing books that start with</value></data>
|
||||
<data name="Books from" xml:space="preserve"><value>Books from</value></data>
|
||||
<data name="Showing books published in" xml:space="preserve"><value>Showing books published in</value></data>
|
||||
<data name="No books found for this filter" xml:space="preserve"><value>No books found for this filter</value></data>
|
||||
<data name="Failed to load books. Please try again later." xml:space="preserve"><value>Failed to load books. Please try again later.</value></data>
|
||||
<data name="Book not found" xml:space="preserve"><value>Book not found</value></data>
|
||||
</root>
|
||||
20
Marechai.App/Services/BooksListFilterContext.cs
Normal file
20
Marechai.App/Services/BooksListFilterContext.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace Marechai.App.Services;
|
||||
|
||||
public interface IBooksListFilterContext
|
||||
{
|
||||
BookListFilterType FilterType { get; set; }
|
||||
string FilterValue { get; set; }
|
||||
}
|
||||
|
||||
public class BooksListFilterContext : IBooksListFilterContext
|
||||
{
|
||||
public BookListFilterType FilterType { get; set; } = BookListFilterType.All;
|
||||
public string FilterValue { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public enum BookListFilterType
|
||||
{
|
||||
All,
|
||||
Letter,
|
||||
Year
|
||||
}
|
||||
@@ -19,6 +19,104 @@ public class BooksService
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
// --- User-facing browsing methods ---
|
||||
|
||||
public async Task<int> GetBooksCountAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
int? result = await _apiClient.Books.Count.GetAsync();
|
||||
|
||||
return result ?? 0;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching books count");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int> GetMinimumYearAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
int? result = await _apiClient.Books.MinimumYear.GetAsync();
|
||||
|
||||
return result ?? 0;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching minimum year");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int> GetMaximumYearAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
int? result = await _apiClient.Books.MaximumYear.GetAsync();
|
||||
|
||||
return result ?? 0;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching maximum year");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<BookDto>> GetBooksByLetterAsync(char letter)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<BookDto>? books = await _apiClient.Books.ByLetter[letter.ToString()].GetAsync();
|
||||
|
||||
return books ?? [];
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching books by letter '{Letter}'", letter);
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<BookDto>> GetBooksByYearAsync(int year)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<BookDto>? books = await _apiClient.Books.ByYear[year].GetAsync();
|
||||
|
||||
return books ?? [];
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching books by year {Year}", year);
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<DocumentSynopsisDto?> GetBookSynopsisAsync(long bookId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _apiClient.Books[bookId].Synopsis.GetAsync();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching synopsis for book {Id}", bookId);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// --- CRUD ---
|
||||
|
||||
public async Task<List<BookDto>> GetAllBooksAsync()
|
||||
{
|
||||
try
|
||||
|
||||
@@ -285,7 +285,7 @@ namespace Marechai.App
|
||||
ApiClientBuilder.RegisterDefaultDeserializer<FormParseNodeFactory>();
|
||||
if (string.IsNullOrEmpty(RequestAdapter.BaseUrl))
|
||||
{
|
||||
RequestAdapter.BaseUrl = "http://localhost:5099";
|
||||
RequestAdapter.BaseUrl = "http://localhost:5023";
|
||||
}
|
||||
PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
// <auto-generated/>
|
||||
#pragma warning disable CS0618
|
||||
using Marechai.App.Books.ByLetter;
|
||||
using Marechai.App.Books.ByYear;
|
||||
using Marechai.App.Books.Companies;
|
||||
using Marechai.App.Books.Count;
|
||||
using Marechai.App.Books.Item;
|
||||
using Marechai.App.Books.MaximumYear;
|
||||
using Marechai.App.Books.MinimumYear;
|
||||
using Marechai.App.Books.Scans;
|
||||
using Marechai.App.Models;
|
||||
using Microsoft.Kiota.Abstractions.Extensions;
|
||||
@@ -20,11 +25,36 @@ namespace Marechai.App.Books
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class BooksRequestBuilder : BaseRequestBuilder
|
||||
{
|
||||
/// <summary>The byLetter property</summary>
|
||||
public global::Marechai.App.Books.ByLetter.ByLetterRequestBuilder ByLetter
|
||||
{
|
||||
get => new global::Marechai.App.Books.ByLetter.ByLetterRequestBuilder(PathParameters, RequestAdapter);
|
||||
}
|
||||
/// <summary>The byYear property</summary>
|
||||
public global::Marechai.App.Books.ByYear.ByYearRequestBuilder ByYear
|
||||
{
|
||||
get => new global::Marechai.App.Books.ByYear.ByYearRequestBuilder(PathParameters, RequestAdapter);
|
||||
}
|
||||
/// <summary>The companies property</summary>
|
||||
public global::Marechai.App.Books.Companies.CompaniesRequestBuilder Companies
|
||||
{
|
||||
get => new global::Marechai.App.Books.Companies.CompaniesRequestBuilder(PathParameters, RequestAdapter);
|
||||
}
|
||||
/// <summary>The count property</summary>
|
||||
public global::Marechai.App.Books.Count.CountRequestBuilder Count
|
||||
{
|
||||
get => new global::Marechai.App.Books.Count.CountRequestBuilder(PathParameters, RequestAdapter);
|
||||
}
|
||||
/// <summary>The maximumYear property</summary>
|
||||
public global::Marechai.App.Books.MaximumYear.MaximumYearRequestBuilder MaximumYear
|
||||
{
|
||||
get => new global::Marechai.App.Books.MaximumYear.MaximumYearRequestBuilder(PathParameters, RequestAdapter);
|
||||
}
|
||||
/// <summary>The minimumYear property</summary>
|
||||
public global::Marechai.App.Books.MinimumYear.MinimumYearRequestBuilder MinimumYear
|
||||
{
|
||||
get => new global::Marechai.App.Books.MinimumYear.MinimumYearRequestBuilder(PathParameters, RequestAdapter);
|
||||
}
|
||||
/// <summary>The scans property</summary>
|
||||
public global::Marechai.App.Books.Scans.ScansRequestBuilder Scans
|
||||
{
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// <auto-generated/>
|
||||
#pragma warning disable CS0618
|
||||
using Marechai.App.Books.ByLetter.Item;
|
||||
using Microsoft.Kiota.Abstractions.Extensions;
|
||||
using Microsoft.Kiota.Abstractions;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
namespace Marechai.App.Books.ByLetter
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds and executes requests for operations under \books\by-letter
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class ByLetterRequestBuilder : BaseRequestBuilder
|
||||
{
|
||||
/// <summary>Gets an item from the Marechai.App.books.byLetter.item collection</summary>
|
||||
/// <param name="position">Unique identifier of the item</param>
|
||||
/// <returns>A <see cref="global::Marechai.App.Books.ByLetter.Item.WithCItemRequestBuilder"/></returns>
|
||||
public global::Marechai.App.Books.ByLetter.Item.WithCItemRequestBuilder this[string position]
|
||||
{
|
||||
get
|
||||
{
|
||||
var urlTplParams = new Dictionary<string, object>(PathParameters);
|
||||
urlTplParams.Add("c", position);
|
||||
return new global::Marechai.App.Books.ByLetter.Item.WithCItemRequestBuilder(urlTplParams, RequestAdapter);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.ByLetter.ByLetterRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="pathParameters">Path parameters for the request</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public ByLetterRequestBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/by-letter", pathParameters)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.ByLetter.ByLetterRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public ByLetterRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/by-letter", rawUrl)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
@@ -0,0 +1,92 @@
|
||||
// <auto-generated/>
|
||||
#pragma warning disable CS0618
|
||||
using Marechai.App.Models;
|
||||
using Microsoft.Kiota.Abstractions.Extensions;
|
||||
using Microsoft.Kiota.Abstractions.Serialization;
|
||||
using Microsoft.Kiota.Abstractions;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System;
|
||||
namespace Marechai.App.Books.ByLetter.Item
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds and executes requests for operations under \books\by-letter\{c}
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class WithCItemRequestBuilder : BaseRequestBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.ByLetter.Item.WithCItemRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="pathParameters">Path parameters for the request</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public WithCItemRequestBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/by-letter/{c}", pathParameters)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.ByLetter.Item.WithCItemRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public WithCItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/by-letter/{c}", rawUrl)
|
||||
{
|
||||
}
|
||||
/// <returns>A List<global::Marechai.App.Models.BookDto></returns>
|
||||
/// <param name="cancellationToken">Cancellation token to use when cancelling requests</param>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
/// <exception cref="global::Marechai.App.Models.ProblemDetails">When receiving a 400 status code</exception>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public async Task<List<global::Marechai.App.Models.BookDto>?> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
#nullable restore
|
||||
#else
|
||||
public async Task<List<global::Marechai.App.Models.BookDto>> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
#endif
|
||||
var requestInfo = ToGetRequestInformation(requestConfiguration);
|
||||
var errorMapping = new Dictionary<string, ParsableFactory<IParsable>>
|
||||
{
|
||||
{ "400", global::Marechai.App.Models.ProblemDetails.CreateFromDiscriminatorValue },
|
||||
};
|
||||
var collectionResult = await RequestAdapter.SendCollectionAsync<global::Marechai.App.Models.BookDto>(requestInfo, global::Marechai.App.Models.BookDto.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false);
|
||||
return collectionResult?.AsList();
|
||||
}
|
||||
/// <returns>A <see cref="RequestInformation"/></returns>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default)
|
||||
{
|
||||
#nullable restore
|
||||
#else
|
||||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default)
|
||||
{
|
||||
#endif
|
||||
var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters);
|
||||
requestInfo.Configure(requestConfiguration);
|
||||
requestInfo.Headers.TryAdd("Accept", "text/plain;q=0.9");
|
||||
return requestInfo;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="global::Marechai.App.Books.ByLetter.Item.WithCItemRequestBuilder"/></returns>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
public global::Marechai.App.Books.ByLetter.Item.WithCItemRequestBuilder WithUrl(string rawUrl)
|
||||
{
|
||||
return new global::Marechai.App.Books.ByLetter.Item.WithCItemRequestBuilder(rawUrl, RequestAdapter);
|
||||
}
|
||||
/// <summary>
|
||||
/// Configuration for the request such as headers, query parameters, and middleware options.
|
||||
/// </summary>
|
||||
[Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class WithCItemRequestBuilderGetRequestConfiguration : RequestConfiguration<DefaultQueryParameters>
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
@@ -0,0 +1,61 @@
|
||||
// <auto-generated/>
|
||||
#pragma warning disable CS0618
|
||||
using Marechai.App.Books.ByYear.Item;
|
||||
using Microsoft.Kiota.Abstractions.Extensions;
|
||||
using Microsoft.Kiota.Abstractions;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
namespace Marechai.App.Books.ByYear
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds and executes requests for operations under \books\by-year
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class ByYearRequestBuilder : BaseRequestBuilder
|
||||
{
|
||||
/// <summary>Gets an item from the Marechai.App.books.byYear.item collection</summary>
|
||||
/// <param name="position">Unique identifier of the item</param>
|
||||
/// <returns>A <see cref="global::Marechai.App.Books.ByYear.Item.WithYearItemRequestBuilder"/></returns>
|
||||
public global::Marechai.App.Books.ByYear.Item.WithYearItemRequestBuilder this[int position]
|
||||
{
|
||||
get
|
||||
{
|
||||
var urlTplParams = new Dictionary<string, object>(PathParameters);
|
||||
urlTplParams.Add("year", position);
|
||||
return new global::Marechai.App.Books.ByYear.Item.WithYearItemRequestBuilder(urlTplParams, RequestAdapter);
|
||||
}
|
||||
}
|
||||
/// <summary>Gets an item from the Marechai.App.books.byYear.item collection</summary>
|
||||
/// <param name="position">Unique identifier of the item</param>
|
||||
/// <returns>A <see cref="global::Marechai.App.Books.ByYear.Item.WithYearItemRequestBuilder"/></returns>
|
||||
[Obsolete("This indexer is deprecated and will be removed in the next major version. Use the one with the typed parameter instead.")]
|
||||
public global::Marechai.App.Books.ByYear.Item.WithYearItemRequestBuilder this[string position]
|
||||
{
|
||||
get
|
||||
{
|
||||
var urlTplParams = new Dictionary<string, object>(PathParameters);
|
||||
if (!string.IsNullOrWhiteSpace(position)) urlTplParams.Add("year", position);
|
||||
return new global::Marechai.App.Books.ByYear.Item.WithYearItemRequestBuilder(urlTplParams, RequestAdapter);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.ByYear.ByYearRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="pathParameters">Path parameters for the request</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public ByYearRequestBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/by-year", pathParameters)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.ByYear.ByYearRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public ByYearRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/by-year", rawUrl)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
@@ -0,0 +1,92 @@
|
||||
// <auto-generated/>
|
||||
#pragma warning disable CS0618
|
||||
using Marechai.App.Models;
|
||||
using Microsoft.Kiota.Abstractions.Extensions;
|
||||
using Microsoft.Kiota.Abstractions.Serialization;
|
||||
using Microsoft.Kiota.Abstractions;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System;
|
||||
namespace Marechai.App.Books.ByYear.Item
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds and executes requests for operations under \books\by-year\{year}
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class WithYearItemRequestBuilder : BaseRequestBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.ByYear.Item.WithYearItemRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="pathParameters">Path parameters for the request</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public WithYearItemRequestBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/by-year/{year}", pathParameters)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.ByYear.Item.WithYearItemRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public WithYearItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/by-year/{year}", rawUrl)
|
||||
{
|
||||
}
|
||||
/// <returns>A List<global::Marechai.App.Models.BookDto></returns>
|
||||
/// <param name="cancellationToken">Cancellation token to use when cancelling requests</param>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
/// <exception cref="global::Marechai.App.Models.ProblemDetails">When receiving a 400 status code</exception>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public async Task<List<global::Marechai.App.Models.BookDto>?> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
#nullable restore
|
||||
#else
|
||||
public async Task<List<global::Marechai.App.Models.BookDto>> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
#endif
|
||||
var requestInfo = ToGetRequestInformation(requestConfiguration);
|
||||
var errorMapping = new Dictionary<string, ParsableFactory<IParsable>>
|
||||
{
|
||||
{ "400", global::Marechai.App.Models.ProblemDetails.CreateFromDiscriminatorValue },
|
||||
};
|
||||
var collectionResult = await RequestAdapter.SendCollectionAsync<global::Marechai.App.Models.BookDto>(requestInfo, global::Marechai.App.Models.BookDto.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false);
|
||||
return collectionResult?.AsList();
|
||||
}
|
||||
/// <returns>A <see cref="RequestInformation"/></returns>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default)
|
||||
{
|
||||
#nullable restore
|
||||
#else
|
||||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default)
|
||||
{
|
||||
#endif
|
||||
var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters);
|
||||
requestInfo.Configure(requestConfiguration);
|
||||
requestInfo.Headers.TryAdd("Accept", "text/plain;q=0.9");
|
||||
return requestInfo;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="global::Marechai.App.Books.ByYear.Item.WithYearItemRequestBuilder"/></returns>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
public global::Marechai.App.Books.ByYear.Item.WithYearItemRequestBuilder WithUrl(string rawUrl)
|
||||
{
|
||||
return new global::Marechai.App.Books.ByYear.Item.WithYearItemRequestBuilder(rawUrl, RequestAdapter);
|
||||
}
|
||||
/// <summary>
|
||||
/// Configuration for the request such as headers, query parameters, and middleware options.
|
||||
/// </summary>
|
||||
[Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class WithYearItemRequestBuilderGetRequestConfiguration : RequestConfiguration<DefaultQueryParameters>
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
@@ -0,0 +1,91 @@
|
||||
// <auto-generated/>
|
||||
#pragma warning disable CS0618
|
||||
using Marechai.App.Models;
|
||||
using Microsoft.Kiota.Abstractions.Extensions;
|
||||
using Microsoft.Kiota.Abstractions.Serialization;
|
||||
using Microsoft.Kiota.Abstractions;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System;
|
||||
namespace Marechai.App.Books.Count
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds and executes requests for operations under \books\count
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class CountRequestBuilder : BaseRequestBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.Count.CountRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="pathParameters">Path parameters for the request</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public CountRequestBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/count", pathParameters)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.Count.CountRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public CountRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/count", rawUrl)
|
||||
{
|
||||
}
|
||||
/// <returns>A <see cref="int"/></returns>
|
||||
/// <param name="cancellationToken">Cancellation token to use when cancelling requests</param>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
/// <exception cref="global::Marechai.App.Models.ProblemDetails">When receiving a 400 status code</exception>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public async Task<int?> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
#nullable restore
|
||||
#else
|
||||
public async Task<int?> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
#endif
|
||||
var requestInfo = ToGetRequestInformation(requestConfiguration);
|
||||
var errorMapping = new Dictionary<string, ParsableFactory<IParsable>>
|
||||
{
|
||||
{ "400", global::Marechai.App.Models.ProblemDetails.CreateFromDiscriminatorValue },
|
||||
};
|
||||
return await RequestAdapter.SendPrimitiveAsync<int?>(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
/// <returns>A <see cref="RequestInformation"/></returns>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default)
|
||||
{
|
||||
#nullable restore
|
||||
#else
|
||||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default)
|
||||
{
|
||||
#endif
|
||||
var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters);
|
||||
requestInfo.Configure(requestConfiguration);
|
||||
requestInfo.Headers.TryAdd("Accept", "text/plain;q=0.9");
|
||||
return requestInfo;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="global::Marechai.App.Books.Count.CountRequestBuilder"/></returns>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
public global::Marechai.App.Books.Count.CountRequestBuilder WithUrl(string rawUrl)
|
||||
{
|
||||
return new global::Marechai.App.Books.Count.CountRequestBuilder(rawUrl, RequestAdapter);
|
||||
}
|
||||
/// <summary>
|
||||
/// Configuration for the request such as headers, query parameters, and middleware options.
|
||||
/// </summary>
|
||||
[Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class CountRequestBuilderGetRequestConfiguration : RequestConfiguration<DefaultQueryParameters>
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
@@ -0,0 +1,91 @@
|
||||
// <auto-generated/>
|
||||
#pragma warning disable CS0618
|
||||
using Marechai.App.Models;
|
||||
using Microsoft.Kiota.Abstractions.Extensions;
|
||||
using Microsoft.Kiota.Abstractions.Serialization;
|
||||
using Microsoft.Kiota.Abstractions;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System;
|
||||
namespace Marechai.App.Books.MaximumYear
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds and executes requests for operations under \books\maximum-year
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class MaximumYearRequestBuilder : BaseRequestBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.MaximumYear.MaximumYearRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="pathParameters">Path parameters for the request</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public MaximumYearRequestBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/maximum-year", pathParameters)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.MaximumYear.MaximumYearRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public MaximumYearRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/maximum-year", rawUrl)
|
||||
{
|
||||
}
|
||||
/// <returns>A <see cref="int"/></returns>
|
||||
/// <param name="cancellationToken">Cancellation token to use when cancelling requests</param>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
/// <exception cref="global::Marechai.App.Models.ProblemDetails">When receiving a 400 status code</exception>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public async Task<int?> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
#nullable restore
|
||||
#else
|
||||
public async Task<int?> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
#endif
|
||||
var requestInfo = ToGetRequestInformation(requestConfiguration);
|
||||
var errorMapping = new Dictionary<string, ParsableFactory<IParsable>>
|
||||
{
|
||||
{ "400", global::Marechai.App.Models.ProblemDetails.CreateFromDiscriminatorValue },
|
||||
};
|
||||
return await RequestAdapter.SendPrimitiveAsync<int?>(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
/// <returns>A <see cref="RequestInformation"/></returns>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default)
|
||||
{
|
||||
#nullable restore
|
||||
#else
|
||||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default)
|
||||
{
|
||||
#endif
|
||||
var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters);
|
||||
requestInfo.Configure(requestConfiguration);
|
||||
requestInfo.Headers.TryAdd("Accept", "text/plain;q=0.9");
|
||||
return requestInfo;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="global::Marechai.App.Books.MaximumYear.MaximumYearRequestBuilder"/></returns>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
public global::Marechai.App.Books.MaximumYear.MaximumYearRequestBuilder WithUrl(string rawUrl)
|
||||
{
|
||||
return new global::Marechai.App.Books.MaximumYear.MaximumYearRequestBuilder(rawUrl, RequestAdapter);
|
||||
}
|
||||
/// <summary>
|
||||
/// Configuration for the request such as headers, query parameters, and middleware options.
|
||||
/// </summary>
|
||||
[Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class MaximumYearRequestBuilderGetRequestConfiguration : RequestConfiguration<DefaultQueryParameters>
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
@@ -0,0 +1,91 @@
|
||||
// <auto-generated/>
|
||||
#pragma warning disable CS0618
|
||||
using Marechai.App.Models;
|
||||
using Microsoft.Kiota.Abstractions.Extensions;
|
||||
using Microsoft.Kiota.Abstractions.Serialization;
|
||||
using Microsoft.Kiota.Abstractions;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System;
|
||||
namespace Marechai.App.Books.MinimumYear
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds and executes requests for operations under \books\minimum-year
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class MinimumYearRequestBuilder : BaseRequestBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.MinimumYear.MinimumYearRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="pathParameters">Path parameters for the request</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public MinimumYearRequestBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/minimum-year", pathParameters)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="global::Marechai.App.Books.MinimumYear.MinimumYearRequestBuilder"/> and sets the default values.
|
||||
/// </summary>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
|
||||
public MinimumYearRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/books/minimum-year", rawUrl)
|
||||
{
|
||||
}
|
||||
/// <returns>A <see cref="int"/></returns>
|
||||
/// <param name="cancellationToken">Cancellation token to use when cancelling requests</param>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
/// <exception cref="global::Marechai.App.Models.ProblemDetails">When receiving a 400 status code</exception>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public async Task<int?> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
#nullable restore
|
||||
#else
|
||||
public async Task<int?> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
#endif
|
||||
var requestInfo = ToGetRequestInformation(requestConfiguration);
|
||||
var errorMapping = new Dictionary<string, ParsableFactory<IParsable>>
|
||||
{
|
||||
{ "400", global::Marechai.App.Models.ProblemDetails.CreateFromDiscriminatorValue },
|
||||
};
|
||||
return await RequestAdapter.SendPrimitiveAsync<int?>(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
/// <returns>A <see cref="RequestInformation"/></returns>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default)
|
||||
{
|
||||
#nullable restore
|
||||
#else
|
||||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default)
|
||||
{
|
||||
#endif
|
||||
var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters);
|
||||
requestInfo.Configure(requestConfiguration);
|
||||
requestInfo.Headers.TryAdd("Accept", "text/plain;q=0.9");
|
||||
return requestInfo;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="global::Marechai.App.Books.MinimumYear.MinimumYearRequestBuilder"/></returns>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
public global::Marechai.App.Books.MinimumYear.MinimumYearRequestBuilder WithUrl(string rawUrl)
|
||||
{
|
||||
return new global::Marechai.App.Books.MinimumYear.MinimumYearRequestBuilder(rawUrl, RequestAdapter);
|
||||
}
|
||||
/// <summary>
|
||||
/// Configuration for the request such as headers, query parameters, and middleware options.
|
||||
/// </summary>
|
||||
[Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class MinimumYearRequestBuilderGetRequestConfiguration : RequestConfiguration<DefaultQueryParameters>
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"descriptionHash": "F3FC5617E7A71665428E4AA0614ADDFC285D8A654413C717584235C9DD36005081E280A8CD61559BA44BB138DB08B09307865C9C8B9D31241C7BD258673BD7B5",
|
||||
"descriptionLocation": "http://localhost:5099/openapi/v1.json",
|
||||
"descriptionHash": "724AE57924BB426C5D5FB34A738D07B85D6E2F86CBAB30EABF70114DD8FF3E4A103AE0A15C6BE3E19484B0557343A4E7B62A6580D4C3A1ECAC79793C6938D28A",
|
||||
"descriptionLocation": "http://localhost:5023/openapi/v1.json",
|
||||
"lockFileVersion": "1.0.0",
|
||||
"kiotaVersion": "1.29.0",
|
||||
"clientClassName": "ApiClient",
|
||||
|
||||
@@ -608,4 +608,14 @@ public class LocalizedStrings
|
||||
public string RegionLabel => _l["RegionLabel"];
|
||||
public string PublisherLabel => _l["PublisherLabel"];
|
||||
public string ReleaseDateLabel => _l["ReleaseDateLabel"];
|
||||
public string AllBooksButton => _l["AllBooksButton"];
|
||||
public string BooksSearchBox_Placeholder => _l["BooksSearchBox_Placeholder"];
|
||||
public string BooksErrorInfoBar_Title => _l["BooksErrorInfoBar_Title"];
|
||||
public string BooksLabel => _l["BooksLabel"];
|
||||
public string BookSynopsisLabel => _l["BookSynopsisLabel"];
|
||||
public string BookAuthorsLabel => _l["BookAuthorsLabel"];
|
||||
public string BookCompaniesLabel => _l["BookCompaniesLabel"];
|
||||
public string BookMachinesLabel => _l["BookMachinesLabel"];
|
||||
public string BookMachineFamiliesLabel => _l["BookMachineFamiliesLabel"];
|
||||
public string BookPreviousEditionLabel => _l["BookPreviousEditionLabel"];
|
||||
}
|
||||
|
||||
@@ -52,6 +52,88 @@ public class BooksController(MarechaiContext context, IConfiguration configurati
|
||||
];
|
||||
|
||||
readonly string _assetRootPath = configuration["AssetRootPath"]!;
|
||||
|
||||
[HttpGet("count")]
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public Task<int> GetBooksCountAsync() => context.Books.CountAsync();
|
||||
|
||||
[HttpGet("minimum-year")]
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public Task<int> GetMinimumYearAsync() => context.Books
|
||||
.Where(b => b.Published.HasValue &&
|
||||
b.Published.Value.Year > 1000)
|
||||
.MinAsync(b => b.Published.Value.Year);
|
||||
|
||||
[HttpGet("maximum-year")]
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public Task<int> GetMaximumYearAsync() => context.Books
|
||||
.Where(b => b.Published.HasValue &&
|
||||
b.Published.Value.Year > 1000)
|
||||
.MaxAsync(b => b.Published.Value.Year);
|
||||
|
||||
[HttpGet("by-letter/{c}")]
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public Task<List<BookDto>> GetBooksByLetterAsync(char c) => context.Books
|
||||
.Where(b =>
|
||||
(b.SortTitle != null &&
|
||||
EF.Functions.Like(b.SortTitle, $"{c}%")) ||
|
||||
(b.SortTitle == null &&
|
||||
EF.Functions.Like(b.Title, $"{c}%")))
|
||||
.OrderBy(b => b.SortTitle)
|
||||
.ThenBy(b => b.Title)
|
||||
.ThenBy(b => b.Published)
|
||||
.Select(b => new BookDto
|
||||
{
|
||||
Id = b.Id,
|
||||
Title = b.Title,
|
||||
NativeTitle = b.NativeTitle,
|
||||
SortTitle = b.SortTitle,
|
||||
Published = b.Published,
|
||||
Isbn = b.Isbn,
|
||||
CountryId = b.CountryId,
|
||||
Pages = b.Pages,
|
||||
Country = b.Country.Name,
|
||||
CoverGuid = b.CoverGuid,
|
||||
OriginalCoverExtension =
|
||||
b.OriginalCoverExtension
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
[HttpGet("by-year/{year:int}")]
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public Task<List<BookDto>> GetBooksByYearAsync(int year) => context.Books
|
||||
.Where(b => b.Published != null &&
|
||||
b.Published.Value.Year == year)
|
||||
.OrderBy(b => b.SortTitle)
|
||||
.ThenBy(b => b.Title)
|
||||
.ThenBy(b => b.Published)
|
||||
.Select(b => new BookDto
|
||||
{
|
||||
Id = b.Id,
|
||||
Title = b.Title,
|
||||
NativeTitle = b.NativeTitle,
|
||||
SortTitle = b.SortTitle,
|
||||
Published = b.Published,
|
||||
Isbn = b.Isbn,
|
||||
CountryId = b.CountryId,
|
||||
Pages = b.Pages,
|
||||
Country = b.Country.Name,
|
||||
CoverGuid = b.CoverGuid,
|
||||
OriginalCoverExtension =
|
||||
b.OriginalCoverExtension
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
|
||||
Reference in New Issue
Block a user