Files
docs/ui-modernization/UI-MODERNIZATION-PLAN.md
T

60 KiB
Raw Blame History

🎨 طرح نوسازی رابط کاربری فرانت‌آفیس + سیستم بلاگ

تاریخ شروع: تیر ۱۴۰۴
آخرین بروزرسانی: بهمن ۱۴۰۴
وضعیت: فازهای ۱ تا ۶ تکمیل — فاز ۷ در حال اجرا
اولویت: بالا


فهرست مطالب

  1. خلاصه اجرایی
  2. وضعیت فعلی
  3. اهداف پروژه
  4. معماری فنی
  5. فاز ۱ — موجودیت‌های بکند (CMS)
  6. فاز ۲ — پنل مدیریت بلاگ (BackOffice)
  7. فاز ۳ — صفحات محتوای دینامیک (درباره ما / تماس با ما)
  8. فاز ۴ — نوسازی لندینگ پیج
  9. فاز ۵ — صفحات بلاگ فرانت‌آفیس
  10. فاز ۶ — بهبود داشبورد کاربر
  11. فاز ۷ — بهینه‌سازی موبایل
  12. فایل‌های تغییریافته (نقشه فایل‌ها)
  13. جدول زمانی
  14. ریسک‌ها و وابستگی‌ها

1. خلاصه اجرایی

این سند طرح جامع نوسازی رابط کاربری فرانت‌آفیس (سمت مشتری) و ایجاد سیستم بلاگ/مدیریت محتوا را شامل می‌شود. اهداف اصلی:

  • ایجاد سیستم بلاگ با قابلیت انتشار مقالات، مجوزها، گواهینامه‌ها با تصاویر
  • صفحات دینامیک درباره ما و تماس با ما (قابل مدیریت از پنل ادمین)
  • نوسازی لندینگ پیج با طراحی حرفه‌ای و حس زنده بودن سامانه
  • صفحات بلاگ فرانت‌آفیس — لیست مقالات با جستجو/فیلتر + صفحه جزئیات مقاله
  • بهبود داشبورد کاربر با طراحی مدرن و اطلاعات پویا
  • 🔄 طراحی Mobile-First (اولویت موبایل) — فاز ۷
  • بدون تغییر UI سمت ادمین (فقط افزودن صفحات مدیریت بلاگ/محتوا)

2. وضعیت فعلی

2.1 پشته فنی

لایه تکنولوژی
FrontOffice Blazor Server (.NET 9) + MudBlazor 8.14.0
BackOffice Blazor WebAssembly (.NET 9) + MudBlazor 8.14.0
CMS (Backend) .NET 9 gRPC + MediatR CQRS + EF Core
دیتابیس SQL Server
فایل‌ها FMS (File Management Service) via gRPC
زبان UI فارسی (RTL) + فونت Vazir
تم Light/Dark toggle

2.2 صفحات فعلی فرانت‌آفیس

