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
+59
View File
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] | پنل مدیریت آساد ابزار</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
@@font-face { font-family:"Vazirmatn"; src:url("https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@@v33.003/fonts/webfonts/Vazirmatn-Regular.woff2") format("woff2"); font-weight:400; font-display:swap; }
@@font-face { font-family:"Vazirmatn"; src:url("https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@@v33.003/fonts/webfonts/Vazirmatn-Bold.woff2") format("woff2"); font-weight:700; font-display:swap; }
*, body { font-family: "Vazirmatn", Tahoma, Arial, sans-serif !important; }
</style>
</head>
<body class="bg-gray-50 text-gray-800">
<div class="flex min-h-screen">
<!-- Sidebar -->
<aside class="fixed right-0 top-0 h-full w-56 bg-gray-900 text-white flex flex-col z-40">
<div class="p-5 border-b border-gray-800">
<div class="flex items-center gap-2">
<div class="bg-blue-600 rounded-lg p-1.5 text-sm">🔧</div>
<div>
<div class="font-bold text-sm">آساد ابزار</div>
<div class="text-xs text-gray-400">پنل مدیریت</div>
</div>
</div>
</div>
<nav class="flex-1 p-4 space-y-1">
<a href="/Admin" class="flex items-center gap-3 px-4 py-2.5 rounded-xl text-sm font-medium text-gray-300 hover:bg-gray-800 hover:text-white transition-colors">
📊 داشبورد
</a>
<a href="/Admin/Products" class="flex items-center gap-3 px-4 py-2.5 rounded-xl text-sm font-medium text-gray-300 hover:bg-gray-800 hover:text-white transition-colors">
📦 محصولات
</a>
<a href="/Admin/Orders" class="flex items-center gap-3 px-4 py-2.5 rounded-xl text-sm font-medium text-gray-300 hover:bg-gray-800 hover:text-white transition-colors">
🛍️ سفارش‌ها
</a>
<a href="/Admin/Blog" class="flex items-center gap-3 px-4 py-2.5 rounded-xl text-sm font-medium text-gray-300 hover:bg-gray-800 hover:text-white transition-colors">
📝 بلاگ
</a>
<a href="/Admin/ChangePassword" class="flex items-center gap-3 px-4 py-2.5 rounded-xl text-sm font-medium text-gray-300 hover:bg-gray-800 hover:text-white transition-colors">
🔑 تغییر رمز عبور
</a>
</nav>
<div class="p-4 border-t border-gray-800">
<form method="post" action="/Admin/Logout">
@Html.AntiForgeryToken()
<button type="submit" class="text-sm text-red-400 hover:text-red-300 transition-colors">🚪 خروج</button>
</form>
</div>
</aside>
<!-- Main -->
<main class="flex-1 mr-56 overflow-auto">
@RenderBody()
</main>
</div>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
+111
View File
@@ -0,0 +1,111 @@
@inject AsadiTools.Services.CartService Cart
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@(ViewData["Title"] != null ? ViewData["Title"] + " | آساد ابزار کرج" : "آساد ابزار - نمایندگی رسمی دیوالت در کرج")</title>
<meta name="description" content="@(ViewData["Description"] ?? "نمایندگی رسمی دیوالت، ماکیتا، رونیکس، توسن و بلک اند دکر در کرج. تعمیر دریل، فرز، مینی فرز، شمشاد زن و بتن کن.")" />
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<script src="https://cdn.tailwindcss.com"></script>
<style>
@@font-face { font-family:"Vazirmatn"; src:url("https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@@v33.003/fonts/webfonts/Vazirmatn-Regular.woff2") format("woff2"); font-weight:400; font-display:swap; }
@@font-face { font-family:"Vazirmatn"; src:url("https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@@v33.003/fonts/webfonts/Vazirmatn-Bold.woff2") format("woff2"); font-weight:700; font-display:swap; }
@@font-face { font-family:"Vazirmatn"; src:url("https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@@v33.003/fonts/webfonts/Vazirmatn-ExtraBold.woff2") format("woff2"); font-weight:800; font-display:swap; }
*, body { font-family: "Vazirmatn", Tahoma, Arial, sans-serif !important; }
::-webkit-scrollbar { width:5px } ::-webkit-scrollbar-thumb { background:#94a3b8; border-radius:3px }
</style>
@await RenderSectionAsync("Head", required: false)
</head>
<body class="bg-gray-50 text-gray-800 flex flex-col min-h-screen">
<!-- Top bar -->
<div class="bg-blue-800 text-white text-sm py-1.5 px-4">
<div class="max-w-6xl mx-auto flex justify-between items-center">
<a href="tel:@SiteData.Company.TelPhone" class="hover:text-yellow-300 transition-colors">📞 @SiteData.Company.Phone</a>
<span class="text-yellow-300 font-bold text-xs">نمایندگی رسمی دیوالت در کرج</span>
</div>
</div>
<!-- Header -->
<header class="bg-white shadow-sm sticky top-0 z-50">
<div class="max-w-6xl mx-auto px-4 py-3 flex items-center justify-between gap-4">
<a href="/" class="flex items-center gap-2 shrink-0">
<div class="bg-blue-700 text-white rounded-lg p-2 text-lg">🔧</div>
<div>
<div class="font-bold text-lg text-gray-900 leading-tight">آساد ابزار</div>
<div class="text-xs text-gray-400">کرج • تعمیر ابزار صنعتی</div>
</div>
</a>
<nav class="hidden md:flex items-center gap-5">
<a href="/" class="text-gray-600 hover:text-blue-700 font-medium transition-colors text-sm">خانه</a>
<a href="/Services" class="text-gray-600 hover:text-blue-700 font-medium transition-colors text-sm">خدمات</a>
<a href="/brands" class="text-gray-600 hover:text-blue-700 font-medium transition-colors text-sm">برندها</a>
<a href="/blog" class="text-gray-600 hover:text-blue-700 font-medium transition-colors text-sm">بلاگ</a>
<a href="/DeWalt" class="inline-flex items-center gap-1 bg-yellow-400 text-gray-900 font-bold px-3 py-1 rounded-lg text-sm hover:bg-yellow-300 transition-colors">🛡️ دیوالت</a>
<a href="/Shop" class="text-gray-600 hover:text-blue-700 font-medium transition-colors text-sm">فروشگاه قطعات</a>
<a href="/Contact" class="text-gray-600 hover:text-blue-700 font-medium transition-colors text-sm">تماس با ما</a>
</nav>
<div class="flex items-center gap-3">
<a href="/Cart" class="relative flex items-center gap-1.5 bg-blue-700 text-white px-3 py-2 rounded-lg text-sm font-medium hover:bg-blue-800 transition-colors">
🛒 <span class="hidden sm:inline">سبد خرید</span>
@if (Cart.Count > 0)
{
<span class="absolute -top-1.5 -left-1.5 bg-yellow-400 text-gray-900 text-xs font-bold rounded-full w-5 h-5 flex items-center justify-center">@Cart.Count</span>
}
</a>
<button onclick="document.getElementById('mobile-menu').classList.toggle('hidden')" class="md:hidden p-2 rounded-lg hover:bg-gray-100">☰</button>
</div>
</div>
<div id="mobile-menu" class="hidden md:hidden border-t bg-white px-4 py-3 space-y-1">
<a href="/" class="block py-2.5 px-3 rounded-lg hover:bg-blue-50 hover:text-blue-700 font-medium">خانه</a>
<a href="/Services" class="block py-2.5 px-3 rounded-lg hover:bg-blue-50 hover:text-blue-700 font-medium">خدمات</a>
<a href="/brands" class="block py-2.5 px-3 rounded-lg hover:bg-blue-50 hover:text-blue-700 font-medium">برندها</a>
<a href="/blog" class="block py-2.5 px-3 rounded-lg hover:bg-blue-50 hover:text-blue-700 font-medium">بلاگ</a>
<a href="/DeWalt" class="block py-2.5 px-3 rounded-lg bg-yellow-50 text-gray-900 font-bold">🛡️ ابزار دیوالت (رسمی)</a>
<a href="/Shop" class="block py-2.5 px-3 rounded-lg hover:bg-blue-50 hover:text-blue-700 font-medium">فروشگاه قطعات</a>
<a href="/Contact" class="block py-2.5 px-3 rounded-lg hover:bg-blue-50 hover:text-blue-700 font-medium">تماس با ما</a>
</div>
</header>
<main class="flex-1">
@RenderBody()
</main>
<!-- Footer -->
<footer class="bg-gray-900 text-gray-300 mt-auto">
<div class="max-w-6xl mx-auto px-4 py-12 grid grid-cols-1 md:grid-cols-3 gap-10">
<div>
<h3 class="text-white font-bold text-lg mb-4">آساد ابزار</h3>
<p class="text-sm leading-7 text-gray-400">با بیش از ۱۵ سال تجربه، نمایندگی رسمی دیوالت در کرج. تعمیر تخصصی ابزار صنعتی با قطعات اصل.</p>
</div>
<div>
<h3 class="text-white font-bold text-lg mb-4">تماس</h3>
<ul class="space-y-2 text-sm">
<li>📞 <a href="tel:@SiteData.Company.TelPhone" class="hover:text-white">@SiteData.Company.Phone</a></li>
<li>📱 <a href="tel:@SiteData.Company.TelMobile" class="hover:text-white">@SiteData.Company.Mobile</a></li>
<li>📍 @SiteData.Company.Address</li>
<li>🕐 @SiteData.Company.WorkingHours</li>
</ul>
</div>
<div>
<h3 class="text-white font-bold text-lg mb-4">خدمات</h3>
<ul class="space-y-2 text-sm">
<li><a href="/Services/Brand?id=dewalt" class="hover:text-white">تعمیر ابزار دیوالت <span class="text-yellow-400 text-xs">(رسمی)</span></a></li>
<li><a href="/Services/Brand?id=makita" class="hover:text-white">تعمیر ابزار ماکیتا</a></li>
<li><a href="/Services/Brand?id=ronix" class="hover:text-white">تعمیر ابزار رونیکس</a></li>
<li><a href="/Services/Brand?id=tosan" class="hover:text-white">تعمیر ابزار توسن</a></li>
<li><a href="/Shop" class="hover:text-white">فروشگاه قطعات یدکی</a></li>
</ul>
</div>
</div>
<div class="border-t border-gray-800 py-4 text-center text-xs text-gray-500">
© @DateTime.Now.Year آساد ابزار کرج – تمام حقوق محفوظ است
</div>
</footer>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
+48
View File
@@ -0,0 +1,48 @@
/* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
for details on configuring this project to bundle and minify static web assets. */
a.navbar-brand {
white-space: normal;
text-align: center;
word-break: break-all;
}
a {
color: #0077cc;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.border-top {
border-top: 1px solid #e5e5e5;
}
.border-bottom {
border-bottom: 1px solid #e5e5e5;
}
.box-shadow {
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}
button.accept-policy {
font-size: 1rem;
line-height: inherit;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
white-space: nowrap;
line-height: 60px;
}
@@ -0,0 +1,2 @@
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js"></script>