diff --git a/MidrandBookshop/Components/Pages/Home.razor.cs b/MidrandBookshop/Components/Pages/Home.razor.cs index 5372ac5..f7ce3f2 100644 --- a/MidrandBookshop/Components/Pages/Home.razor.cs +++ b/MidrandBookshop/Components/Pages/Home.razor.cs @@ -47,19 +47,52 @@ public partial class Home : ComponentBase { var data = ProductsCollection.AsEnumerable(); - // Category filtering restricts rendering solely when checking the open catalog + // 1. Category Filtering if (ActiveCategory != "All" && !AuthorId.HasValue) + { data = data.Where(p => ProductPrimaryCategoryCache.ContainsKey(p.Id) && ProductPrimaryCategoryCache[p.Id] == ActiveCategory); + } - // Text matching is completely restricted from evaluating author metadata properties + // 2. Text Search Query Matching if (!string.IsNullOrWhiteSpace(SharedSearchQuery)) { var q = SharedSearchQuery.Trim(); - data = data.Where(p => (p.Name ?? "").Contains(q, StringComparison.OrdinalIgnoreCase)); } + // 3. FIX: Price Tier Constraint Selection Layout + 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 + }; + }); + } + + // 4. FIX: New Acquisition Flag Status Check + if (OnlyShowNew) + { + // Utilizing your mapping configuration: book.Enabled defines new arrival status + data = data.Where(p => p.Enabled); + } + + // 5. FIX: Collection Sorting Pipeline Extensions + 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 // Fallback to raw catalog chronological order sequence + }; + return data; } } diff --git a/MidrandBookshop/Components/Pages/ProductView.razor.css b/MidrandBookshop/Components/Pages/ProductView.razor.css index 898af69..87b9198 100644 --- a/MidrandBookshop/Components/Pages/ProductView.razor.css +++ b/MidrandBookshop/Components/Pages/ProductView.razor.css @@ -1,7 +1,6 @@ /* ========================================================================== Structural Layout Containers ========================================================================== */ - .product-container { max-width: 1200px; margin: 0 auto; @@ -18,7 +17,6 @@ /* ========================================================================== Breadcrumb Navigation Links ========================================================================== */ - .breadcrumb { font-size: 0.85rem; margin-bottom: 2.5rem; @@ -49,7 +47,6 @@ /* ========================================================================== Left Section: Media Gallery Components ========================================================================== */ - .gallery-section { display: flex; flex-direction: column; @@ -76,16 +73,21 @@ mix-blend-mode: multiply; } -/* Dynamic Overlaid Attribute Badges */ +/* Dynamic Overlaid Attribute Badges - Centered flawlessly without stacking */ .format-badges { - position: absolute; - bottom: 1.5rem; - left: 50%; - transform: translateX(-50%); - display: flex; - flex-wrap: wrap; - gap: 0.5rem; - white-space: nowrap; + position: absolute !important; + bottom: 1.5rem !important; + left: 50% !important; /* Move anchor point to exactly half-width */ + right: auto !important; + transform: translateX(-50%) !important; /* Offset width symmetrically to center perfectly */ + display: flex !important; + flex-direction: row !important; + flex-wrap: nowrap !important; /* Firmly prevents items from stacking vertically */ + justify-content: center !important; + align-items: center !important; + gap: 0.5rem !important; + width: max-content !important; /* Expands safely according to badges text values */ + max-width: 90% !important; /* Keeps bounding box clean of parent borders */ } .badge { @@ -96,6 +98,8 @@ border-radius: 100px; font-weight: 600; border: 1px solid transparent; + display: inline-block !important; + white-space: nowrap !important; /* Protects badge inner labels from broken line wrapping */ } .badge-physical { @@ -148,7 +152,6 @@ /* ========================================================================== Right Section: Product Details & Typography Controls ========================================================================== */ - .details-section { display: flex; flex-direction: column; @@ -209,7 +212,6 @@ /* ========================================================================== Interactive E-Commerce Selection Bars ========================================================================== */ - .purchase-actions { display: flex; gap: 1rem; @@ -274,7 +276,6 @@ /* ========================================================================== Informational Text Elements & Links ========================================================================== */ - .info-block { margin-bottom: 2rem; } @@ -321,7 +322,6 @@ /* ========================================================================== Responsive Adaptations & Breakpoints ========================================================================== */ - @media (max-width: 992px) { .product-layout { grid-template-columns: 1fr; @@ -338,6 +338,25 @@ padding: 1rem 1rem; } + .main-image-wrapper { + min-height: 320px; + padding: 2rem 1rem 4.5rem 1rem; /* Extra padding baseline clearance */ + } + + .main-image { + max-height: 240px; /* Fluidly limits image height to avoid overlay overlapping */ + } + + .format-badges { + bottom: 1.25rem !important; /* Fits beautifully aligned at the bottom center */ + gap: 0.4rem !important; + } + + .badge { + font-size: 0.65rem !important; /* Clean uniform scaling factor to clear margins */ + padding: 0.25rem 0.65rem !important; + } + .product-title { font-size: 1.85rem; }