صفحه مسیر وضعیت
لندینگ / Hero گرادیان + Features + Timeline + Stats + بلاگ + Testimonials + FAQ + CTA
درباره ما /about محتوای دینامیک از CMS (با fallback)
تماس با ما /contact محتوای دینامیک از CMS + فرم تماس
بلاگ /blog لیست مقالات + جستجو + فیلتر دسته‌بندی + صفحه‌بندی
مقاله /blog/{slug} صفحه جزئیات مقاله + breadcrumb + تگ‌ها + شمارنده بازدید
سوالات متداول /faq فعال
پروفایل /profile/* ۱۰ صفحه (هدر گرادیانی + والت‌کارت‌ها + تایل‌های مدرن)
فروشگاه /products/* ۸ صفحه (محصولات، سبد، سفارشات، ...)
باشگاه /club/* ۲ صفحه
کمیسیون /commission/* ۳ صفحه
شبکه /network/* ۲ صفحه
پکیج /packages/* ۴ صفحه

2.3 مشکلات فعلی (رفع شده )

  1. احساس ایستا بودن — لندینگ پیج بدون انیمیشن و محتوای پویا فاز ۴ حل شد
  2. بدون بلاگ — امکان انتشار مقاله/خبر/مجوز وجود ندارد فازهای ۱، ۲، ۵ حل شد
  3. صفحات استاتیک — درباره ما و تماس با ما هاردکد هستند فاز ۳ حل شد
  4. طراحی ساده — فاقد عناصر بصری جذاب فازهای ۴ و ۶ حل شد
  5. موبایل‌محور نبودن — ریسپانسیو هست اما اولویت با دسکتاپ → 🔄 فاز ۷

3. اهداف پروژه

3.1 اهداف عملیاتی

هدف شاخص موفقیت
سیستم بلاگ ادمین بتواند مقاله بنویسد، دسته‌بندی کند، تصویر آپلود کند، منتشر/آرشیو کند
محتوای دینامیک ادمین بتواند درباره ما و تماس با ما را از پنل ویرایش کند
لندینگ حرفه‌ای اولین بازدید حس «پلتفرم زنده و فعال» بدهد
Mobile-First تمام صفحات در موبایل عالی نمایش داده شوند
عملکرد زمان بارگذاری صفحه اول < ۳ ثانیه

3.2 محدوده (Scope)

✅ در محدوده:
  - سیستم بلاگ کامل (CMS → BackOffice → FrontOffice)
  - صفحات محتوای دینامیک (About, Contact)
  - نوسازی لندینگ پیج
  - بهبود داشبورد/پروفایل
  - بهینه‌سازی موبایل
  - افزودن صفحات مدیریت بلاگ به BackOffice

⛔ خارج از محدوده:
  - تغییرات UI سایر بخش‌های BackOffice
  - سیستم کامنت‌گذاری (فاز بعدی)
  - سیستم جستجوی پیشرفته (فاز بعدی)
  - اپلیکیشن موبایل (PWA یا Native)

4. معماری فنی

4.1 جریان داده بلاگ

┌──────────────┐    gRPC     ┌───────────┐    EF Core    ┌──────────┐
│  BackOffice  │ ──────────► │    CMS    │ ────────────► │ SQL Server│
│ (Admin CRUD) │ ◄────────── │  (gRPC)   │ ◄──────────── │          │
└──────────────┘             └───────────┘               └──────────┘
                                  │ ▲
                            gRPC  │ │
                                  ▼ │
                             ┌──────────────┐
                             │ FrontOffice  │
                             │ (مشاهده بلاگ)│
                             └──────────────┘
                                  │
                             FMS  │  (آپلود تصاویر)
                                  ▼
                             ┌──────────┐
                             │   FMS    │
                             │ (فایل‌ها) │
                             └──────────┘

4.2 موجودیت‌های جدید (Entity Relationship)

BlogPost (1) ──────── (N) BlogPostCategory ──────── (1) BlogCategory
   │
   │ (1:N)
   ▼
BlogPostImage

BlogPost.Tags → از Tag موجود استفاده می‌شود (BlogPostTag join table)

SitePage → صفحات دینامیک (About, Contact, Custom)
   │
   │ (1:N)
   ▼
SitePageSection → بخش‌های هر صفحه

4.3 الگوی CQRS موجود (برای مرجع)

Proto (gRPC Definition)
  ↓
WebApi/Services/{Feature}Service.cs  (extends generated gRPC base)
  ↓ Mapster (Proto → Command/Query)
Application/{Feature}CQ/Commands/ or Queries/
  ↓ MediatR
Handler → Repository (DbContext)
  ↓
Domain/Entities/{Entity}.cs

5. فاز ۱ — موجودیت‌های بکند (CMS) تکمیل شد

وضعیت: تکمیل | اولویت: بالا | پیش‌نیاز: ندارد

5.1 موجودیت‌های جدید Domain

BlogPost.cs

Location: CMS/src/CMSMicroservice.Domain/Entities/Blog/BlogPost.cs
Base: BaseAuditableEntity

Properties:
  - string Title (required, max 200)
  - string Slug (required, unique, max 200)
  - string Summary (max 500) — خلاصه برای کارت‌ها
  - string HtmlContent (required) — محتوای HTML کامل
  - string? FeaturedImagePath — تصویر شاخص
  - string? FeaturedImageThumbnailPath — تامبنیل تصویر شاخص
  - BlogPostStatus Status (enum: Draft, Published, Scheduled, Archived)
  - DateTime? PublishedAt — زمان انتشار
  - DateTime? ScheduledPublishAt — زمانبندی انتشار
  - int ViewCount — تعداد بازدید
  - long AuthorUserId — نویسنده
  - bool IsFeatured — نمایش در صفحه اول
  - int SortOrder — ترتیب نمایش

Relations:
  - ICollection<BlogPostCategory> BlogPostCategories
  - ICollection<BlogPostTag> BlogPostTags
  - ICollection<BlogPostImage> BlogPostImages

BlogCategory.cs

Location: CMS/src/CMSMicroservice.Domain/Entities/Blog/BlogCategory.cs
Base: BaseAuditableEntity

Properties:
  - string Title (required, max 100)
  - string Slug (required, unique, max 100)
  - string? Description (max 500)
  - string? IconName — آیکون Material
  - int SortOrder
  - bool IsActive

Relations:
  - ICollection<BlogPostCategory> BlogPostCategories

BlogPostCategory.cs (Join Table)

Location: CMS/src/CMSMicroservice.Domain/Entities/Blog/BlogPostCategory.cs
Base: BaseEntity

Properties:
  - long BlogPostId
  - long BlogCategoryId

Relations:
  - BlogPost BlogPost
  - BlogCategory BlogCategory

BlogPostTag.cs (Join Table)

Location: CMS/src/CMSMicroservice.Domain/Entities/Blog/BlogPostTag.cs
Base: BaseEntity

Properties:
  - long BlogPostId
  - long TagId

Relations:
  - BlogPost BlogPost
  - Tag Tag (موجود — استفاده مجدد)

BlogPostImage.cs

Location: CMS/src/CMSMicroservice.Domain/Entities/Blog/BlogPostImage.cs
Base: BaseAuditableEntity

Properties:
  - long BlogPostId
  - string ImagePath
  - string ThumbnailPath
  - string? AltText (max 200)
  - string? Caption (max 300)
  - int SortOrder

Relations:
  - BlogPost BlogPost

SitePage.cs (صفحات دینامیک)

Location: CMS/src/CMSMicroservice.Domain/Entities/Content/SitePage.cs
Base: BaseAuditableEntity

Properties:
  - string PageKey (unique, e.g. "about", "contact") — کلید شناسایی
  - string Title (max 200)
  - string? MetaDescription (max 300) — SEO
  - string? HeroTitle — عنوان Hero
  - string? HeroSubtitle — زیرعنوان Hero
  - string? HeroImagePath — تصویر Hero
  - bool IsActive

Relations:
  - ICollection<SitePageSection> Sections

SitePageSection.cs (بخش‌های صفحه)

Location: CMS/src/CMSMicroservice.Domain/Entities/Content/SitePageSection.cs
Base: BaseAuditableEntity

Properties:
  - long SitePageId
  - string SectionKey (e.g. "mission", "vision", "team-member-1")
  - string Title (max 200)
  - string? Subtitle (max 300)
  - string? HtmlContent — محتوای HTML
  - string? IconName — آیکون Material
  - string? ImagePath
  - string? ImageThumbnailPath
  - int SortOrder
  - bool IsActive
  - string? ExtraData — JSON blob for flexible data

Relations:
  - SitePage SitePage

Enum: BlogPostStatus.cs

Location: CMS/src/CMSMicroservice.Domain/Enums/BlogPostStatus.cs

Values:
  Draft = 0
  Published = 1
  Scheduled = 2
  Archived = 3

5.2 Entity Configurations (Infrastructure)

فایل‌های جدید:
  CMS/src/CMSMicroservice.Infrastructure/Configurations/Blog/
    ├── BlogPostConfiguration.cs
    ├── BlogCategoryConfiguration.cs
    ├── BlogPostCategoryConfiguration.cs
    ├── BlogPostTagConfiguration.cs
    └── BlogPostImageConfiguration.cs
  CMS/src/CMSMicroservice.Infrastructure/Configurations/Content/
    ├── SitePageConfiguration.cs
    └── SitePageSectionConfiguration.cs

فایل‌های ویرایشی:
  CMS/src/CMSMicroservice.Infrastructure/ApplicationDbContext.cs
    + DbSet<BlogPost> BlogPosts
    + DbSet<BlogCategory> BlogCategories
    + DbSet<BlogPostCategory> BlogPostCategories
    + DbSet<BlogPostTag> BlogPostTags
    + DbSet<BlogPostImage> BlogPostImages
    + DbSet<SitePage> SitePages
    + DbSet<SitePageSection> SitePageSections

5.3 Proto Definitions

blogpost.proto

Location: CMS/src/CMSMicroservice.Protobuf/Protos/blogpost.proto

service BlogPostContract {
  rpc CreateBlogPost (CreateBlogPostRequest) returns (BlogPostResponse);
  rpc UpdateBlogPost (UpdateBlogPostRequest) returns (BlogPostResponse);
  rpc DeleteBlogPost (DeleteBlogPostRequest) returns (BoolResponse);
  rpc GetBlogPost (GetBlogPostRequest) returns (BlogPostResponse);
  rpc GetBlogPostBySlug (GetBlogPostBySlugRequest) returns (BlogPostResponse);
  rpc GetAllBlogPosts (GetAllBlogPostsRequest) returns (BlogPostListResponse);
  rpc GetPublishedBlogPosts (GetPublishedBlogPostsRequest) returns (BlogPostListResponse);
  rpc GetFeaturedBlogPosts (GetFeaturedBlogPostsRequest) returns (BlogPostListResponse);
  rpc PublishBlogPost (PublishBlogPostRequest) returns (BoolResponse);
  rpc ArchiveBlogPost (ArchiveBlogPostRequest) returns (BoolResponse);
  rpc IncrementViewCount (IncrementViewCountRequest) returns (BoolResponse);
}

blogcategory.proto

Location: CMS/src/CMSMicroservice.Protobuf/Protos/blogcategory.proto

service BlogCategoryContract {
  rpc CreateBlogCategory (CreateBlogCategoryRequest) returns (BlogCategoryResponse);
  rpc UpdateBlogCategory (UpdateBlogCategoryRequest) returns (BlogCategoryResponse);
  rpc DeleteBlogCategory (DeleteBlogCategoryRequest) returns (BoolResponse);
  rpc GetBlogCategory (GetBlogCategoryRequest) returns (BlogCategoryResponse);
  rpc GetAllBlogCategories (GetAllBlogCategoriesRequest) returns (BlogCategoryListResponse);
}

blogpostimage.proto

Location: CMS/src/CMSMicroservice.Protobuf/Protos/blogpostimage.proto

service BlogPostImageContract {
  rpc AddBlogPostImage (AddBlogPostImageRequest) returns (BlogPostImageResponse);
  rpc DeleteBlogPostImage (DeleteBlogPostImageRequest) returns (BoolResponse);
  rpc GetBlogPostImages (GetBlogPostImagesRequest) returns (BlogPostImageListResponse);
  rpc ReorderBlogPostImages (ReorderBlogPostImagesRequest) returns (BoolResponse);
}

sitepage.proto

Location: CMS/src/CMSMicroservice.Protobuf/Protos/sitepage.proto

service SitePageContract {
  rpc GetSitePage (GetSitePageRequest) returns (SitePageResponse);
  rpc GetSitePageByKey (GetSitePageByKeyRequest) returns (SitePageResponse);
  rpc UpdateSitePage (UpdateSitePageRequest) returns (SitePageResponse);
  rpc GetAllSitePages (GetAllSitePagesRequest) returns (SitePageListResponse);
  rpc CreateSitePageSection (CreateSitePageSectionRequest) returns (SitePageSectionResponse);
  rpc UpdateSitePageSection (UpdateSitePageSectionRequest) returns (SitePageSectionResponse);
  rpc DeleteSitePageSection (DeleteSitePageSectionRequest) returns (BoolResponse);
  rpc ReorderSitePageSections (ReorderSitePageSectionsRequest) returns (BoolResponse);
}

5.4 Application Layer (CQRS)

CMS/src/CMSMicroservice.Application/
  BlogPostCQ/
    Commands/
      CreateBlogPost/
        CreateBlogPostCommand.cs
        CreateBlogPostCommandHandler.cs
        CreateBlogPostCommandValidator.cs
      UpdateBlogPost/
        UpdateBlogPostCommand.cs
        UpdateBlogPostCommandHandler.cs
        UpdateBlogPostCommandValidator.cs
      DeleteBlogPost/
        DeleteBlogPostCommand.cs
        DeleteBlogPostCommandHandler.cs
      PublishBlogPost/
        PublishBlogPostCommand.cs
        PublishBlogPostCommandHandler.cs
      ArchiveBlogPost/
        ArchiveBlogPostCommand.cs
        ArchiveBlogPostCommandHandler.cs
    Queries/
      GetBlogPost/
        GetBlogPostQuery.cs
        GetBlogPostQueryHandler.cs
      GetBlogPostBySlug/
        GetBlogPostBySlugQuery.cs
        GetBlogPostBySlugQueryHandler.cs
      GetAllBlogPosts/
        GetAllBlogPostsQuery.cs
        GetAllBlogPostsQueryHandler.cs
      GetPublishedBlogPosts/
        GetPublishedBlogPostsQuery.cs
        GetPublishedBlogPostsQueryHandler.cs
      GetFeaturedBlogPosts/
        GetFeaturedBlogPostsQuery.cs
        GetFeaturedBlogPostsQueryHandler.cs

  BlogCategoryCQ/
    Commands/
      CreateBlogCategory/ (3 files)
      UpdateBlogCategory/ (3 files)
      DeleteBlogCategory/ (2 files)
    Queries/
      GetBlogCategory/ (2 files)
      GetAllBlogCategories/ (2 files)

  BlogPostImageCQ/
    Commands/
      AddBlogPostImage/ (3 files)
      DeleteBlogPostImage/ (2 files)
      ReorderBlogPostImages/ (2 files)
    Queries/
      GetBlogPostImages/ (2 files)

  SitePageCQ/
    Commands/
      UpdateSitePage/ (3 files)
      CreateSitePageSection/ (3 files)
      UpdateSitePageSection/ (3 files)
      DeleteSitePageSection/ (2 files)
      ReorderSitePageSections/ (2 files)
    Queries/
      GetSitePage/ (2 files)
      GetSitePageByKey/ (2 files)
      GetAllSitePages/ (2 files)

5.5 WebApi Services & Mappings

CMS/src/CMSMicroservice.WebApi/
  Services/
    BlogPostService.cs     — extends BlogPostContractBase
    BlogCategoryService.cs — extends BlogCategoryContractBase
    BlogPostImageService.cs — extends BlogPostImageContractBase
    SitePageService.cs     — extends SitePageContractBase
  Common/Mappings/
    BlogPostProfile.cs
    BlogCategoryProfile.cs
    BlogPostImageProfile.cs
    SitePageProfile.cs

5.6 Migration

# ساخت Migration جدید
cd CMS/src/CMSMicroservice.Infrastructure
dotnet ef migrations add AddBlogAndSitePages \
  --startup-project ../CMSMicroservice.WebApi \
  --context ApplicationDbContext

6. فاز ۲ — پنل مدیریت بلاگ (BackOffice) تکمیل شد

تخمین: ۲-۳ روز | اولویت: بالا | پیش‌نیاز: فاز ۱ | وضعیت: تکمیل

6.1 صفحات ایجاد شده BackOffice

BackOffice/src/BackOffice/Pages/
  Blog/
    BlogPostManagementPage.razor         — لیست پست‌ها + فیلتر وضعیت/دسته‌بندی + جستجو
    BlogPostManagementPage.razor.cs      — کدبیهایند: LoadServerData، CRUD، Publish، Archive
    BlogCategoryManagementPage.razor     — مدیریت دسته‌بندی‌ها (MudDataGrid)
    BlogCategoryManagementPage.razor.cs
    Components/
      BlogPostEditDialog.razor           — ایجاد/ویرایش پست (عنوان، اسلاگ، خلاصه، HTML، دسته‌بندی‌ها)
      BlogPostEditDialog.razor.cs        — Multi-select دسته‌بندی + ویژه/ترتیب
      BlogCategoryEditDialog.razor       — ایجاد/ویرایش دسته‌بندی
      BlogCategoryEditDialog.razor.cs

  Content/
    SitePageManagementPage.razor         — لیست صفحات سایت
    SitePageManagementPage.razor.cs      — ویرایش صفحه + مدیریت بخش‌ها
    Components/
      SitePageEditDialog.razor           — ویرایش اطلاعات صفحه (Hero, Meta, وضعیت)
      SitePageEditDialog.razor.cs
      SitePageSectionsDialog.razor       — مدیریت بخش‌های صفحه (CRUD + لیست)
      SitePageSectionsDialog.razor.cs
      SitePageSectionEditDialog.razor    — ایجاد/ویرایش بخش (کلید، عنوان، HTML، تصاویر)
      SitePageSectionEditDialog.razor.cs

6.2 ناوبری BackOffice (NavMenu)

بخش «مدیریت محتوا» به NavMenu.razor اضافه شد (قبل از بخش سیستم):

<MudText Class="nav-menu__title" Typo="Typo.subtitle2">مدیریت محتوا</MudText>

<AuthorizeView Roles="Administrator">
    <Authorized>
        @if (CanManageBlog)
        {
            <MudNavGroup Title="بلاگ" Icon="@Icons.Material.Filled.Article" Expanded="false">
                <MudNavLink Href="/blog/posts" Icon="@Icons.Material.Filled.PostAdd">پست‌ها</MudNavLink>
                <MudNavLink Href="/blog/categories" Icon="@Icons.Material.Filled.Category">دسته‌بندی‌ها</MudNavLink>
            </MudNavGroup>
        }

        @if (CanManageSitePages)
        {
            <MudNavLink Href="/content/pages" Icon="@Icons.Material.Filled.WebAsset">صفحات سایت</MudNavLink>
        }
    </Authorized>
</AuthorizeView>

مجوزهای جدید: blog.manage، sitepages.manage

6.3 سرویس‌های BackOffice

BackOffice/src/BackOffice/Services/
  Blog/
    IBlogCategoryService.cs     — اینترفیس + DTOs (Filter, ListResult, Item, Edit)
    BlogCategoryService.cs      — پیاده‌سازی با gRPC client (GetAll, GetActive, GetById, Create, Update, Delete)
    IBlogPostService.cs         — اینترفیس + DTOs (Filter, ListResult, ListItem, Details, Edit, PublishResult, ArchiveResult)
    BlogPostService.cs          — پیاده‌سازی (CRUD + Publish + Archive)
    IBlogPostImageService.cs    — اینترفیس + DTOs (ImageItem, ImageAdd, ImageSort)
    BlogPostImageService.cs     — پیاده‌سازی (GetByPostId, Add, Delete, Reorder)
  Content/
    ISitePageService.cs         — اینترفیس + DTOs (Summary, Details, SectionItem, Edit, SectionEdit, SectionSort)
    SitePageService.cs          — پیاده‌سازی (GetAll, GetById, Update, CRUD Section, Reorder)

ثبت DI در ConfigureService.cs:

  • ۴ gRPC Client: BlogPostContractClient، BlogCategoryContractClient، BlogPostImageContractClient، SitePageContractClient
  • ۴ Application Service: IBlogPostService، IBlogCategoryService، IBlogPostImageService، ISitePageService

6.4 ویرایشگر محتوا

از پکیج موجود Tizzani.MudBlazor.HtmlEditor (قبلاً نصب شده) استفاده می‌شود:

<!-- در CreateBlogPostDialog -->
<MudHtmlEditor @bind-Value="_post.HtmlContent"
               Placeholder="محتوای مقاله را بنویسید..."
               MinHeight="400px" />

6.5 آپلود تصویر شاخص

از سرویس موجود IFileManagerService استفاده:

// الگوی موجود از ProductService
var imagePath = await _fileManagerService.UploadFileAsync(imageBytes, fileName);

6.6 مشخصات صفحه مدیریت مقالات

ویژگی شرح
جدول مقالات MudDataGrid با ستون‌های: عنوان، دسته‌بندی، وضعیت، تاریخ انتشار، بازدید
فیلتر وضعیت (همه/پیش‌نویس/منتشر/آرشیو) + جستجوی عنوان
عملیات ایجاد، ویرایش، حذف، انتشار، آرشیو، پیش‌نمایش
تصویر شاخص Drag & Drop آپلود + پیش‌نمایش
دسته‌بندی Multi-select از دسته‌بندی‌های موجود
تگ Multi-select با autocomplete از تگ‌های موجود
ویرایشگر WYSIWYG HTML editor (MudBlazor.HtmlEditor)

7. فاز ۳ — صفحات محتوای دینامیک (درباره ما / تماس با ما) تکمیل شد

وضعیت: تکمیل | اولویت: متوسط | پیش‌نیاز: فاز ۱

7.1 تغییرات About.razor

قبل (فعلی): محتوا هاردکد — عنوان‌ها، تصاویر، متون همه در Razor مستقیم نوشته شده

بعد (جدید):

OnInitializedAsync:
  1. صدا زدن SitePageContract.GetSitePageByKey("about")
  2. دریافت SitePage + Sections
  3. نمایش دینامیک با loop روی Sections
  
Fallback:
  - اگر سرویس خطا داد → نمایش محتوای پیش‌فرض (هاردکد فعلی به عنوان fallback)

ساختار بخش‌های صفحه درباره ما:

SectionKey نوع داده
hero Hero HeroTitle, HeroSubtitle, HeroImagePath
mission Card Title, HtmlContent, IconName
vision Card Title, HtmlContent, IconName
value-1 ... value-N Cards Grid Title, Subtitle, IconName, HtmlContent
team-1 ... team-N Team Cards Title (نام), Subtitle (سمت), HtmlContent (توضیح), ImagePath

7.2 تغییرات Contact.razor

SectionKey نوع داده
hero Hero HeroTitle, HeroSubtitle
contact-info Info ExtraData (JSON: address, phone, email, hours)
social-media Links ExtraData (JSON: telegram, instagram, linkedin, whatsapp urls)
map Map ExtraData (JSON: lat, lng, address text)

7.3 Seed Data

اجرای اولیه Migration با داده پیش‌فرض (محتوای هاردکد فعلی):

// در SitePageConfiguration یا Seed Migration
var aboutPage = new SitePage {
    PageKey = "about",
    Title = "درباره ما",
    HeroTitle = "پلتفرم هوشمند تیم‌سازی و مدیریت فروش",
    HeroSubtitle = "ما با ارائه ابزارهای نوآورانه...",
    IsActive = true
};
// + Sections با محتوای فعلی

8. فاز ۴ — نوسازی لندینگ پیج تکمیل شد

وضعیت: تکمیل | اولویت: بالا | پیش‌نیاز: فاز ۱ (بخش بلاگ برای "آخرین مقالات")

8.1 ساختار جدید لندینگ پیج

┌─────────────────────────────────────────┐
│            🔝 HERO SECTION              │
│  • Gradient animated background         │
│  • عنوان بزرگ + زیرعنوان              │
│  • Badge‌های انیمیشنی                   │
│  • CTA buttons با hover effects        │
│  • تصویر/ایلاستریشن سمت چپ           │
│  • اعداد زنده (تعداد کاربران، ...)    │
└─────────────────────────────────────────┘
          ↓ Scroll indicator ↓
┌─────────────────────────────────────────┐
│         ✨ FEATURES (چرا ما؟)           │
│  • 6 کارت با آیکون + عنوان + توضیح    │
│  • Hover effect (scale + shadow)        │
│  • انیمیشن fade-in on scroll           │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│      📊 LIVE STATS (آمار زنده)          │
│  • Counter animation (شمارش تعداد)      │
│  • تعداد کاربران فعال                   │
│  • تعداد محصولات                        │
│  • حجم معاملات                         │
│  • Intersection Observer trigger        │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│      🔄 HOW IT WORKS (چطور کار می‌کند) │
│  • Timeline بهبودیافته                  │
│  • آیکون‌های مرحله‌ای بزرگ‌تر          │
│  • انیمیشن step-by-step               │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│     📝 LATEST BLOG (آخرین مقالات)      │  ← جدید!
│  • ۳ کارت آخرین مقالات منتشرشده       │
│  • تصویر شاخص + عنوان + خلاصه         │
│  • دکمه "مشاهده همه مقالات"            │
│  • Loading skeleton                    │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│    🏆 TESTIMONIALS (اعتماد مشتریان)     │
│  • Carousel/Swiper اسلایدر             │
│  • Avatar + نام + سمت + نقل قول       │
│  • Auto-play + دکمه‌های ناوبری         │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│      ❓ FAQ (سوالات متداول)              │
│  • بدون تغییر اساسی (فقط پولیش)       │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│      📞 CTA BANNER (دعوت نهایی)        │  ← جدید!
│  • Gradient background                 │
│  • عنوان جذاب + دکمه ثبت‌نام          │
│  • طرح ساده و تأثیرگذار               │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│            🦶 FOOTER                     │
│  • بدون تغییر اساسی + لینک بلاگ       │
└─────────────────────────────────────────┘

8.2 تغییرات فنی لندینگ

الف) Hero Section بهبودیافته

تغییرات:
  1. Animated gradient background (CSS keyframes)
  2. اعداد واقعی از API (تعداد کاربران، محصولات، ...)
  3. Badge‌ها با انیمیشن pulse
  4. Scroll-down indicator (chevron انیمیشنی)
  5. تصویر/SVG illustration سمت چپ

ب) آمار زنده (Live Stats)

سرویس جدید — یک Query ساده در CMS:
  GetPlatformStats → { UserCount, ProductCount, OrderCount, ... }
  
فرانت: 
  - Counter animation (JS interop یا CSS counter)
  - Intersection Observer: فقط وقتی اسکرول به این بخش رسید شمارش شروع شود

ج) بخش آخرین مقالات (جدید)

<!-- Latest Blog Posts Section -->
<section class="py-16">
  <MudContainer MaxWidth="MaxWidth.Large">
    <MudText Typo="Typo.h4" Align="Align.Center">آخرین مقالات</MudText>
    <MudGrid Spacing="4">
      @foreach (var post in _latestPosts.Take(3))
      {
        <MudItem xs="12" md="4">
          <BlogPostCard Post="post" />
        </MudItem>
      }
    </MudGrid>
    <MudButton Href="/blog" Variant="Variant.Outlined">مشاهده همه</MudButton>
  </MudContainer>
</section>

د) CTA Banner نهایی (جدید)

<!-- Final CTA -->
<section class="cta-banner py-16">
  <MudContainer MaxWidth="MaxWidth.Medium">
    <MudStack AlignItems="AlignItems.Center" Spacing="4">
      <MudText Typo="Typo.h3">آماده شروع هستید؟</MudText>
      <MudText>همین الان ثبت‌نام کنید و از مزایای کارا بازار سلامت بهره‌مند شوید.</MudText>
      <MudButton Variant="Variant.Filled" Color="Color.Primary" Size="Size.Large">
        شروع رایگان
      </MudButton>
    </MudStack>
  </MudContainer>
</section>

8.3 CSS جدید / بهبودیافته

/* فایل: wwwroot/css/app.css — بخش‌های جدید */

