Files
ECommerce.RCL/Components/Pages/Shop/Shop.razor
T

149 lines
6.4 KiB
Plaintext

@page "/shop"
@inject ProductAPIConsumer productService
@inject CategoryAPIConsumer categoryService
@inject NavigationManager nav
@using Common
<div class="flex flex-col gap-8 pb-20">
<!-- Hero Section -->
<div class="relative w-full h-80 rounded-2xl overflow-hidden shadow-2xl">
<div class="absolute inset-0 bg-cover bg-center"
style="background-image: url(https://img.daisyui.com/images/stock/photo-1507358522600-9f71e620c44e.webp);">
</div>
<div class="absolute inset-0 bg-black/50 backdrop-blur-[2px]"></div>
<div class="relative z-10 h-full flex flex-col justify-center items-center text-center text-white p-6">
<h1 class="text-4xl md:text-6xl font-extrabold mb-4 tracking-tight">Discover Premium Quality</h1>
<p class="text-lg md:text-xl text-gray-200 max-w-2xl">Explore our curated collection of top-tier products
and exclusive bundles designed to elevate your lifestyle.</p>
</div>
</div>
<!-- Filter Section -->
<EditForm Model="productFilter" OnValidSubmit="() => OnSearchProduct(1)"
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 border border-gray-100 dark:border-gray-700">
<div class="grid grid-cols-1 lg:grid-cols-4 gap-6 items-end">
<!-- Search -->
<div class="lg:col-span-1">
<label class="block text-sm font-semibold text-gray-700 dark:text-gray-300 mb-2">Search</label>
<div class="relative">
<InputText @bind-Value="productFilter.Name" placeholder="Search products..."
class="w-full pl-4 pr-10 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all dark:bg-gray-700 dark:border-gray-600 dark:text-white" />
<button type="submit"
class="absolute right-2 top-1/2 -translate-y-1/2 p-2 text-gray-400 hover:text-blue-500">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</button>
</div>
</div>
<!-- Category -->
<div class="lg:col-span-1">
<label class="block text-sm font-semibold text-gray-700 dark:text-gray-300 mb-2">Category</label>
<CategoryTreeSelect @bind-Value="productFilter.CategoryId" ShowBundles="false"
Placeholder="All Categories" />
</div>
<!-- Type -->
<div class="lg:col-span-1">
<label class="block text-sm font-semibold text-gray-700 dark:text-gray-300 mb-2">Type</label>
<InputSelect @bind-Value="productFilter.IsBundle"
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all dark:bg-gray-700 dark:border-gray-600 dark:text-white">
<option value="">All Types</option>
<option value="true">Bundles Only</option>
<option value="false">Products Only</option>
</InputSelect>
</div>
<!-- Price -->
<div class="lg:col-span-1">
<label class="block text-sm font-semibold text-gray-700 dark:text-gray-300 mb-2">Max Price</label>
<InputNumber @bind-Value="productFilter.Price" placeholder="Max Price"
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all dark:bg-gray-700 dark:border-gray-600 dark:text-white" />
</div>
<!-- Discount -->
<div class="lg:col-span-1">
<label class="block text-sm font-semibold text-gray-700 dark:text-gray-300 mb-2">Min Discount %</label>
<InputNumber @bind-Value="productFilter.Discount" placeholder="Min Discount"
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all dark:bg-gray-700 dark:border-gray-600 dark:text-white" />
</div>
<!-- Action -->
<div class="lg:col-span-1">
<button type="submit"
class="w-full py-3 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-lg shadow-md transition-colors duration-200">
Apply Filters
</button>
</div>
</div>
</EditForm>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 w-full h-full gap-5 p-5 md:p-12 lg:p-20">
@foreach (var product in products)
{
<ProductComp4 Product="product" />
}
</div>
<PaginationComp OnSearch="OnSearchProduct" PaginationModel="pagination"></PaginationComp>
</div>
@code {
public Pagination pagination { get; set; } = new() { CurrentPage = 1, PageSize = 15 };
public ProductFilter productFilter { get; set; } = new ProductFilter();
List<ProductVM> products = new List<ProductVM>();
[Parameter, SupplyParameterFromQuery]
public string? CategoryId { get; set; }
[Parameter, SupplyParameterFromQuery]
public bool? IsBundle { get; set; }
protected async override Task OnParametersSetAsync()
{
bool changed = false;
if (!string.IsNullOrEmpty(CategoryId) && Guid.TryParse(CategoryId, out var categoryGuid))
{
productFilter.CategoryId = categoryGuid;
changed = true;
}
if (IsBundle.HasValue)
{
productFilter.IsBundle = IsBundle.Value;
changed = true;
}
if (changed)
{
await OnSearchProduct();
}
}
protected async override Task OnInitializedAsync()
{
if (string.IsNullOrEmpty(CategoryId))
{
await OnSearchProduct();
}
}
async Task OnSearchProduct(int pageNumber = 1)
{
pagination.CurrentPage = pageNumber;
var result = await productService.FetchProduct(productFilter, pagination);
products = result.Item1;
pagination.ItemsCount = result.Item2;
}
}