Files
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

144 lines
7.4 KiB
Plaintext

@page "/blog/{slug}"
@model AsadiTools.Pages.Blog.BlogPostModel
@{ Layout = "_Layout"; var p = Model.Post!; var c = SiteData.Company; }
@section Head {
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@type": "BlogPosting",
"headline": "@p.Title.Replace("\"","'")",
"description": "@((p.MetaDescription ?? p.Excerpt ?? "").Replace("\"","'"))",
"image": "@(p.FeaturedImage ?? "")",
"datePublished": "@(p.PublishedAt?.ToString("yyyy-MM-dd") ?? p.CreatedAt.ToString("yyyy-MM-dd"))",
"dateModified": "@p.UpdatedAt.ToString("yyyy-MM-dd")",
"author": { "@@type": "Organization", "name": "آساد ابزار کرج" },
"publisher": { "@@type": "Organization", "name": "آساد ابزار کرج", "logo": { "@@type": "ImageObject", "url": "" } },
"mainEntityOfPage": { "@@type": "WebPage", "@@id": "/blog/@p.EffectiveSlug" }
}
</script>
}
<div class="max-w-6xl mx-auto px-4 py-10">
<div class="grid lg:grid-cols-3 gap-10">
<!-- ── Article ──────────────────────────────────────────────────── -->
<article class="lg:col-span-2">
<!-- Breadcrumb -->
<nav class="flex items-center gap-2 text-sm text-gray-400 mb-6">
<a href="/" class="hover:text-blue-600">خانه</a><span>/</span>
<a href="/blog" class="hover:text-blue-600">بلاگ</a><span>/</span>
<span class="text-gray-700 line-clamp-1">@p.Title</span>
</nav>
<!-- Tags -->
@if (p.TagList.Any())
{
<div class="flex flex-wrap gap-1.5 mb-4">
@foreach (var tag in p.TagList)
{
<a href="/blog?tag=@Uri.EscapeDataString(tag)"
class="text-xs bg-blue-50 text-blue-600 px-2.5 py-1 rounded-full hover:bg-blue-100 transition-colors">@tag</a>
}
</div>
}
<h1 class="text-3xl font-extrabold text-gray-900 leading-tight mb-4">@p.Title</h1>
<div class="flex items-center gap-4 text-sm text-gray-400 mb-8 pb-8 border-b">
<span>📅 @p.DisplayDate</span>
<span>✍️ آساد ابزار کرج</span>
</div>
@if (!string.IsNullOrEmpty(p.FeaturedImage))
{
<div class="rounded-2xl overflow-hidden mb-8" style="max-height:420px">
<img src="@p.FeaturedImage" alt="@p.Title" class="w-full h-full object-cover" loading="eager" />
</div>
}
<!-- Content -->
<div class="prose prose-lg max-w-none text-gray-700 leading-8
[&_h2]:text-2xl [&_h2]:font-extrabold [&_h2]:text-gray-900 [&_h2]:mt-10 [&_h2]:mb-4 [&_h2]:pb-2 [&_h2]:border-b
[&_h3]:text-xl [&_h3]:font-bold [&_h3]:text-gray-800 [&_h3]:mt-6 [&_h3]:mb-3
[&_p]:mb-4 [&_p]:leading-8
[&_ul]:mb-4 [&_ul]:space-y-2 [&_ul]:list-disc [&_ul]:pr-6
[&_ol]:mb-4 [&_ol]:space-y-2 [&_ol]:list-decimal [&_ol]:pr-6
[&_li]:leading-7
[&_blockquote]:border-r-4 [&_blockquote]:border-blue-400 [&_blockquote]:pr-4 [&_blockquote]:italic [&_blockquote]:text-gray-600 [&_blockquote]:my-6
[&_strong]:font-bold [&_strong]:text-gray-900
[&_table]:w-full [&_table]:border-collapse [&_table]:my-6
[&_th]:bg-gray-100 [&_th]:p-3 [&_th]:text-right [&_th]:font-bold [&_th]:border [&_th]:border-gray-200
[&_td]:p-3 [&_td]:border [&_td]:border-gray-200 [&_td]:text-right">
@Html.Raw(p.Content)
</div>
<!-- Related -->
@if (Model.RelatedPosts.Any())
{
<div class="mt-12 pt-8 border-t">
<h2 class="text-xl font-bold text-gray-900 mb-5">مقالات مرتبط</h2>
<div class="grid sm:grid-cols-3 gap-4">
@foreach (var rp in Model.RelatedPosts)
{
<a href="/blog/@rp.EffectiveSlug"
class="group bg-white rounded-xl border border-gray-100 overflow-hidden hover:shadow-md transition-shadow">
@if (!string.IsNullOrEmpty(rp.FeaturedImage))
{
<div style="height:120px" class="overflow-hidden">
<img src="@rp.FeaturedImage" alt="@rp.Title" loading="lazy"
class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" />
</div>
}
<div class="p-3">
<p class="text-sm font-medium text-gray-800 leading-snug line-clamp-2 group-hover:text-blue-700">@rp.Title</p>
<p class="text-xs text-gray-400 mt-1">@rp.DisplayDate</p>
</div>
</a>
}
</div>
</div>
}
</article>
<!-- ── Sidebar ───────────────────────────────────────────────────── -->
<aside class="space-y-5 lg:sticky lg:top-24 lg:self-start">
<!-- CTA -->
<div class="bg-blue-700 text-white rounded-2xl p-6 text-center">
<div class="text-3xl mb-2">🔧</div>
<h3 class="font-extrabold mb-2">تعمیر ابزار در کرج</h3>
<p class="text-blue-200 text-sm mb-5">تشخیص رایگان • ضمانت ۳ ماهه</p>
<a href="tel:@c.TelPhone"
class="block bg-white text-blue-700 font-bold py-3 rounded-xl hover:opacity-90 mb-3 transition-opacity">
📞 @c.Phone
</a>
<a href="https://wa.me/@c.Whatsapp" target="_blank"
class="block bg-green-500 text-white font-bold py-3 rounded-xl hover:bg-green-600 transition-colors">
💬 واتساپ
</a>
</div>
<!-- Tags cloud -->
@if (p.TagList.Any())
{
<div class="bg-white rounded-2xl border border-gray-100 p-5">
<h3 class="font-bold text-gray-900 mb-3 text-sm">برچسب‌ها</h3>
<div class="flex flex-wrap gap-2">
@foreach (var tag in p.TagList)
{
<a href="/blog?tag=@Uri.EscapeDataString(tag)"
class="text-xs bg-gray-100 text-gray-600 px-2.5 py-1 rounded-full hover:bg-blue-100 hover:text-blue-700 transition-colors">@tag</a>
}
</div>
</div>
}
<a href="/blog" class="block bg-gray-50 border border-gray-200 rounded-2xl p-5 hover:shadow-md transition-shadow text-center">
<span class="text-xl block mb-1">📖</span>
<span class="font-bold text-gray-800 text-sm">مشاهده همه مقالات</span>
</a>
</aside>
</div>
</div>