/* Animated gradient hero */
.hero-section {
  background: linear-gradient(-45deg, #6366f1, #8b5cf6, #a855f7, #6366f1);
  background-size: 400% 400%;
  animation: gradientShift 8s ease infinite;
}

@keyframes gradientShift {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

/* Scroll-triggered fade-in */
.fade-in-up {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.fade-in-up.visible {
  opacity: 1;
  transform: translateY(0);
}

/* Counter animation */
@property --num {
  syntax: '<integer>';
  initial-value: 0;
  inherits: false;
}
.counter {
  animation: counter 2s ease-out forwards;
  counter-reset: num var(--num);
}

/* Pulse badge */
.pulse-badge {
  animation: pulse 2s infinite;
}
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 rgba(99,102,241,0.4); }
  70% { box-shadow: 0 0 0 10px rgba(99,102,241,0); }
  100% { box-shadow: 0 0 0 0 rgba(99,102,241,0); }
}

/* CTA Banner */
.cta-banner {
  background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
  color: white;
  border-radius: 24px;
  margin: 2rem;
}

/* Card hover effects */
.feature-card-v2 {
  transition: transform 0.3s, box-shadow 0.3s;
}
.feature-card-v2:hover {
  transform: translateY(-8px);
  box-shadow: 0 12px 40px rgba(0,0,0,0.12);
}

/* Blog post card */
.blog-card {
  transition: transform 0.3s ease;
  overflow: hidden;
}
.blog-card:hover {
  transform: translateY(-4px);
}
.blog-card .blog-card-image {
  transition: transform 0.5s ease;
}
.blog-card:hover .blog-card-image {
  transform: scale(1.05);
}

8.4 JS Interop (حداقل)

// فایل: wwwroot/js/landing.js

// Intersection Observer for fade-in animations
window.initScrollAnimations = () => {
  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        entry.target.classList.add('visible');
        observer.unobserve(entry.target);
      }
    });
  }, { threshold: 0.1 });

  document.querySelectorAll('.fade-in-up').forEach(el => observer.observe(el));
};

