Initial commit - ECommerce.RCL
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
@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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user