using LiteCharms.Features; using LiteCharms.Features.MidrandBooks.AuthorBooks; using LiteCharms.Features.MidrandBooks.Authors; using LiteCharms.Features.MidrandBooks.Categories; using LiteCharms.Features.MidrandBooks.Payments; using LiteCharms.Features.MidrandBooks.Products; using LiteCharms.Features.MidrandBooks.Products.Models; using LiteCharms.Features.Models; namespace MidrandBookshop.Components.Pages; public partial class Home : ComponentBase { [Inject] private ProductService ProductService { get; set; } = default!; [Inject] private BooksService BooksService { get; set; } = default!; [Inject] private AuthorService AuthorService { get; set; } = default!; [Inject] private CategoryService CategoryService { get; set; } = default!; [Inject] private NavigationManager Navigation { get; set; } = default!; [Inject] private HydrationService HydrationService { get; set; } = default!; [Inject] private CancellationToken CancellationToken { get; set; } = default!; [Inject] private CartService CartService { get; set; } = default!; [SupplyParameterFromQuery(Name = "q")] public string? SharedSearchQuery { get; set; } [SupplyParameterFromQuery] public long? AuthorId { get; set; } private ElementReference topTargetRef; public enum ViewMode { Grid, List } private ViewMode CurrentViewMode = ViewMode.Grid; private string ActiveCategory = "All"; private bool ShowExpandedCategories = false; private bool ShowFilterMenu = false; private string SelectedSortOption = "default"; private string ActivePriceFilter = "all"; private bool OnlyShowNew = false; private List MainCategories { get; set; } = ["All"]; private List DynamicExtendedCategories { get; set; } = []; private int ItemsPerPage = 12; private int VisibleCount = 12; private List ProductsCollection { get; set; } = []; protected string? ActiveAuthorFilterName { get; private set; } private Dictionary ProductPriceCache { get; set; } = []; private Dictionary ProductPrimaryCategoryCache { get; set; } = []; private Dictionary ProductAuthorCache { get; set; } = []; private IEnumerable FilteredData { get { var data = ProductsCollection.AsEnumerable(); if (ActiveCategory != "All" && !AuthorId.HasValue) { data = data.Where(p => ProductPrimaryCategoryCache.ContainsKey(p.Id) && ProductPrimaryCategoryCache[p.Id] == ActiveCategory); } if (!string.IsNullOrWhiteSpace(SharedSearchQuery)) { var q = SharedSearchQuery.Trim(); data = data.Where(p => (p.Name ?? "").Contains(q, StringComparison.OrdinalIgnoreCase)); } if (ActivePriceFilter != "all") { data = data.Where(p => { var price = ProductPriceCache.TryGetValue(p.Id, out var amt) ? amt : 0m; return ActivePriceFilter switch { "under-500" => price < 500m, "500-1000" => price >= 500m && price <= 1000m, "over-1000" => price > 1000m, _ => true }; }); } if (OnlyShowNew) data = data.Where(p => p.Enabled); data = SelectedSortOption switch { "price-low" => data.OrderBy(p => ProductPriceCache.TryGetValue(p.Id, out var amt) ? amt : 0m), "price-high" => data.OrderByDescending(p => ProductPriceCache.TryGetValue(p.Id, out var amt) ? amt : 0m), "title-asc" => data.OrderBy(p => p.Name ?? string.Empty, StringComparer.OrdinalIgnoreCase), "default" or _ => data }; return data; } } private IEnumerable PaginatedBooks => FilteredData.Take(VisibleCount); private bool HasMoreItems => FilteredData.Count() > VisibleCount; protected override async Task OnInitializedAsync() { if (CartService.ShoppingCart.Items.Count == 0) await CartService.LoadCartFromStorageAsync(); } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender == false && HydrationService.CartHydrated == false) { if(!CartService.ShoppingCart.CustomerId.HasValue) await HydrationService.EnsureCustomerExistsAsync(CancellationToken); } } protected override async Task OnParametersSetAsync() => await LoadCatalogDataAsync(); private async Task LoadCatalogDataAsync() { ProductsCollection.Clear(); ProductPriceCache.Clear(); ProductPrimaryCategoryCache.Clear(); ProductAuthorCache.Clear(); ActiveAuthorFilterName = null; if (AuthorId.HasValue) { var authorResult = await AuthorService.GetAuthorAsync(AuthorId.Value); if (authorResult.IsSuccess && authorResult.Value != null) { var author = authorResult.Value; ActiveAuthorFilterName = author.PublisherType == PublisherTypes.Company && !string.IsNullOrWhiteSpace(author.Company) ? author.Company : $"{author.Name} {author.LastName}".Trim(); } var authorBooksResult = await BooksService.GetBooksByAuthorAsync(AuthorId.Value); if (authorBooksResult.IsSuccess && authorBooksResult.Value != null) { foreach (var authorBook in authorBooksResult.Value) { if (authorBook.Product != null) { var product = authorBook.Product; ProductsCollection.Add(product); ProductPriceCache[product.Id] = product.Price?.Amount ?? 0m; ProductAuthorCache[product.Id] = ActiveAuthorFilterName ?? "Unknown Author"; var categoryResult = await ProductService.GetProductCategoriesAsync(product.Id); ProductPrimaryCategoryCache[product.Id] = (categoryResult.IsSuccess && categoryResult.Value.Length > 0) ? (categoryResult.Value[0].Name ?? "General") : "General"; } } } return; } var selectionRange = new DateRange { From = new DateOnly(2020, 1, 1), To = DateOnly.FromDateTime(DateTime.UtcNow.AddDays(1)), MaxRecords = 100 }; var allProductsResult = await ProductService.GetProductsAsync(0, selectionRange); if (allProductsResult.IsSuccess && allProductsResult.Value != null) { ProductsCollection = allProductsResult.Value.ToList(); foreach (var product in ProductsCollection) { var priceResult = await ProductService.GetProductPriceAsync(product.Id); ProductPriceCache[product.Id] = priceResult.IsSuccess ? priceResult.Value.Amount : 0m; var categoryResult = await ProductService.GetProductCategoriesAsync(product.Id); ProductPrimaryCategoryCache[product.Id] = (categoryResult.IsSuccess && categoryResult.Value.Length > 0) ? (categoryResult.Value[0].Name ?? "General") : "General"; ProductAuthorCache[product.Id] = !string.IsNullOrWhiteSpace(product.Metadata?.Manufacturer) ? product.Metadata.Manufacturer : "Unknown Author"; } } var categoriesResult = await CategoryService.GetCategoriesAsync(); if (categoriesResult.IsSuccess && categoriesResult.Value != null) { var cleanNames = categoriesResult.Value .Select(c => c.Name) .Where(n => !string.IsNullOrEmpty(n)).Cast() .ToList(); MainCategories = ["All", .. cleanNames.Take(3)]; DynamicExtendedCategories = [.. cleanNames.Skip(3)]; } } private void ClearAuthorFilter() { var newUri = Navigation.GetUriWithQueryParameters("/", new Dictionary { { "authorId", null } }); Navigation.NavigateTo(newUri); } private void ResetFilters() { SelectedSortOption = "default"; ActivePriceFilter = "all"; OnlyShowNew = false; VisibleCount = ItemsPerPage; } private void NavigateToProduct(long id) => Navigation.NavigateTo($"/product/{id}"); private void SetViewMode(ViewMode targetMode) => CurrentViewMode = targetMode; private void SelectCategory(string categoryName) { ActiveCategory = categoryName; VisibleCount = ItemsPerPage; var updatedUri = Navigation.GetUriWithQueryParameters(Navigation.Uri, new Dictionary {{ "q", null }}); Navigation.NavigateTo(updatedUri); } private void ToggleExtraCategories() => ShowExpandedCategories = !ShowExpandedCategories; private void ToggleFilterMenu() => ShowFilterMenu = !ShowFilterMenu; private void ChangeSort(string sortOption) => SelectedSortOption = sortOption; private void ChangePriceFilter(string priceBracket) { ActivePriceFilter = priceBracket; VisibleCount = ItemsPerPage; } private void ToggleNewArrivalsOnly(ChangeEventArgs e) { OnlyShowNew = e.Value is bool b && b; VisibleCount = ItemsPerPage; } private void LoadNextPage() { if (HasMoreItems) VisibleCount += ItemsPerPage; } }