// Counter animation
window.animateCounter = (elementId, target, duration) => {
  const el = document.getElementById(elementId);
  if (!el) return;
  let start = 0;
  const step = target / (duration / 16);
  const timer = setInterval(() => {
    start += step;
    if (start >= target) { start = target; clearInterval(timer); }
    el.textContent = Math.floor(start).toLocaleString('fa-IR');
  }, 16);
};

9. فاز ۵ — صفحات بلاگ فرانت‌آفیس تکمیل شد

وضعیت: تکمیل | اولویت: بالا | پیش‌نیاز: فاز ۱

9.1 صفحات ایجاد شده (واقعی)

FrontOffice/src/FrontOffice.Main/Pages/Blog/
  Index.razor              — لیست مقالات با جستجو + فیلتر دسته‌بندی + صفحه‌بندی
  Index.razor.cs           — LoadPostsAsync، OnCategoryChanged، OnPageChanged، NavigateToPost
  Post.razor               — صفحه جزئیات مقاله (تصویر شاخص، breadcrumb، HTML، تگ‌ها)
  Post.razor.cs            — OnParametersSetAsync (لود slug)، IncrementViewCount خودکار

9.2 سرویس‌های جدید فرانت‌آفیس

FrontOffice/src/FrontOffice.Main/Utilities/
  BlogPostService.cs       — (قبلاً فاز ۴ ایجاد شد) GetFeatured, GetPublished, GetBySlug, IncrementView
  BlogCategoryService.cs   — GetActiveCategoriesAsync (فیلتر سایدبار بلاگ)

