Files
Khwezi Mngoma 8d2efbeb4a
continuous-integration/drone/pr Build is passing
Added legal pages, contact and abut us
Redesigned account, checkout
Added stock management design elements
2026-06-16 23:32:44 +02:00

148 lines
6.5 KiB
Plaintext

@page "/product/{BookId:long}"
@rendermode InteractiveServer
<div class="product-container">
@if (IsLoading)
{
<div class="text-center py-5">
<div class="spinner-border text-dark" role="status">
<span class="visually-hidden">Loading product details...</span>
</div>
<p class="text-muted mt-2">Loading curated details...</p>
</div>
}
else if (CurrentProduct == null)
{
<div class="text-center py-5 animate-fade-in">
<svg class="text-muted mb-3" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<circle cx="12" cy="12" r="10" />
<line x1="12" y1="8" x2="12" y2="12" />
<line x1="12" y1="16" x2="12.01" y2="16" />
</svg>
<h2 class="h5 text-dark fw-medium">Artifact Not Found</h2>
<p class="text-muted small">The requested book could not be found in our current catalog.</p>
<button class="btn btn-dark btn-sm rounded-pill px-4 mt-2" @onclick='() => Navigation.NavigateTo("/")'>Return to Books</button>
</div>
}
else
{
<nav class="breadcrumb">
<span @onclick='() => Navigation.NavigateTo("/")' class="crumb-link">Books</span>
<span class="crumb-separator">/</span>
<span class="crumb-current">@CurrentProduct.Name</span>
</nav>
<div class="product-layout">
<div class="gallery-section">
<div class="main-image-wrapper">
@if (!string.IsNullOrWhiteSpace(ActiveImageUrl))
{
<img src="@ActiveImageUrl" alt="@CurrentProduct.Name" class="main-image" />
}
else
{
<div class="book-spine-fallback-large bg-dark d-flex align-items-center justify-content-center text-center p-4 text-white-50 shadow-sm">
<div>
<span class="fw-semibold tracking-wider d-block">@PrimaryCategory.ToUpper()</span>
<span class="opacity-50 small" style="font-size: 0.65rem;">CURATED EDITION</span>
</div>
</div>
}
<div class="format-badges">
@if (CurrentProduct.Enabled)
{
<span class="badge badge-physical">Physical Book</span>
}
@if (StockCount <= 0)
{
<span class="badge bg-danger text-white border-0">Out of Stock</span>
}
else if (StockCount <= 3)
{
<span class="badge bg-warning text-dark border-0">Only @StockCount Left</span>
}
else
{
<span class="badge badge-ebook">In Stock (@StockCount available)</span>
}
</div>
</div>
@if (Thumbnails.Count > 1)
{
<div class="thumbnail-grid">
@foreach (var img in Thumbnails)
{
var currentImg = img;
<div class="thumbnail-wrapper @(ActiveImageUrl == currentImg ? "active" : "")"
@onclick="() => ActiveImageUrl = currentImg">
<img src="@currentImg" alt="Catalog gallery thumbnail" />
</div>
}
</div>
}
</div>
<div class="details-section">
<div class="meta-header">
<span class="author-name">@AuthorName</span>
<div class="rating-stars">
@for (int i = 1; i <= 5; i++)
{
<span class="star @(i <= 4 ? "filled" : "")">★</span>
}
<span class="rating-text">(4.8)</span>
</div>
</div>
<h1 class="product-title">@CurrentProduct.Name</h1>
<div class="product-price">R @LivePrice.ToString("N2")</div>
<div class="purchase-actions">
<div class="quantity-picker @(StockCount <= 0 ? "opacity-50 pointer-events-none" : "")">
<button @onclick="DecreaseQty" class="qty-btn" disabled="@(StockCount <= 0 || Quantity <= 1)">-</button>
<span class="qty-val">@(StockCount <= 0 ? 0 : Quantity)</span>
<button @onclick="IncreaseQty" class="qty-btn" disabled="@(StockCount <= 0 || Quantity >= StockCount)">+</button>
</div>
@if (StockCount > 0)
{
<button class="btn-add-to-cart" @onclick="HandleAddToCart">
Add to Cart
</button>
}
else
{
<button class="btn-add-to-cart bg-secondary text-white-50 cursor-not-allowed" disabled>
Sold Out
</button>
}
</div>
<hr class="divider" />
@if (!string.IsNullOrWhiteSpace(CurrentProduct.Description))
{
<div class="info-block">
<h3>Description</h3>
<p class="description-text">@CurrentProduct.Description</p>
</div>
}
<div class="info-block author-bio-card">
<h3>About the Author</h3>
<p class="author-bio">
@(string.IsNullOrWhiteSpace(CurrentProduct.Metadata?.Manufacturer)
? "Details regarding this publisher/author are maintained inside our curated archives."
: $"{CurrentProduct.Metadata.Manufacturer} is globally recognized for their direct contribution to this specific genre spectrum.")
</p>
<button class="btn-text-link" @onclick="ViewAllAuthorBooks">
View all books by @AuthorName →
</button>
</div>
</div>
</div>
}
</div>