- Added /admin redirect to login page in nginx config - Fixed backend server.js route ordering for proper admin handling - Updated authentication middleware and routes - Added user management routes - Configured PostgreSQL integration - Updated environment configuration
81 lines
4.0 KiB
Plaintext
81 lines
4.0 KiB
Plaintext
@model List<SkyArtShop.Models.Product>
|
|
@{
|
|
ViewData["Title"] = "Shop";
|
|
var categories = ViewBag.Categories as List<string> ?? new();
|
|
var selected = ViewBag.SelectedCategory as string;
|
|
}
|
|
|
|
<section class="shop-hero">
|
|
<div class="container">
|
|
<h1>Shop All Products</h1>
|
|
<p class="hero-subtitle">Find everything you need for your creative projects</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="shop-filters">
|
|
<div class="container">
|
|
<div class="filter-bar">
|
|
<div class="filter-group">
|
|
<label for="category-filter">Category:</label>
|
|
<select id="category-filter" onchange="window.location.href='/shop?category='+this.value;">
|
|
<option value="">All Products</option>
|
|
@foreach (var cat in categories)
|
|
{
|
|
<option value="@cat" selected="@(selected == cat ? "selected" : null)">@cat</option>
|
|
}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="shop-products">
|
|
<div class="container">
|
|
<div class="products-grid">
|
|
@foreach (var product in Model)
|
|
{
|
|
<div class="product-card">
|
|
<a href="/shop/product/@product.Id" class="product-link">
|
|
<div class="product-image">
|
|
@{
|
|
var displayImage = !string.IsNullOrEmpty(product.ImageUrl)
|
|
? product.ImageUrl
|
|
: (product.Images != null && product.Images.Count > 0
|
|
? product.Images[0]
|
|
: "/assets/images/placeholder.jpg");
|
|
}
|
|
<img src="@displayImage" alt="@product.Name" loading="lazy" />
|
|
</div>
|
|
<h3>@product.Name</h3>
|
|
@if (!string.IsNullOrEmpty(product.Color))
|
|
{
|
|
<span class="product-color-badge">@product.Color</span>
|
|
}
|
|
<div class="product-description">@Html.Raw(product.ShortDescription ?? product.Description)</div>
|
|
<p class="price">$@product.Price.ToString("F2")</p>
|
|
</a>
|
|
<div style="display: flex; gap: 0.5rem; margin-top: 0.5rem;">
|
|
<button class="btn btn-small btn-icon"
|
|
onclick="addToWishlist('@product.Id', '@product.Name', @product.Price, '@(product.Images != null && product.Images.Count > 0 ? product.Images[0] : product.ImageUrl ?? "/assets/images/placeholder.jpg")')"
|
|
aria-label="Add to wishlist">
|
|
<i class="bi bi-heart"></i>
|
|
</button>
|
|
<button class="btn btn-small btn-icon"
|
|
onclick="addToCart('@product.Id', '@product.Name', @product.Price, '@(product.Images != null && product.Images.Count > 0 ? product.Images[0] : product.ImageUrl ?? "/assets/images/placeholder.jpg")')" aria-label="Add to cart">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
<path
|
|
d="M7 4h-2l-1 2h-2v2h2l3.6 7.59-1.35 2.44c-.16.28-.25.61-.25.97 0 1.1.9 2 2 2h12v-2h-11.1c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.42c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1h-14.31l-.94-2zm3 17c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm8 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
@section Scripts {
|
|
<script>
|
|
// Cart functionality now loaded from cart.js
|
|
</script>
|
|
} |