DTOs تعریف شده در BlogPostService.cs:

  • BlogPostCardDto — Id, Title, Slug, Summary, ThumbnailUrl, PublishedAt, ViewCount, IsFeatured, Categories
  • BlogPostDetailDto — همه فیلدهای کارت + HtmlContent, FeaturedImagePath, Tags
  • BlogPostListResult — Posts, TotalCount, TotalPages, CurrentPage
  • BlogCategoryInfo — Id, Title, Slug
  • BlogTagInfo — Id, Title, Name

DTO تعریف شده در BlogCategoryService.cs:

  • BlogCategoryDto — Id, Title, Slug, Description, IconName, PostCount

9.3 مسیرها (Routes) — پیاده‌سازی شده

// RouteConstants.cs
public static class Blog
{
    public const string Index = "/blog";
    public const string Post = "/blog/"; // usage: /blog/{slug}
}

9.4 طراحی صفحه لیست بلاگ — پیاده‌سازی شده

┌─────────────────────────────────────────┐
│           Blog Hero (گرادیان بنفش)       │
│  "بلاگ"                                 │
│  "آخرین مطالب، آموزش‌ها و اخبار"        │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│  [جستجو...] [دسته‌بندی ▼] [جستجو 🔍]    │  ← فیلتر + MudSelect
└─────────────────────────────────────────┘
┌────────┐ ┌────────┐ ┌────────┐
│ Card 1 │ │ Card 2 │ │ Card 3 │   ← blog-card-v2
│ thumb  │ │ thumb  │ │ thumb  │   ← تصویر شاخص
│ cat    │ │ cat    │ │ cat    │   ← chip دسته‌بندی
│ title  │ │ title  │ │ title  │   ← ۲ خط clamp
│ desc   │ │ desc   │ │ desc   │   ← ۲ خط clamp
│ 📅 👁  │ │ 📅 👁  │ │ 📅 👁  │   ← تاریخ + بازدید
└────────┘ └────────┘ └────────┘
     ← ← ← [1] [2] [3] → → →       ← MudPagination

