Initial commit — AsadiTools v1.0
CI/CD / CI — dotnet build (push) Successful in 44s
CI/CD / Deploy — docker compose (push) Failing after 1s

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>
This commit is contained in:
Soroush Asadi
2026-06-01 22:08:43 +03:30
commit f97f891d67
146 changed files with 88128 additions and 0 deletions
+333
View File
@@ -0,0 +1,333 @@
@page "/brands/{brand}"
@model AsadiTools.Pages.Brands.BrandDetailModel
@{ Layout = "_Layout"; var b = Model.Brand!; var c = SiteData.Company; }
@section Head {
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@graph": [
{
"@@type": "LocalBusiness",
"name": "آساد ابزار کرج",
"telephone": "+98@c.TelPhone.Substring(1)",
"address": { "@@type": "PostalAddress", "addressLocality": "کرج", "addressRegion": "البرز", "addressCountry": "IR" },
"openingHours": "Mo-Sa 08:00-18:00",
"priceRange": "$$"
},
{
"@@type": "Service",
"name": "تعمیر ابزار @b.NameFa در کرج",
"provider": { "@@type": "LocalBusiness", "name": "آساد ابزار کرج" },
"areaServed": { "@@type": "City", "name": "کرج" },
"description": "@ViewData["Description"]",
"offers": { "@@type": "Offer", "availability": "https://schema.org/InStock" }
},
{
"@@type": "FAQPage",
"mainEntity": [
@for (int i = 0; i < b.Faqs.Length; i++) {
var faq = b.Faqs[i];
<text>{ "@@type": "Question", "name": "@faq.Q.Replace("\"","'")", "acceptedAnswer": { "@@type": "Answer", "text": "@faq.A.Replace("\"","'")" } }@(i < b.Faqs.Length - 1 ? "," : "")</text>
}
]
},
{
"@@type": "BreadcrumbList",
"itemListElement": [
{ "@@type": "ListItem", "position": 1, "name": "خانه", "item": "/" },
{ "@@type": "ListItem", "position": 2, "name": "برندها", "item": "/brands" },
{ "@@type": "ListItem", "position": 3, "name": "تعمیر ابزار @b.NameFa", "item": "/brands/@b.Id" }
]
}
]
}
</script>
}
<!-- ═══════════════════════ HERO ══════════════════════════════════════════ -->
<div class="relative text-white py-16 px-4 overflow-hidden" style="min-height:320px">
<div class="absolute inset-0">
<img src="@b.HeroImage" alt="تعمیر ابزار @b.NameFa در کرج" class="w-full h-full object-cover" />
<div class="absolute inset-0" style="background:linear-gradient(135deg, @b.Color+ee 0%, @b.Color+bb 50%, rgba(0,0,0,0.7) 100%)"></div>
</div>
<div class="relative max-w-6xl mx-auto">
<!-- Breadcrumb -->
<nav class="flex items-center gap-2 text-sm mb-6 opacity-80" style="color:@(b.TextColor == "#fff" ? "white" : "#374151")">
<a href="/" class="hover:opacity-100">خانه</a>
<span>/</span>
<a href="/brands" class="hover:opacity-100">برندها</a>
<span>/</span>
<span class="opacity-100 font-medium">@b.NameFa</span>
</nav>
<div class="flex flex-col sm:flex-row items-start sm:items-center gap-6">
<div class="w-24 h-24 rounded-2xl flex items-center justify-center text-2xl font-extrabold border-2 border-white/40 bg-white/20 backdrop-blur shrink-0 shadow-xl"
style="color:@b.TextColor">
@b.Name.Substring(0, Math.Min(3, b.Name.Length))
</div>
<div>
<div class="flex flex-wrap items-center gap-3 mb-3">
<h1 class="text-4xl font-extrabold" style="color:@(b.TextColor == "#fff" ? "white" : "#111827")">
تعمیر ابزار @b.NameFa در کرج
</h1>
@if (b.IsOfficial)
{
<span class="bg-yellow-400 text-gray-900 text-sm font-bold px-3 py-1 rounded-full shadow-lg">🛡️ نمایندگی رسمی</span>
}
</div>
<p class="text-lg max-w-2xl leading-7 opacity-90" style="color:@(b.TextColor == "#fff" ? "#e5e7eb" : "#374151")">
@b.Tagline
</p>
<div class="flex flex-wrap gap-2 mt-4 text-sm opacity-80" style="color:@(b.TextColor == "#fff" ? "#d1d5db" : "#6b7280")">
<span>📍 تأسیس @b.Founded</span>
<span>·</span>
<span>🌍 @b.Country</span>
@if (b.IsOfficial) { <span>·</span> <span class="text-yellow-300 font-bold">✅ نمایندگی رسمی در کرج</span> }
</div>
</div>
</div>
</div>
</div>
<!-- ═══════════════════════ MAIN GRID ═════════════════════════════════════ -->
<div class="max-w-6xl mx-auto px-4 py-12 grid lg:grid-cols-3 gap-10">
<!-- ══ LEFT / MAIN ════════════════════════════════════════════════════ -->
<div class="lg:col-span-2 space-y-12">
@if (b.IsOfficial) {
<!-- Official badge -->
<div class="bg-yellow-50 border-2 border-yellow-300 rounded-2xl p-6">
<div class="flex items-start gap-4">
<div class="w-12 h-12 bg-yellow-400 rounded-xl flex items-center justify-center text-2xl shrink-0">🛡️</div>
<div>
<h2 class="text-xl font-extrabold text-gray-900 mb-2">نمایندگی رسمی مجاز @b.NameFa در کرج</h2>
<p class="text-gray-600 leading-7">آساد ابزار تنها نمایندگی رسمی و مجاز برند @b.NameFa در شهر کرج و استان البرز است. تمام تعمیرات توسط تکنیسین‌های آموزش‌دیده رسمی و با قطعات کاملاً اورجینال @b.NameFa انجام می‌شود. هر تعمیر دارای ضمانت‌نامه کتبی ۳ ماهه است.</p>
</div>
</div>
</div>
}
<!-- About brand -->
<section>
<h2 class="text-2xl font-extrabold text-gray-900 mb-6 pb-3 border-b-2 flex items-center gap-3" style="border-color:@b.Color">
<span class="w-8 h-8 rounded-lg flex items-center justify-center text-sm font-bold text-white" style="background:@b.Color">@b.Name[0]</span>
درباره برند @b.NameFa
</h2>
<div class="prose prose-lg max-w-none space-y-4 text-gray-600 leading-8">
<p>@b.About1</p>
<p>@b.About2</p>
<p>@b.About3</p>
</div>
</section>
<!-- Popular models -->
<section>
<h2 class="text-2xl font-extrabold text-gray-900 mb-6 pb-3 border-b-2" style="border-color:@b.Color">
مدل‌های محبوب @b.NameFa در ایران
</h2>
<div class="grid sm:grid-cols-2 gap-4">
@foreach (var m in b.Models)
{
<div class="bg-white rounded-2xl border border-gray-100 p-5 hover:shadow-md transition-shadow hover:border-gray-200">
<div class="flex items-center justify-between mb-2">
<span class="font-mono text-sm font-bold text-gray-800">@m.Model</span>
<span class="text-xs font-bold px-2 py-0.5 rounded-full text-white" style="background:@b.Color">@m.Watts</span>
</div>
<div class="font-semibold text-gray-900 mb-1">@m.NameFa</div>
<p class="text-sm text-gray-500 leading-6">@m.Desc</p>
</div>
}
</div>
</section>
<!-- Repair services -->
<section>
<h2 class="text-2xl font-extrabold text-gray-900 mb-6 pb-3 border-b-2" style="border-color:@b.Color">
خدمات تعمیر @b.NameFa در آساد ابزار
</h2>
<div class="grid sm:grid-cols-2 gap-3">
@foreach (var svc in b.RepairServices)
{
<div class="flex items-start gap-3 bg-white rounded-xl border border-gray-100 p-4 hover:border-gray-200 transition-colors">
<span class="w-6 h-6 rounded-full flex items-center justify-center text-white text-xs font-bold shrink-0 mt-0.5" style="background:@b.Color">✓</span>
<span class="text-sm text-gray-700 leading-6">@svc</span>
</div>
}
</div>
</section>
<!-- Common problems -->
<section>
<h2 class="text-2xl font-extrabold text-gray-900 mb-6 pb-3 border-b-2" style="border-color:@b.Color">
مشکلات رایج ابزار @b.NameFa و راه‌حل
</h2>
<div class="space-y-4">
@foreach (var prob in b.CommonProblems)
{
<div class="bg-white rounded-2xl border border-gray-100 p-6">
<h3 class="font-bold text-gray-900 mb-3 flex items-center gap-2">
<span class="w-6 h-6 rounded-full bg-red-100 text-red-600 flex items-center justify-center text-xs shrink-0">!</span>
@prob.Problem
</h3>
<div class="grid sm:grid-cols-2 gap-4 text-sm">
<div class="bg-red-50 rounded-xl p-3">
<div class="text-xs font-bold text-red-700 mb-1">علت احتمالی:</div>
<div class="text-gray-600 leading-6">@prob.Cause</div>
</div>
<div class="bg-green-50 rounded-xl p-3">
<div class="text-xs font-bold text-green-700 mb-1">راه‌حل:</div>
<div class="text-gray-600 leading-6">@prob.Solution</div>
</div>
</div>
</div>
}
</div>
</section>
<!-- Repair process -->
<section>
<h2 class="text-2xl font-extrabold text-gray-900 mb-6 pb-3 border-b-2" style="border-color:@b.Color">
فرآیند تعمیر ابزار @b.NameFa
</h2>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
@{ var steps = new[] { ("۱","تحویل ابزار","حضوری یا از طریق پست"), ("۲","بررسی رایگان","تشخیص دقیق عیب"), ("۳","تعمیر تخصصی","قطعه اصل + ضمانت"), ("۴","تحویل با گارانتی","ضمانت‌نامه کتبی ۳ ماهه") }; }
@foreach (var step in steps)
{
<div class="text-center p-5 bg-gray-50 rounded-2xl border border-gray-100 hover:bg-white hover:shadow-sm transition-all">
<div class="w-11 h-11 rounded-full flex items-center justify-center text-lg font-extrabold mx-auto mb-3 shadow"
style="background:@b.Color;color:@b.TextColor">@step.Item1</div>
<div class="font-bold text-gray-800 text-sm mb-1">@step.Item2</div>
<div class="text-xs text-gray-400">@step.Item3</div>
</div>
}
</div>
</section>
<!-- FAQ -->
<section>
<h2 class="text-2xl font-extrabold text-gray-900 mb-6 pb-3 border-b-2" style="border-color:@b.Color">
سوالات متداول درباره تعمیر ابزار @b.NameFa
</h2>
<div class="space-y-3" id="faq-list">
@for (int i = 0; i < b.Faqs.Length; i++)
{
var faq = b.Faqs[i];
<details class="bg-white rounded-2xl border border-gray-100 overflow-hidden group" @(i == 0 ? "open" : "")>
<summary class="flex items-center justify-between p-5 cursor-pointer font-bold text-gray-900 hover:bg-gray-50 select-none list-none">
<span>@faq.Q</span>
<span class="text-gray-400 group-open:rotate-180 transition-transform shrink-0 mr-3">▾</span>
</summary>
<div class="px-5 pb-5 text-gray-600 leading-8 text-sm border-t border-gray-50 pt-4">@faq.A</div>
</details>
}
</div>
</section>
</div>
<!-- ══ SIDEBAR ══════════════════════════════════════════════════════ -->
<div class="space-y-5 lg:sticky lg:top-24 lg:self-start">
<!-- CTA card -->
<div class="rounded-2xl p-6 text-center shadow-lg" style="background:@b.Color">
<div class="text-2xl mb-2">🔧</div>
<h3 class="font-extrabold text-lg mb-1" style="color:@(b.TextColor == "#fff" ? "white" : "#111827")">
درخواست تعمیر @b.NameFa
</h3>
<p class="text-sm mb-5 opacity-80" style="color:@(b.TextColor == "#fff" ? "#e5e7eb" : "#374151")">
مشاوره رایگان – تشخیص رایگان
</p>
<a href="tel:@c.TelPhone"
class="block bg-white font-bold text-center py-3 rounded-xl hover:opacity-90 mb-3 transition-opacity shadow"
style="color:@b.Color">
📞 @c.Phone
</a>
<a href="https://wa.me/@c.Whatsapp" target="_blank"
class="block bg-green-500 text-white font-bold text-center py-3 rounded-xl hover:bg-green-600 transition-colors">
💬 پیام واتساپ
</a>
</div>
<!-- Guarantees -->
<div class="bg-white rounded-2xl border border-gray-100 p-6">
<h3 class="font-bold text-gray-900 mb-4 flex items-center gap-2">
<span class="w-6 h-6 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center text-xs">⭐</span>
مزایای تعمیر در آساد ابزار
</h3>
<ul class="space-y-3 text-sm text-gray-600">
@foreach (var item in new[] {
"تشخیص عیب رایگان بدون پیش‌پرداخت",
"قطعات ۱۰۰٪ اورجینال تأییدشده",
"ضمانت‌نامه کتبی ۳ ماهه",
"تکنیسین مجاز و متخصص",
"قیمت شفاف پیش از شروع",
"تحویل سریع زیر ۴۸ ساعت",
"ارسال از سراسر کشور"
})
{
<li class="flex items-center gap-2">
<span class="text-green-500 shrink-0">✓</span> @item
</li>
}
</ul>
</div>
<!-- Parts shop link -->
<a href="/Shop?brand=@b.Id"
class="block bg-gray-50 border border-gray-200 rounded-2xl p-5 hover:shadow-md hover:bg-white transition-all">
<div class="flex items-center gap-3">
<span class="text-2xl">🛒</span>
<div>
<h3 class="font-bold text-gray-900 text-sm">قطعات یدکی @b.NameFa</h3>
<p class="text-xs text-gray-400 mt-0.5">خرید آنلاین از فروشگاه ما</p>
</div>
</div>
</a>
<!-- Other brands -->
<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 ob in BrandSeoData.AllBrands.Where(x => x.Id != b.Id))
{
<a href="/brands/@ob.Id"
class="text-xs px-3 py-1.5 rounded-full border border-gray-200 text-gray-600 hover:text-white transition-all hover:border-transparent"
style="--hover-bg:@ob.Color"
onmouseover="this.style.background='@ob.Color';this.style.borderColor='@ob.Color'"
onmouseout="this.style.background='';this.style.borderColor=''">
@ob.NameFa
</a>
}
</div>
</div>
</div>
</div>
<!-- ══════════════════════ BOTTOM CTA ════════════════════════════════════ -->
<section class="py-14 px-4" style="background:@b.Color">
<div class="max-w-3xl mx-auto text-center">
<h2 class="text-2xl font-extrabold mb-3" style="color:@(b.TextColor == "#fff" ? "white" : "#111827")">
ابزار @b.NameFa شما خراب شده؟
</h2>
<p class="mb-8 text-lg opacity-85" style="color:@(b.TextColor == "#fff" ? "#e5e7eb" : "#374151")">
همین الان تماس بگیرید. تشخیص رایگان، تعمیر با ضمانت کتبی ۳ ماهه.
</p>
<div class="flex flex-wrap justify-center gap-4">
<a href="tel:@c.TelPhone"
class="bg-white font-bold px-8 py-3.5 rounded-xl hover:opacity-90 transition-opacity text-lg shadow-lg"
style="color:@b.Color">
📞 @c.Phone
</a>
<a href="https://wa.me/@c.Whatsapp" target="_blank"
class="bg-green-600 text-white font-bold px-8 py-3.5 rounded-xl hover:bg-green-700 transition-colors text-lg shadow-lg">
💬 واتساپ
</a>
<a href="/Shop?brand=@b.Id"
class="bg-white/20 border border-white/50 font-bold px-8 py-3.5 rounded-xl hover:bg-white/30 transition-colors text-lg"
style="color:@(b.TextColor == "#fff" ? "white" : "#111827")">
🛒 قطعات یدکی
</a>
</div>
</div>
</section>