# 📋 تاریخچه تغییرات FrontOffice — کارا بازار سلامت > **آخرین بروزرسانی**: بهمن ۱۴۰۴ (فوریه ۲۰۲۶) > **فریمورک**: Blazor Server + MudBlazor 8.14 + .NET 9 --- ## 🔖 نسخه ۲.۶.۰ — بهمن ۱۴۰۴ (February 16, 2026) ### ۱. درگاه پرداخت زرین‌پال - **یکپارچه‌سازی ZarinPal** — پرداخت مستقیم بدون PYMS واسط - صفحه checkout فروشگاه تخفیفی: ریدایرکت به ZarinPal → callback → تأیید - صفحه checkout فروشگاه عادی: همان جریان - پشتیبانی از sandbox و production ### ۲. جدول PaymentTransaction - **Entity جدید** `PaymentTransaction` — ذخیره جزئیات سطح درگاه (Authority, CardPan, CardHash, RefId) - جدا از جدول Transaction اصلی - Migration: `AddPaymentTransactionTable` ### ۳. فیکس نمایش وضعیت پرداخت - **مشکل:** سفارشات تخفیفی «در انتظار پرداخت» نشان می‌دادند حتی بعد از پرداخت موفق - **علت:** Mapster نمی‌تونست `PaymentStatus` (enum) رو به `payment_completed` (bool) مپ کنه - **رفع:** مپینگ دستی در `DiscountOrderService` ### ۴. فیکس DeliveryStatus - **مشکل:** فروشگاه تخفیفی بعد از پرداخت `InTransit` ست می‌کرد - **رفع:** تغییر به `Pending` — ادمین باید وضعیت پست رو مشخص کنه ### ۵. تغییر به NuGet Package (Docker build fix) - `ProjectReference` به CMS Protobuf → `PackageReference` (v0.0.178) - Docker build context فقط `src/` داره → مسیر `../../../CMS` قابل دسترسی نیست --- ## 🔖 نسخه ۲.۵.۰ — بهمن ۱۴۰۴ ### ۱. محافظت صفحات نیازمند احراز هویت (Auth Guard) **فایل‌های تغییریافته:** - `Shared/MainLayout.razor.cs` **شرح:** قبلاً هیچ محافظتی در سطح مسیریابی وجود نداشت — کاربر غیرلاگین می‌توانست مستقیماً به `/profile/*`، `/commission/*`، `/cart` و... دسترسی پیدا کند. **تغییرات:** - متد `EnforceAuthGuardAsync()` اضافه شد — در هر تغییر مسیر و اولین بار رندر اجرا می‌شود - متد `IsProtectedRoute(path)` مسیرهای محافظت‌شده را تشخیص می‌دهد - کاربر غیرلاگین → ریدایرکت به `/` (صفحه اصلی) **مسیرهای محافظت‌شده:** | گروه | مسیرها | |---|---| | پروفایل | `/profile/*` | | کمیسیون | `/commission/*` | | شبکه | `/network/*` | | باشگاه | `/club/*` | | سبد خرید | `/cart`, `/checkout*`, `/orders`, `/order/*`, `/order-tracking/*` | | پکیج‌ها | `/my-packages` | | دروازه | `/my-orders`, `/my-cart` | | فروشگاه تخفیفی | `/discount-store/cart`, `/discount-store/checkout`, `/discount-store/orders`, `/discount-store/order/*` | **مسیرهای عمومی:** `/`, `/register`, `/about`, `/faq`, `/contact`, `/blog/*`, `/packages`, `/package/*`, `/products`, `/product/*`, `/categories`, `/stores`, `/discount-store`, `/discount-store/product/*` --- ### ۲. استخراج کامپوننت PhoneVerifyForm **فایل‌های جدید:** - `Shared/PhoneVerifyForm.razor` - `Shared/PhoneVerifyForm.razor.cs` **فایل‌های تغییریافته:** - `Shared/AuthDialog.razor` - `Shared/AuthDialog.razor.cs` **شرح:** فرم تلفن + تایید OTP + کپچا که قبلاً به‌صورت `RenderFragment` با `__builder` مستقیم در `AuthDialog` نوشته شده بود، به کامپوننت مستقل `PhoneVerifyForm` استخراج شد. **ساختار قبل:** ``` AuthDialog.razor └── @code { PhoneOrVerifyContent() => __builder => { ... } } ← RenderFragment پیچیده ``` **ساختار بعد:** ``` AuthDialog.razor └── ← کامپوننت مستقل PhoneVerifyForm.razor ← مارکاپ فرم PhoneVerifyForm.razor.cs ← پارامترها و فرم رف‌ها ``` **پارامترهای PhoneVerifyForm:** | پارامتر | نوع | توضیح | |---|---|---| | `CurrentStep` | `AuthStep` | مرحله فعلی (Phone / Verify) | | `PhoneRequest` | `CreateNewOtpTokenRequest` | مدل فرم تلفن | | `VerifyRequest` | `VerifyOtpTokenRequest` | مدل فرم تایید | | `CaptchaCode` | `string?` | کد کپچا نمایش‌داده‌شده | | `CaptchaInput` / `CaptchaInputChanged` | `string?` + `EventCallback` | ورودی کپچا (two-way) | | `OnRefreshCaptcha` | `EventCallback` | رفرش کپچا | | `IsBusy` | `bool` | وضعیت بارگذاری | | `ErrorMessage` / `InfoMessage` | `string?` | پیام‌های خطا/اطلاع | | `PhoneNumber` | `string?` | شماره تایید‌شده | | `ResendRemaining` | `int` | ثانیه تا ارسال مجدد | | `OnChangePhone` / `OnResendOtp` | `EventCallback` | اکشن‌های تایید | **نکته مهم — Two-way binding کپچا:** فیلد کپچا با `Value` + `ValueChanged` بایند شده (نه `@bind-Value`) تا مقدار تایپ‌شده از فرزند به والد برگردد: ```razor ``` **دسترسی به فرم‌ها از والد:** ```csharp // AuthDialog.razor.cs var phoneForm = _phoneVerifyForm?.GetPhoneForm(); var verifyForm = _phoneVerifyForm?.GetVerifyForm(); ``` --- ### ۳. بهبود لایوت مدال ورود (AuthDialog) **فایل‌های تغییریافته:** - `Shared/AuthDialog.razor` - `Utilities/AuthDialogService.cs` - `wwwroot/css/site.css` **مشکلات قبلی:** - دیالوگ روی موبایل `FullScreen` بود → فضای خالی بزرگ بین فرم و دکمه‌ها - `TitleContent` و `DialogActions` جدا → گپ عمودی - ردیف کپچا با `MudStack Row="true"` → آیتم‌ها عمودی رندر می‌شدند **تغییرات:** 1. **حذف FullScreen**: `AuthDialogService` حالا همیشه `MaxWidth.ExtraSmall, FullWidth=true, CloseButton=true` 2. **ادغام محتوا**: آواتار + عنوان + فرم + دکمه‌ها همه داخل `DialogContent` → بدون `TitleContent` و `DialogActions` 3. **کلاس `auth-dialog-wrapper`**: CSS با `.auth-dialog-wrapper .mud-dialog-title { display: none; }` عنوان پیش‌فرض دیالوگ رو مخفی می‌کنه 4. **ردیف کپچا**: از `MudStack Row` به `div.captcha-row` با CSS flex اختصاصی 5. **حالت Inline**: بدون تغییر ساختاری — فقط از `PhoneVerifyForm` استفاده می‌کنه **CSS جدید:** ```css .auth-dialog-wrapper .mud-dialog-title { display: none; } .auth-dialog-wrapper .mud-dialog-content { padding-bottom: 24px !important; } .auth-dialog-content { max-width: 400px; margin: 0 auto; } .captcha-row { display: flex; align-items: center; gap: 10px; } .captcha-row > .mud-input-control { flex: 1 1 0; min-width: 0; } .captcha-row > .mud-paper { flex: 0 0 auto; } .captcha-row > .mud-button-root { flex: 0 0 auto; } ``` --- ### ۴. صفحه لندینگ — حذف /pricing و اضافه بنر بلاگ **فایل‌های تغییریافته:** - `Pages/Index.razor` - `wwwroot/css/site.css` **تغییرات:** 1. دکمه هیرو «مشاهده پکیج‌ها» → **«آخرین اخبار»** با لینک `/blog` 2. **بنر جدیدترین مطلب** بین هیرو و «سه گام تا شروع» اضافه شد - تصویر بندانگشتی + عنوان + خلاصه + آیکون شیشه‌ای - هاور: `translateY(-2px)` + سایه بزرگ‌تر **CSS جدید:** ```css .landing-blog-banner { border: 1px solid var(--mud-palette-divider); transition: ... } .landing-blog-banner:hover { box-shadow: var(--mud-elevation-4); transform: translateY(-2px); } .landing-blog-thumb { width: 80px; height: 80px; border-radius: 12px; } .landing-blog-title { -webkit-line-clamp: 1; font-weight: 600; } .landing-blog-summary { -webkit-line-clamp: 1; } ``` --- ### ۵. افزایش ارتفاع تکست‌باکس‌ها (Global) **فایل تغییریافته:** - `wwwroot/css/site.css` **قبل:** `padding: 10px 14px` **بعد:** `padding: 14px 14px` + `font-size: 1rem` ```css .mud-input-outlined .mud-input-slot { padding: 14px 14px !important; font-size: 1rem; } ``` تمام فیلدهای Outlined در کل اپلیکیشن بزرگ‌تر شدند. --- ### ۶. اصلاح RTL فیلدهای ورودی **فایل تغییریافته:** - `wwwroot/css/site.css` **مشکل:** فیلدهای `type="tel"` به‌صورت پیش‌فرض مرورگر `direction: ltr` می‌گیرن — لیبل سمت راست ولی placeholder/cursor سمت چپ. **اصلاح:** ```css .mud-input-slot input, .mud-input-slot textarea { direction: rtl !important; text-align: right !important; } ``` --- ### ۷. اصلاح captcha-box CSS **فایل تغییریافته:** - `wwwroot/css/site.css` **قبل:** ```css .captcha-box { min-width: 120px; min-height: 56px; background: linear-gradient(135deg, rgba(123,97,255,.12), rgba(255,140,189,.12)); } ``` **بعد:** ```css .captcha-box { min-width: 96px; min-height: 48px; border-radius: var(--mud-default-borderradius); background: rgba(99,102,241,.08); border: 1px solid var(--mud-palette-divider); } ``` --- ## 📁 نقشه فایل‌ها ``` Shared/ ├── AuthDialog.razor ← بازنویسی (کامپوننت PhoneVerifyForm جایگزین RenderFragment) ├── AuthDialog.razor.cs ← بروزرسانی (استفاده از _phoneVerifyForm) ├── PhoneVerifyForm.razor ← ✨ جدید (فرم تلفن + تایید + کپچا) ├── PhoneVerifyForm.razor.cs ← ✨ جدید (پارامترها و فرم رف‌ها) ├── MainLayout.razor.cs ← Auth Guard اضافه شد Pages/ ├── Index.razor ← /pricing → /blog + بنر بلاگ Utilities/ ├── AuthDialogService.cs ← حذف FullScreen، ثابت‌سازی سایز wwwroot/css/ ├── site.css ← captcha-row, auth-dialog, RTL fix, input height ``` --- ## 🔍 وضعیت بیلد | تاریخ | خطا | هشدار | توضیح | |---|---|---|---| | بهمن ۱۴۰۴ | **۰** | ۱۰۵ | MUD0002 warnings (بی‌خطر — مربوط به MudBlazor analyzer) |