9.5 طراحی صفحه مقاله — پیاده‌سازی شده

┌─────────────────────────────────────────┐
│  [تصویر شاخص full-width] + overlay     │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│  خانه > بلاگ > عنوان مقاله             │ ← Breadcrumb
│                                         │
│  [دسته‌بندی ۱] [دسته‌بندی ۲]             │ ← Chips (کلیک → فیلتر)
│                                         │
│  عنوان مقاله (H4, bold)                 │
│  خلاصه مقاله (subtitle)                │
│                                         │
│  📅 تاریخ  👁 ۱,۲۳۴ بازدید             │
│  ─────────────────────────              │
│                                         │
│  [محتوای HTML مقاله]                    │ ← blog-content (styled)
│  ...                                    │
│                                         │
│  ─────────────────────────              │
│  🏷️ [تگ ۱] [تگ ۲] [تگ ۳]              │ ← Outlined chips
│                                         │
│  [← بازگشت به بلاگ]                     │
└─────────────────────────────────────────┘

9.6 CSS اضافه شده (بخش Blog Pages در site.css)

/* Blog Pages region — اضافه شده به site.css */
.blog-hero           گرادیان بنفش (مشابه CTA)
.blog-title-clamp    -webkit-line-clamp: 2
.blog-summary-clamp  -webkit-line-clamp: 2
.cursor-pointer      cursor: pointer
.blog-detail-hero    تصویر شاخص 340px + overlay
.blog-content        تایپوگرافی مقاله (h1-h3, p, img, blockquote, code, pre, ul/ol, a)
/* + mobile overrides + dark mode */

9.7 ناوبری — لینک بلاگ اضافه شد

تغییرات واقعی:
  - MainLayout.razor → لینک "بلاگ" در navbar دسکتاپ (بین FAQ و Contact)
  - MainLayout.razor → لینک "بلاگ" در Mobile Drawer
  - Index.razor (لندینگ) → کارت‌های بلاگ کلیک‌پذیر شدند (onclick)
  - Index.razor (لندینگ) → دکمه "مشاهده همه مقالات" فعال شد (uncomment)

9.8 ثبت DI (ConfigureServices.cs)

// اضافه شده:
using CMSMicroservice.Protobuf.Protos.BlogCategory;

// Common services:
services.AddScoped<BlogCategoryService>();

// gRPC clients:
services.AddScoped(CreateAuthenticatedClient<BlogCategoryContract.BlogCategoryContractClient>);

10. فاز ۶ — بهبود داشبورد کاربر تکمیل شد

وضعیت: تکمیل | اولویت: متوسط | پیش‌نیاز: ندارد

10.1 بازطراحی کامل Profile/Index.razor

صفحه /profile به طور کامل با طراحی مدرن بازنویسی شد:

┌─────────────────────────────────────────┐
│   ████ GRADIENT HEADER CARD ████        │ ← .dash-header-card
│   🧑 آواتار شیشه‌ای | نام + موبایل     │ ← .dash-avatar
│   عضو از ...  |  [💎 سامانه دایا]       │ ← دکمه glass-morphism
└─────────────────────────────────────────┘
┌──────────┐  ┌──────────┐  ┌──────────┐
│ 💳 اعتباری│  │ 🏷 تخفیف │  │ 👥 تیمی │  ← .dash-wallet-card
│ ۲.۵M تومان│  │ ۵۰۰K    │  │ ۸۵۰K    │     (hover lift)
└──────────┘  └──────────┘  └──────────┘
┌─────────────────────────────────────────┐
│   📎 کد دعوت شما | [اشتراک‌گذاری]       │ ← فعال اگر پکیج + باشگاه
│   یا                                    │
│   🔒 لینک دعوت فعال نشده (dashed border)│ ← حالت قفل
│   [شروع فرآیند تامین اعتبار]            │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│  دسترسی سریع                            │ ← .dash-tile (10 تایل)
│  ┌────┐ ┌────┐ ┌────┐ ┌────┐           │
│  │شخصی│ │آدرس│ │شجره│ │تنظیم│           │   هر تایل:
│  └────┘ └────┘ └────┘ └────┘           │   - آواتار رنگی
│  ┌────┐ ┌────┐ ┌────┐ ┌────┐           │   - عنوان + زیرعنوان
│  │فروش│ │کیف │ │برداشت│ │باشگا│          │   - hover: lift + primary border
│  └────┘ └────┘ └────┘ └────┘           │
│  ┌────┐ ┌────┐                         │
│  │آمار│ │پاداش│                         │
│  └────┘ └────┘                         │
└─────────────────────────────────────────┘

10.2 تغییرات فایل‌ها

Profile/Index.razor — بازنویسی کامل:

  • هدر گرادیانی (dash-header-card) با آواتار شیشه‌ای
  • ۳ کارت والت جداگانه (اعتباری/تخفیف/تیمی) با رنگ‌های مختلف
  • بخش رفرال تمیزتر (فعال با TextField + دکمه | قفل با dashed border)
  • ۱۰ تایل مدرن با DashTile record + آواتار رنگی

Profile/Index.razor.cs — اضافه شده:

private readonly List<DashTile> _dashTiles = new()
{
    new(RouteConstants.Profile.Personal, Icons.Material.Filled.Person, "اطلاعات شخصی", ...),
    new(RouteConstants.Profile.Addresses, Icons.Material.Filled.LocationOn, "آدرس‌ها", ...),
    // ... 10 تایل با رنگ‌بندی اختصاصی
};
private record DashTile(string Href, string Icon, string Title, string Subtitle, string AvatarStyle);

