Files
midrandbooks/MidrandBookshop/Components/Pages/Product.razor
T
2026-05-23 16:52:27 +02:00

137 lines
5.0 KiB
Plaintext

@page "/product/{BookId:long}"
@inject NavigationManager Navigation
<div class="product-container">
<nav class="breadcrumb">
<span @onclick='() => Navigation.NavigateTo("/")' class="crumb-link">Books</span>
<span class="crumb-separator">/</span>
<span class="crumb-current">@BookTitle</span>
</nav>
<div class="product-layout">
<div class="gallery-section">
<div class="main-image-wrapper">
<img src="@ActiveImageUrl" alt="@BookTitle" class="main-image" />
<div class="format-badges">
@if (IsPhysicalBook)
{
<span class="badge badge-physical">Book</span>
}
@if (IsEBook)
{
<span class="badge badge-ebook">E-Book</span>
}
@if (CanReadOnline)
{
<span class="badge badge-online">Read Online</span>
}
</div>
</div>
<div class="thumbnail-grid">
@foreach (var img in Thumbnails)
{
<div class="thumbnail-wrapper @(ActiveImageUrl == img ? "active" : "")"
@onclick="() => ActiveImageUrl = img">
<img src="@img" alt="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 <= CurrentRating ? "filled" : "")">★</span>
}
<span class="rating-text">(@CurrentRating.ToString("F1"))</span>
</div>
</div>
<h1 class="product-title">@BookTitle</h1>
<div class="product-price">R @Price.ToString("N2")</div>
<div class="purchase-actions">
<div class="quantity-picker">
<button @onclick="DecreaseQty" class="qty-btn">-</button>
<span class="qty-val">@Quantity</span>
<button @onclick="IncreaseQty" class="qty-btn">+</button>
</div>
<button class="btn-add-to-cart" @onclick="HandleAddToCart">
Add to Cart
</button>
</div>
<hr class="divider" />
<div class="info-block">
<h3>Description</h3>
<p class="description-text">@BookDescription</p>
</div>
<div class="info-block author-bio-card">
<h3>About the Author</h3>
<p class="author-bio">@AuthorBio</p>
<button class="btn-text-link" @onclick="ViewAllAuthorBooks">
View all books by @AuthorName →
</button>
</div>
</div>
</div>
</div>
@code {
[Parameter] public long BookId { get; set; }
// Mock State - In production, pull these via a Service using BookId inside OnInitialized
private string BookTitle { get; set; } = "Letters from M/M (Paris)";
private string AuthorName { get; set; } = "M/M Paris";
private string AuthorBio { get; set; } = "M/M Paris is an art and design partnership consisting of Michaël Amzalag and Mathias Augustyniak, established in 1992. Renowned globally for their influence on fashion, music, and contemporary art layout structures.";
private string BookDescription { get; set; } = "An exquisite archive tracking visual graphics, typography, and structural design curation over three decades. Beautifully bound with matte-coated plates and custom layouts.";
private decimal Price { get; set; } = 720.00m;
// Dynamic Ratings State
private double CurrentRating { get; set; } = 4.7;
// Formats supported
private bool IsPhysicalBook { get; set; } = true;
private bool IsEBook { get; set; } = true;
private bool CanReadOnline { get; set; } = false;
// Image Caching Gallery State
private string ActiveImageUrl { get; set; } = "images/book-cover-large.png";
private List<string> Thumbnails { get; set; } = new()
{
"images/book-cover-large.png",
"images/book-inside-1.png",
"images/book-inside-2.png"
};
private int Quantity { get; set; } = 1;
protected override void OnInitialized()
{
// Default the gallery viewer context logic
if (Thumbnails.Any())
{
ActiveImageUrl = Thumbnails.First();
}
}
private void IncreaseQty() => Quantity++;
private void DecreaseQty() { if (Quantity > 1) Quantity--; }
private void HandleAddToCart()
{
// Event logic hooked into your structural state layout
}
private void ViewAllAuthorBooks()
{
Navigation.NavigateTo($"/catalog?author={Uri.EscapeDataString(AuthorName)}");
}
}