Files
abzarasadi/Pages/Shop/Detail.cshtml
T
Soroush Asadi f97f891d67
CI/CD / CI — dotnet build (push) Successful in 44s
CI/CD / Deploy — docker compose (push) Failing after 1s
Initial commit — AsadiTools v1.0
Full ASP.NET Core 10 Razor Pages app for آساد ابزار tool repair shop
in Karaj, Iran (official DeWalt representative).

Features:
- Homepage, Services, DeWalt page, Shop (pagination + images)
- 10 brand SEO pages (/brands/*) with rich Persian content + FAQ schema
- Blog engine with admin management (/blog, /Admin/Blog)
- Cart, Checkout, Contact (OpenStreetMap embed)
- Admin panel: Products CRUD, Orders, Blog, Change Password
- Jalali date formatting, product images, SiteData centralised contact
- Docker + docker-compose with healthcheck
- Gitea CI/CD via .gitea/workflows/ci-cd.yml (NuGet through Nexus mirror)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 22:08:43 +03:30

75 lines
4.0 KiB
Plaintext

@page
@model AsadiTools.Pages.Shop.DetailModel
@{ ViewData["Title"] = Model.Product?.NameFa ?? "قطعه"; Layout = "_Layout"; }
@if (Model.Product is null)
{
<div class="max-w-xl mx-auto text-center py-20"><p class="text-gray-500">محصول یافت نشد.</p><a href="/Shop" class="text-blue-600 hover:underline mt-2 block">بازگشت به فروشگاه</a></div>
}
else
{
var p = Model.Product;
var cat = SiteData.Categories.FirstOrDefault(c => c.Id == p.Category);
var brand = SiteData.Brands.FirstOrDefault(b => b.Id == p.Brand);
<div class="max-w-5xl mx-auto px-4 py-8">
<nav class="flex items-center gap-2 text-sm text-gray-500 mb-8">
<a href="/" class="hover:text-blue-600">خانه</a><span>/</span>
<a href="/Shop" class="hover:text-blue-600">فروشگاه</a><span>/</span>
<span class="text-gray-800">@p.NameFa</span>
</nav>
<div class="grid md:grid-cols-2 gap-10">
<div class="rounded-3xl overflow-hidden aspect-square @(string.IsNullOrEmpty(p.ImageUrl) ? "bg-gradient-to-br from-blue-50 to-blue-100 flex items-center justify-center text-8xl" : "")">
@if (!string.IsNullOrEmpty(p.ImageUrl))
{
<img src="@p.ImageUrl" alt="@p.NameFa" class="w-full h-full object-cover" />
}
else
{
@(cat?.Icon ?? "🔧")
}
</div>
<div>
<div class="flex flex-wrap gap-2 mb-4">
@if (brand != null) { <span class="text-sm font-bold px-3 py-1 rounded-full text-white" style="background-color:@brand.Color">@brand.NameFa</span> }
@if (cat != null) { <span class="text-sm px-3 py-1 rounded-full bg-gray-100 text-gray-600">@cat.Icon @cat.NameFa</span> }
</div>
<h1 class="text-2xl font-extrabold text-gray-900 mb-2">@p.NameFa</h1>
@if (p.NameEn != null) { <p class="text-gray-400 text-sm mb-4 font-mono">@p.NameEn</p> }
@if (p.Sku != null) { <p class="text-xs text-gray-400 mb-6 bg-gray-100 inline-block px-3 py-1 rounded-full">کد محصول: @p.Sku</p> }
@if (p.Description != null) { <p class="text-gray-600 leading-7 mb-6 text-sm">@p.Description</p> }
<div class="mb-6">
@if (p.HasDiscount) { <p class="text-gray-400 line-through text-lg">@SiteData.FormatPrice(p.Price)</p> }
<p class="text-3xl font-extrabold text-blue-700">@SiteData.FormatPrice(p.FinalPrice)</p>
</div>
<div class="mb-6">
@if (p.Stock > 0)
{
<span class="text-green-600 text-sm font-medium">🟢 موجود در انبار (@p.Stock عدد)</span>
}
else
{
<span class="text-red-500 text-sm font-medium">🔴 ناموجود</span>
}
</div>
<form method="post" class="flex gap-3">
@Html.AntiForgeryToken()
<input type="hidden" name="productId" value="@p.Id" />
<input type="hidden" name="nameFa" value="@p.NameFa" />
<input type="hidden" name="price" value="@p.FinalPrice" />
<input type="hidden" name="sku" value="@p.Sku" />
<button type="submit" @(p.Stock == 0 ? "disabled" : "")
class="flex-1 flex items-center justify-center gap-2 bg-blue-700 text-white py-3.5 rounded-xl font-bold hover:bg-blue-800 transition-colors disabled:bg-gray-200 disabled:text-gray-400">
🛒 @(p.Stock == 0 ? "ناموجود" : "افزودن به سبد خرید")
</button>
<a href="/Cart" class="flex items-center gap-2 border-2 border-blue-700 text-blue-700 py-3.5 px-4 rounded-xl font-bold hover:bg-blue-50">سبد</a>
</form>
</div>
</div>
</div>
}