10.3 CSS اضافه شده (بخش Dashboard v2 در site.css)

/* Dashboard v2 region */
.dash-header-card      گرادیان بنفش + دایره تزئینی
.dash-avatar           شیشه‌ای (rgba + border سفید)
.dash-wallet-card      border + hover lift
.dash-tile             border + hover lift + primary border on hover
/* + dark mode + mobile overrides */

11. فاز ۷ — بهینه‌سازی موبایل تکمیل شد

وضعیت: تکمیل | اولویت: بالا | پیش‌نیاز: فازهای ۴-۶

11.1 مشکلات شناسایی و رفع شده

مشکل وضعیت قبل راه‌حل
Dead Zone ناوبری (600-959px) همبرگر فقط زیر 600px، لینک‌ها فقط بالای 960px تغییر Breakpoint از SmAndUp به MdAndUp
فوتر پنهان در موبایل DeviceDetector.IsDesktop() فوتر را حذف می‌کرد حذف شرط — فوتر همیشه نمایش داده شود
عدم وجود Bottom Nav فقط Drawer برای ناوبری موبایل اضافه شدن bottom-nav ثابت (5 لینک)
تایپوگرافی بزرگ h1=2rem, h2=1.875rem ثابت responsive: h1→1.5rem, h2→1.35rem در موبایل
Touch targets کوچک Dense AppBar، لینک‌های Drawer بدون padding min-height: 44px برای لینک‌ها، 40px برای آیکون‌ها
نقشه تماس بلند 400px ثابت 240px در موبایل با کلاس contact-map-placeholder
دکمه‌های About تنگ Row بدون flex-wrap اضافه flex-wrap + full-width در موبایل
محتوای بلاگ overflow بدون guard overflow-x: auto + table/iframe responsive
هاور در تاچ جلوه‌های هاور در صفحه لمسی @media (hover: none) — غیرفعال
Safe area بدون padding env(safe-area-inset-*) برای notched phones
theme-color نداشت <meta name="theme-color" content="#7c4dff">

11.2 Bottom Navigation — پیاده‌سازی

┌──────────────────────────────────────┐
│  🏠    🏬    📰    🛒    👤         │ ← .bottom-nav (fixed)
│ خانه  فروش  بلاگ  سبد  پروفایل     │    backdrop-filter blur
└──────────────────────────────────────┘
  • فقط در زیر Breakpoint.MdAndUp نمایش داده شود (MudHidden)
  • اگر لاگین نباشد: دکمه "ورود" بجای "سبد خرید" و "پروفایل"
  • padding-bottom: 68px روی .main-content-wrapper برای جلوگیری از overlap
  • env(safe-area-inset-bottom) برای گوشی‌های notched

11.3 CSS اضافه شده (بخش Phase 7 در site.css ~120 خط)

.bottom-nav              — fixed, z-1100, rounded top, glass blur
.bottom-nav-item         — flex column, min 48px touch, transition color
.main-content-wrapper    — padding-bottom 68px (≤960px)
responsive typography    — h1-h5 smaller ≤600px
touch targets            — drawer links 44px, appbar icons 40px
footer mobile            — compact padding, smaller text
landing mobile           — smaller chips, timeline text
blog mobile              — shorter thumbnails, scaled pagination, overflow guard
dashboard mobile         — compact wallets + tiles
about mobile             — hero button wrap, reduced padding
contact mobile           — shorter map, full-width submit
global mobile            — tighter container padding, safe-area
@media (hover: none)     — disable hover transforms on touch

11.4 فایل‌های تغییریافته

MainLayout.razor     — Breakpoint fix + Bottom Nav + Footer gate removed
site.css             — +120 خط CSS موبایل (Phase 7 region)
_Host.cshtml         — +theme-color + apple-mobile-web-app meta tags
Contact.razor        — +class contact-map-placeholder
About.razor          — +flex-wrap روی دکمه‌های hero

12. فایل‌های تغییریافته (نقشه فایل‌ها)

فایل‌های جدید

پروژه مسیر تعداد فایل
CMS Domain Entities/Blog/ (BlogPost, BlogCategory, BlogTag, BlogPostCategory, BlogPostTag, BlogPostImage) + Entities/Content/ (SitePage, SitePageAttachment) + Enums/ (BlogPostStatus) 9
CMS Infrastructure Configurations/Blog/ (5) + Configurations/Content/ (2) + EF Migration 8
CMS Application BlogPostCQ/ (~25) + BlogCategoryCQ/ (~12) + BlogPostImageCQ/ (~9) + SitePageCQ/ (~18) ~64
CMS Protobuf public_messages.proto + blogpost.proto + blogcategory.proto + sitepage.proto 4
CMS WebApi Services/ (BlogPostService, BlogCategoryService, SitePageService, BlogPostImageService) + Mappings/ (4 profiles) 8
BackOffice Pages Pages/Blog/ (BlogPosts.razor, BlogCategories.razor + ۲ dialog) + Pages/Content/ (SitePages.razor + ۳ dialog) 10
BackOffice Services Services/Blog/ (BlogPostService, BlogCategoryService, BlogTagService + ۳ model) + Services/Content/ (SitePageService + model) 8
FrontOffice Pages Pages/Blog/Index.razor + Index.razor.cs + Post.razor + Post.razor.cs 4
FrontOffice Services Utilities/BlogPostService.cs + Utilities/BlogCategoryService.cs + Utilities/SitePageService.cs 3
FrontOffice Assets wwwroot/js/landing.js 1
~119 فایل جدید

فایل‌های ویرایشی

پروژه فایل تغییر
CMS Infrastructure ApplicationDbContext.cs +7 DbSets (BlogPost, BlogCategory, BlogTag, BlogPostCategory, BlogPostTag, BlogPostImage, SitePage)
CMS WebApi Program.cs +4 gRPC service registrations
BackOffice Shared/NavMenu.razor +بخش مدیریت محتوا (بلاگ + صفحات) + ۲ مجوز جدید
BackOffice Common/Configure/ConfigureService.cs +4 gRPC clients + 4 services + using statements
FrontOffice Pages/Index.razor بازنویسی کامل (Hero + Features + Timeline + Stats + Blog + Testimonials + FAQ + CTA)
FrontOffice Pages/Index.razor.cs +LoadFeaturedPosts + NavigateToPost
FrontOffice Pages/About.razor تبدیل به دینامیک (CMS + fallback)
FrontOffice Pages/Contact.razor تبدیل به دینامیک (CMS + fallback)
FrontOffice Pages/Profile/Index.razor بازنویسی کامل (header card + wallets + tiles)
FrontOffice Pages/Profile/Index.razor.cs +DashTile record + _dashTiles لیست
FrontOffice Shared/MainLayout.razor +لینک بلاگ (desktop + mobile drawer)
FrontOffice Common/Configure/ConfigureServices.cs +BlogCategoryService + BlogCategoryContract gRPC
FrontOffice Utilities/RouteConstants.cs +Blog.Index + Blog.Post routes
FrontOffice wwwroot/css/site.css +Landing v2 + Blog Pages + Dashboard v2 (~300 خط CSS)
FrontOffice Pages/_Host.cshtml +landing.js script reference
~15 فایل ویرایشی

