using Microsoft.AspNetCore.Components; using Prefab.Web.Client.Models.Catalog; using Prefab.Web.Client.Models.Home; using Prefab.Web.Client.Services; using Prefab.Web.Client.ViewModels.Catalog; namespace Prefab.Web.Client.Pages; public class HomeComponent : ResultComponentBase { private const int CategorySkeletonSlots = 4; private readonly List _featuredProducts = []; private readonly List _latestCategories = []; [Inject] protected IHomePageService HomePageService { get; set; } = null!; public IEnumerable Slides => new List { new() { Number = 1, Text = "Take on more work, without adding more people.", TextWidth = "full", TextPosition = "top-right" }, new() { Number = 4, Text = "Real-time visibility to your assemblies.", TextWidth = "half", TextPosition = "center-right" }, new() { Number = 2, Text = "Explore, configure, order, install.", TextWidth = "full", TextPosition = "top-left" } }; protected IReadOnlyList FeaturedProducts => _featuredProducts; protected bool IsFeaturedProductsLoading { get; private set; } = true; protected bool FeaturedProductsHaveItemsToShow => _featuredProducts.Count > 0; protected int NumberOfFeaturedProductCardsPerGroup { get; private set; } = 4; protected IReadOnlyList LatestCategories => _latestCategories; protected bool AreCategoriesLoading { get; private set; } = true; protected bool CategoriesHaveItemsToShow => _latestCategories.Count > 0; protected int NumberOfCategorySkeletons => CategorySkeletonSlots; protected override async Task OnInitializedAsync() { await LoadHomeContentAsync(); } protected IReadOnlyList> GetProductCardGroups() { if (!FeaturedProductsHaveItemsToShow) { return Array.Empty>(); } var groupSize = Math.Max(1, NumberOfFeaturedProductCardsPerGroup); var groups = new List>(); for (var index = 0; index < _featuredProducts.Count; index += groupSize) { var segment = _featuredProducts .Skip(index) .Take(groupSize) .ToList(); if (segment.Count > 0) { groups.Add(segment); } } return groups; } protected string CalculateWidthOfFeaturedProductCard() { var groupSize = Math.Max(1, NumberOfFeaturedProductCardsPerGroup); var width = 100d / groupSize; return $"width: {width:0.##}%; padding: 0 10px; box-sizing: border-box;"; } #region Media Query Handlers protected void OnExtraSmallChange(bool matches) { if (!matches) { return; } NumberOfFeaturedProductCardsPerGroup = 1; StateHasChanged(); } protected void OnSmallChange(bool matches) { if (!matches) { return; } NumberOfFeaturedProductCardsPerGroup = 2; StateHasChanged(); } protected void OnMediumChange(bool matches) { if (!matches) { return; } NumberOfFeaturedProductCardsPerGroup = 2; StateHasChanged(); } protected void OnLargeChange(bool matches) { if (!matches) { return; } NumberOfFeaturedProductCardsPerGroup = 3; StateHasChanged(); } protected void OnExtraLargeChange(bool matches) { if (!matches) { return; } NumberOfFeaturedProductCardsPerGroup = 4; StateHasChanged(); } #endregion private async Task LoadHomeContentAsync() { IsFeaturedProductsLoading = true; AreCategoriesLoading = true; _featuredProducts.Clear(); _latestCategories.Clear(); try { var result = await Execute(HomePageService.Get, CancellationToken.None); if (result.IsSuccess && result.Value is { } payload) { if (payload.FeaturedProducts.Count > 0) { _featuredProducts.AddRange(payload.FeaturedProducts); } if (payload.LatestCategories.Count > 0) { _latestCategories.AddRange(payload.LatestCategories); } } } finally { IsFeaturedProductsLoading = false; AreCategoriesLoading = false; } } public class Slide { public int Number { get; set; } public string Text { get; set; } = string.Empty; public string TextWidth { get; set; } = string.Empty; public string TextPosition { get; set; } = string.Empty; public string AltText { get; set; } = string.Empty; public string GoToUrl { get; set; } = string.Empty; } }