149 lines
6.4 KiB
Plaintext
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;
|
|
}
|
|
} |