13. جدول زمانی

هفته ۱:
  ├─ فاز ۱: موجودیت‌های بکند (Entities + Protos + CQRS)     [۲-۳ روز] ✅ تکمیل
  └─ فاز ۲: پنل مدیریت بلاگ BackOffice                     [۲-۳ روز] ✅ تکمیل

هفته ۲:
  ├─ فاز ۳: صفحات دینامیک (About + Contact)                [۱-۲ روز] ✅ تکمیل
  ├─ فاز ۴: نوسازی لندینگ پیج                              [۲-۳ روز] ✅ تکمیل
  └─ فاز ۵: صفحات بلاگ FrontOffice                         [۲-۳ روز] ✅ تکمیل

هفته ۳:
  ├─ فاز ۶: بهبود داشبورد کاربر                            [۱-۲ روز] ✅ تکمیل
  ├─ فاز ۷: بهینه‌سازی موبایل                               [۱-۲ روز] ✅ تکمیل
  └─ تست + رفع باگ + دیپلوی                               [۱-۲ روز]

مجموع تخمین: ۱۲-۲۰ روز کاری (۲.۵ تا ۴ هفته)

ترتیب وابستگی

فاز ۱ (Backend) ──► فاز ۲ (Admin Blog)
     │              
     ├──────────► فاز ۳ (Dynamic Pages)
     │
     ├──────────► فاز ۵ (FrontOffice Blog)
     │                    │
     │                    ▼
     └──────────► فاز ۴ (Landing) ──► فاز ۷ (Mobile)
                                          ▲
                  فاز ۶ (Dashboard) ───────┘

14. ریسک‌ها و وابستگی‌ها

ریسک احتمال تأثیر راه‌حل
WYSIWYG Editor محدودیت RTL متوسط متوسط تست اولیه MudBlazor.HtmlEditor با فارسی، fallback به textarea + markdown
حجم Migration بزرگ کم بالا Migration را تکه‌تکه اجرا کن (Blog اول، SitePage بعد)
عملکرد لندینگ با انیمیشن‌ها متوسط متوسط Lazy load + Intersection Observer + حداقل JS
FMS قطعی هنگام آپلود تصویر کم بالا Retry policy + پیام خطای مناسب
Slug فارسی در URL متوسط کم استفاده از ID-based URLs با slug فقط برای SEO
سازگاری Dark Mode متوسط کم تست هر بخش در هر دو حالت

ضمیمه: نمونه کد الگوهای کلیدی

A. الگوی Entity (مطابق پروژه)

// Domain/Entities/Blog/BlogPost.cs
public class BlogPost : BaseAuditableEntity
{
    public string Title { get; set; } = default!;
    public string Slug { get; set; } = default!;
    public string? Summary { get; set; }
    public string HtmlContent { get; set; } = default!;
    public string? FeaturedImagePath { get; set; }
    public string? FeaturedImageThumbnailPath { get; set; }
    public BlogPostStatus Status { get; set; } = BlogPostStatus.Draft;
    public DateTime? PublishedAt { get; set; }
    public int ViewCount { get; set; }
    public long AuthorUserId { get; set; }
    public bool IsFeatured { get; set; }
    public int SortOrder { get; set; }
    
    public ICollection<BlogPostCategory> BlogPostCategories { get; set; } = new List<BlogPostCategory>();
    public ICollection<BlogPostTag> BlogPostTags { get; set; } = new List<BlogPostTag>();
    public ICollection<BlogPostImage> BlogPostImages { get; set; } = new List<BlogPostImage>();
}

B. الگوی Proto (مطابق پروژه)

// blogpost.proto
syntax = "proto3";
option csharp_namespace = "CMSMicroservice.Protobuf";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";

service BlogPostContract {
  rpc CreateBlogPost (CreateBlogPostRequest) returns (BlogPostResponse);
  rpc GetPublishedBlogPosts (GetPublishedBlogPostsRequest) returns (BlogPostListResponse);
  // ...
}

message CreateBlogPostRequest {
  string title = 1;
  string slug = 2;
  string summary = 3;
  string html_content = 4;
  bytes featured_image = 5;
  string featured_image_file_name = 6;
  repeated int64 category_ids = 7;
  repeated int64 tag_ids = 8;
  bool is_featured = 9;
}

message BlogPostResponse {
  int64 id = 1;
  string title = 2;
  string slug = 3;
  string summary = 4;
  string html_content = 5;
  string featured_image_path = 6;
  string featured_image_thumbnail_path = 7;
  int32 status = 8;
  google.protobuf.Timestamp published_at = 9;
  int32 view_count = 10;
  bool is_featured = 11;
  repeated BlogCategoryInfo categories = 12;
  repeated TagInfo tags = 13;
}

C. الگوی CQRS Handler (مطابق پروژه)

// Application/BlogPostCQ/Commands/CreateBlogPost/CreateBlogPostCommandHandler.cs
public class CreateBlogPostCommandHandler : IRequestHandler<CreateBlogPostCommand, long>
{
    private readonly IApplicationDbContext _context;
    private readonly IFileManagerService _fileManager;
    
    public CreateBlogPostCommandHandler(
        IApplicationDbContext context,
        IFileManagerService fileManager)
    {
        _context = context;
        _fileManager = fileManager;
    }
    
    public async Task<long> Handle(CreateBlogPostCommand request, CancellationToken ct)
    {
        var post = new BlogPost
        {
            Title = request.Title,
            Slug = request.Slug,
            Summary = request.Summary,
            HtmlContent = request.HtmlContent,
            Status = BlogPostStatus.Draft,
            AuthorUserId = request.AuthorUserId,
        };
        
        if (request.FeaturedImage?.Length > 0)
        {
            var (path, thumb) = await _fileManager.UploadFileAsync(
                request.FeaturedImage, request.FeaturedImageFileName);
            post.FeaturedImagePath = path;
            post.FeaturedImageThumbnailPath = thumb;
        }
        
        _context.BlogPosts.Add(post);
        await _context.SaveChangesAsync(ct);
        
        // Add categories & tags...
        
        return post.Id;
    }
}

D. الگوی gRPC Service (مطابق پروژه)

// WebApi/Services/BlogPostService.cs
public class BlogPostService : BlogPostContract.BlogPostContractBase
{
    private readonly IMediator _mediator;
    private readonly IMapper _mapper;
    
    public BlogPostService(IMediator mediator, IMapper mapper)
    {
        _mediator = mediator;
        _mapper = mapper;
    }
    
    public override async Task<BlogPostResponse> CreateBlogPost(
        CreateBlogPostRequest request, ServerCallContext context)
    {
        var command = _mapper.Map<CreateBlogPostCommand>(request);
        var id = await _mediator.Send(command);
        // Get and return the created post...
    }
}

یادداشت: این سند یک نقشه‌راه جامع است. هر فاز به صورت مستقل قابل پیاده‌سازی است و وابستگی‌ها در بخش ۱۳ مشخص شده‌اند. بعد از تأیید این طرح، پیاده‌سازی فاز به فاز شروع می‌شود.