Files
FrontOffice/docs/UI-UNIFICATION-PLAN.md
T
Masoud 8f2d739d1f
Build and Deploy to Production / build-and-deploy (push) Has been cancelled
fix: update references from تخفیفی to اعتباری across multiple files
2026-02-17 15:24:13 +03:30

23 KiB
Raw Blame History

🎨 پلن جامع یکپارچه‌سازی UI/UX — کارا بازار سلامت

تاریخ: بهمن ۱۴۰۴
وضعیت: تمام ۶ فاز + فاز ۷ (ناوبری و امنیت) تکمیل شد
هدف: یکپارچه‌سازی طراحی FrontOffice با ۲۰٪ تغییر UX و ۵۰٪ تغییر UI
فریمورک: Blazor Server + MudBlazor 8.14
📋 تاریخچه تغییرات جزئی: CHANGELOG.md


📊 خلاصه اجرایی

شاخص وضعیت قبل وضعیت بعد
صفحات کل ۴۱ صفحه + ۶ کامپوننت مشترک ۴۱ صفحه + ۸ کامپوننت مشترک
الگوی PageHeader ۱۹ صفحه از ۴۱ ۳۲+ صفحه
Inline Style سنگین ۱۱ صفحه 🔴 ≤۲ صفحه (فقط gradient‌های تزئینی)
Loading State ۲ الگوی متفاوت (Circular vs Linear) <LoadingState> واحد
Empty State ۴+ الگوی متناقض <EmptyState> واحد
Container Spacing ۶ الگوی متناقض py-6 استاندارد
رنگ‌بندی رنگ‌های hardcoded در ۸+ صفحه CSS Variable
تم پالت Primary #0380C0 (آبی ساده) Indigo #6366f1 + Full PaletteDark
Elevation مخلوط ۲/۳/۴ استاندارد ۰–۲
Build ۰ خطا ۰ خطا

فازها

فاز عنوان وضعیت
۱ زیرساخت دیزاین سیستم تکمیل
۲ صفحات پروفایل تکمیل
۳ صفحات تخصصی تکمیل
۴ بهبود بصری فروشگاه تکمیل
۵ صفحات عمومی تکمیل
۶ پالیش و تست تکمیل
۷ ناوبری، امنیت و بازسازی کامپوننت‌ها تکمیل

🔍 بخش ۱: تحلیل ضعف‌های جاری

۱.۱ ناسازگاری‌های ساختاری (Structural)

۱.۱.۱ — PageHeader دوگانه

مشکل: نیمی از صفحات از <PageHeader> استفاده می‌کنند، نیم دیگر header دستی دارند.

از <PageHeader> استفاده می‌کنند Header دستی دارند
Store/* (۸ صفحه) Profile/* (۷ صفحه)
DiscountStore/* (۶ صفحه) Club/* (۲ صفحه)
Gateway/* (۳ صفحه) Commission/* (۲ صفحه)
Package/* (۲ صفحه) Network/* (۱ صفحه)
PackageDetail, Checkout Blog/*, Index, About, Contact, FAQ

تأثیر: ظاهر متفاوت دکمه بازگشت، فاصله‌بندی ناهماهنگ

۱.۱.۲ — Container MaxWidth متناقض

MaxWidth.Large    → اکثر صفحات
MaxWidth.Medium   → Personal, Settings, OrderTracking, Blog/Post, Gateway/*
MaxWidth.Small    → ChangePassword
ترکیبی (loading≠content) → OrderDetail, ProductDetail, PackageDetail

تأثیر: برخی صفحات پهن‌تر از حد نیاز هستند (مثلاً فرم‌های ساده با Large)

۱.۱.۳ — Container Padding متناقض

py-6       → اکثریت (استاندارد)
py-8       → Package/Packages, Package/MyPackages
pa-2 pa-md-6 → Store/Products, DiscountStore/Products
py-6 py-md-10 → Gateway/*
py-4 py-md-6 → DiscountStore/ProductDetail
py-16 سکشنی → Index, About, Contact, FAQ

قاعده پیشنهادی: py-6 برای صفحات داخلی، section-based برای صفحات عمومی


۱.۲ ناسازگاری‌های بصری (Visual)

۱.۲.۱ — Inline Style سنگین (۱۱ صفحه)

صفحه نمونه مشکل‌دار
Index.razor Style="color:#fff; font-size:clamp(1.6rem,4.5vw,2.4rem);"
Profile/Index Style="background:rgba(99,102,241,.12);"
Store/ProductDetail style="width:100%;height:360px;background-image:url(...);"
PackageDetail Style="background: radial-gradient(600px 280px..."
Checkout Style="background: radial-gradient(..." + Elevation="4"
Blog/Index Style="color:#fff; font-weight:700;", Style="font-size:3.5rem;"
Blog/Post Style="width:100%; height:100%;", Style="font-size:4rem;"
About Style="background: radial-gradient(...);"
WeeklyBalance Style="background: linear-gradient(135deg, #e8f5e9..."
Gateway/** Style="background:rgba(16,185,129,.12)...", Style="color:#10b981;"
DiscountStore/ProductDetail Style="background:rgba(16,185,129,.06)..."

۱.۲.۲ — رنگ‌های Hardcoded

رنگ استفاده باید باشد
#10b981 Gateway (سبز فروشگاه) var(--ds-color-store)
#ef4444 Gateway (قرمز تخفیفی) var(--ds-color-discount)
#6366f1, #818cf8, #a78bfa Hero/Banner gradients var(--ds-gradient-primary)
rgba(99,102,241,.12) Dashboard backgrounds var(--ds-primary-soft)
rgba(16,185,129,.06) Discount product highlights var(--ds-success-soft)
#e8f5e9, #c8e6c9 WeeklyBalance stat cards var(--ds-success-gradient)

۱.۲.۳ — Elevation ناهماهنگ

Elevation="0"  → Blog cards (با border)
Elevation="1"  → برخی صفحات
Elevation="2"  → اکثر صفحات (استاندارد)
Elevation="3"  → WeeklyBalance stat cards
Elevation="4"  → Checkout.razor

قاعده پیشنهادی: Elevation="0" با border = کارت‌های اطلاعاتی، Elevation="2" = default

۱.۲.۴ — Paper Rounding ناهماهنگ

rounded-lg  (16px) → اکثریت
rounded-xl  (20px) → Index, Profile/Index, Gateway, DiscountStore/ProductDetail  
بدون class  → design system !important → 12px

۱.۳ ناسازگاری‌های UX (تجربه کاربری)

۱.۳.۱ — Loading State دوگانه

MudProgressCircular  → Store/*, DiscountStore/*, Package/*, About, Blog, Addresses
MudProgressLinear    → Club/*, Commission/*, Network/*, RegisterWizard

مشکل: کاربر دو تجربه مختلف «در حال بارگذاری» می‌بیند

۱.۳.۲ — Empty State ناهماهنگ

MudAlert Severity.Info         → Store/Orders, Categories, DiscountStore/Orders
Icon + Text + Button           → Addresses, Package/MyPackages, PackageDetail
MudAlert Severity.Warning      → WithdrawalRequests
Custom dashed-border paper     → Blog/Index

۱.۳.۳ — Routing Directive ناهماهنگ

@attribute [Route(RouteConstants...)]  → ۳۹ صفحه ✅
@page "/categories"                    → Categories.razor ❌
@page "/blog/{Slug}"                   → Blog/Post.razor ❌  

۱.۳.۴ — PackageDetail Loading/Error بدون Container

Loading و Error state در PackageDetail.razor بدون MudContainer رندر می‌شوند → محتوا تمام‌عرض نمایش می‌یابد.

۱.۳.۵ — تم فعلی کم‌رنگ

// CustomMudTheme.cs فعلی
Primary = "#0380C0"       // آبی ساده
// بدون Secondary، Tertiary، Info، Warning تعریف‌شده
// بدون PaletteDark
// بدون LayoutProperties

مشکلات:

  • فقط Primary تعریف شده، بقیه رنگ‌ها default MudBlazor
  • Dark mode بدون palette اختصاصی
  • بدون DefaultBorderRadius، AppbarHeight و غیره
  • تناقض بین Primary #0380C0 و gradient‌های CSS با #6366f1

🎯 بخش ۲: معماری دیزاین سیستم هدف

۲.۱ سلسله‌مراتب صفحات

┌─────────────────────────────────────────────┐
│ MainLayout                                   │
│  ├─ AppBar (fixed, transparent)              │
│  ├─ MudMainContent                           │
│  │   ├─ [Public Pages] → Section-based       │
│  │   │   (Index, About, Contact, FAQ, Blog)  │
│  │   └─ [Internal Pages] → Container-based   │
│  │       ├─ <PageHeader/>                    │
│  │       ├─ Content (MudStack/MudGrid)       │
│  │       └─ </MudContainer>                  │
│  ├─ Footer (hidden on mobile)                │
│  └─ BottomNav (mobile only)                  │
└─────────────────────────────────────────────┘

۲.۲ قواعد واحد (Single Source of Truth)

قاعده مقدار
Container MaxWidth Large = لیست/گرید, Medium = فرم/جزئیات, Small = تک‌فرم ساده
Container Spacing py-6 صفحات داخلی, section-based صفحات عمومی
Paper Elevation 0 با border = کارت اطلاعاتی, 2 = default
Paper Rounding rounded-lg = default, rounded-xl = hero/banner
Loading State <LoadingState/> component واحد
Empty State <EmptyState/> component واحد
Page Header <PageHeader/> در تمام صفحات داخلی
Content Wrapper MudStack Spacing="3" بعد از PageHeader

۲.۳ CSS Variables هدف

:root {
    /* ── Brand Colors ── */
    --ds-brand-primary: #6366f1;        /* Indigo — هویت اصلی */
    --ds-brand-secondary: #8b5cf6;      /* Purple */
    --ds-brand-accent: #a78bfa;         /* Light purple */
    
    /* ── Semantic Colors ── */
    --ds-color-store: #10b981;          /* فروشگاه عادی */
    --ds-color-discount: #ef4444;       /* فروشگاه اعتباری */
    --ds-color-success: #10b981;
    --ds-color-warning: #f59e0b;
    --ds-color-error: #ef4444;
    --ds-color-info: #3b82f6;
    
    /* ── Soft Backgrounds ── */
    --ds-primary-soft: rgba(99,102,241,.08);
    --ds-success-soft: rgba(16,185,129,.08);
    --ds-error-soft: rgba(239,68,68,.08);
    --ds-warning-soft: rgba(245,158,11,.08);
    
    /* ── Gradients ── */
    --ds-gradient-primary: linear-gradient(135deg, #6366f1 0%, #818cf8 50%, #a78bfa 100%);
    --ds-gradient-store: linear-gradient(135deg, #10b981 0%, #34d399 100%);
    --ds-gradient-discount: linear-gradient(135deg, #ef4444 0%, #f97316 50%, #f59e0b 100%);
    --ds-gradient-success: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
    
    /* ── Spacing (existing) ── */
    --ds-radius-sm: 8px;
    --ds-radius-md: 12px;
    --ds-radius-lg: 16px;
    --ds-radius-xl: 20px;
    --ds-transition: 0.2s ease;
    --ds-shadow-sm: 0 1px 3px rgba(0,0,0,.06);
    --ds-shadow-md: 0 4px 12px rgba(0,0,0,.08);
    --ds-shadow-lg: 0 8px 24px rgba(0,0,0,.10);
}

🚀 بخش ۳: فازبندی اجرا

🔷 فاز ۱ — زیرساخت دیزاین سیستم (UI ~15%)

اولویت: بالا | ریسک: پایین | حجم: ۶ فایل

# تسک فایل نوع تغییر
1.1 ارتقاء CustomMudTheme.cs — اضافه کردن PaletteDark، LayoutProperties، رنگ‌های Secondary/Tertiary/Info، تغییر Primary به #6366f1 CustomMudTheme.cs UI
1.2 توسعه CSS Variables — اضافه کردن brand colors، semantic colors، soft backgrounds، gradients site.css UI
1.3 ساخت <LoadingState> component واحد Shared/LoadingState.razor (جدید) UX
1.4 ساخت <EmptyState> component واحد Shared/EmptyState.razor (جدید) UX
1.5 بهبود <PageHeader> — اضافه کردن آیکون، subtitle اختیاری Shared/PageHeader.razor UI
1.6 اضافه کردن .page-container CSS pattern site.css UI

🔷 فاز ۲ — یکپارچه‌سازی صفحات Profile (UI ~10%, UX ~5%)

اولویت: بالا | ریسک: پایین | حجم: ۹ فایل

# تسک تغییرات
2.1 Profile/Personal → جایگزینی header دستی با <PageHeader> UX
2.2 Profile/Addresses<PageHeader> + <LoadingState> + <EmptyState> UX
2.3 Profile/Wallet<PageHeader> UX
2.4 Profile/Settings<PageHeader> UX
2.5 Profile/Tree<PageHeader> UX
2.6 Profile/WithdrawalRequests<PageHeader> + <EmptyState> UX
2.7 Profile/ChangePassword<PageHeader> UX
2.8 Profile/Index (Dashboard) → حذف inline styles، استفاده از CSS Variables UI
2.9 Club/MembershipPage + Club/FeaturesPage<PageHeader> + <LoadingState> UX

🔷 فاز ۳ — یکپارچه‌سازی صفحات تخصصی (UI ~5%, UX ~5%)

اولویت: متوسط | ریسک: پایین | حجم: ۵ فایل

# تسک تغییرات
3.1 Commission/Dashboard<PageHeader> + <LoadingState> UX
3.2 Commission/WeeklyBalance<PageHeader> + حذف inline gradient styles UI + UX
3.3 Network/NetworkStatistics<PageHeader> + <LoadingState> UX
3.4 PackageDetail → wrap loading/error در MudContainer UX bug fix
3.5 Checkout → Elevation=4→2، حذف inline radial-gradient UI

🔷 فاز ۴ — بهبود بصری فروشگاه‌ها (UI ~10%)

اولویت: متوسط | ریسک: پایین | حجم: ۶ فایل

# تسک تغییرات
4.1 Store/Products → حذف inline hero styles، استفاده از CSS class UI
4.2 Store/ProductDetail → حذف inline image styles، ساخت .product-image-main CSS UI
4.3 DiscountStore/ProductDetail → حذف hardcoded rgba، استفاده از --ds-success-soft UI
4.4 Gateway/* (۳ صفحه) → حذف hardcoded #10b981/#ef4444، استفاده از --ds-color-store/--ds-color-discount UI
4.5 یکسان‌سازی Elevation → 0 با border یا 2 UI
4.6 یکسان‌سازی Container spacing → py-6 UI

🔷 فاز ۵ — بهبود صفحات عمومی و بلاگ (UI ~10%)

اولویت: پایین | ریسک: پایین | حجم: ۷ فایل

# تسک تغییرات
5.1 Index.razor → حذف inline styles از hero، استفاده از CSS class UI
5.2 About.razor → حذف inline radial-gradient UI
5.3 Contact.razor → cleanup minor inline styles UI
5.4 FAQ.razor → cleanup minor inline styles UI
5.5 Blog/Index → حذف inline hero styles، استفاده از CSS class UI
5.6 Blog/Post → حذف inline styles از hero image و typography UI
5.7 RegisterWizard → بهینه‌سازی wizard-section dark mode UI

🔷 فاز ۶ — Polish نهایی و فرآیندی (UX ~10%)

اولویت: پایین | ریسک: بسیار پایین | حجم: ۴ فایل + تست

# تسک تغییرات
6.1 Fix routing inconsistency — Categories + Blog/Post UX
6.2 MudSnackbar notifications styling UI
6.3 Dialog styling consistency (AuthDialog, AddressDialogs) UI
6.4 Micro-interactions — button press, card hover, page transition UI
6.5 تست کامل Dark Mode در تمام صفحات UI + QA
6.6 تست Mobile Responsive در تمام صفحات UX + QA

📈 بخش ۴: جدول تأثیرگذاری

تأثیر UI (هدف ~۵۰٪ تغییر)

حوزه تعداد فایل درصد تأثیر
Theme + CSS Variables ۲ ۱۵% (تأثیر سراسری)
حذف Inline Styles ۱۱ ۱۵%
یکسان‌سازی Elevation/Rounding ۲۰+ ۱۰%
بهبود رنگ‌بندی (CSS Variables) ۸ ۵%
Micro-interactions سراسری ۵%
جمع ~۵۰%

تأثیر UX (هدف ~۲۰٪ تغییر)

حوزه تعداد فایل درصد تأثیر
PageHeader یکپارچه ۱۲ صفحه ۸%
LoadingState واحد ۱۵+ صفحه ۴%
EmptyState واحد ۸+ صفحه ۳%
Container fixes (PackageDetail) ۲ ۲%
Routing consistency ۲ ۱%
Flow improvements ۲ ۲%
جمع ~۲۰%

🔧 بخش ۵: مشخصات فنی کامپوننت‌های جدید

۵.۱ LoadingState Component

@* Shared/LoadingState.razor *@
<MudStack AlignItems="AlignItems.Center" Class="py-16">
    <MudProgressCircular Color="Color.Primary" Indeterminate="true" Size="Size.Large" />
    @if (!string.IsNullOrWhiteSpace(Message))
    {
        <MudText Typo="Typo.body1" Class="mud-text-secondary mt-2">@Message</MudText>
    }
</MudStack>

@code {
    [Parameter] public string Message { get; set; } = "در حال بارگذاری...";
}

۵.۲ EmptyState Component

@* Shared/EmptyState.razor *@
<MudStack AlignItems="AlignItems.Center" Class="py-12" Spacing="3">
    <MudIcon Icon="@Icon" Size="Size.Large" Color="Color.Default" Class="mud-text-disabled" />
    <MudText Typo="Typo.h6" Class="mud-text-secondary">@Title</MudText>
    @if (!string.IsNullOrWhiteSpace(Description))
    {
        <MudText Typo="Typo.body2" Class="mud-text-secondary" Style="max-width:400px; text-align:center;">
            @Description
        </MudText>
    }
    @if (!string.IsNullOrWhiteSpace(ActionText))
    {
        <MudButton Variant="Variant.Filled" Color="Color.Primary" 
                   Href="@ActionHref" OnClick="@OnAction" Class="mt-2">
            @ActionText
        </MudButton>
    }
</MudStack>

@code {
    [Parameter] public string Icon { get; set; } = Icons.Material.Filled.Inbox;
    [Parameter] public string Title { get; set; } = "موردی یافت نشد";
    [Parameter] public string? Description { get; set; }
    [Parameter] public string? ActionText { get; set; }
    [Parameter] public string? ActionHref { get; set; }
    [Parameter] public EventCallback OnAction { get; set; }
}

۵.۳ PageHeader ارتقاء‌یافته

@* Shared/PageHeader.razor — ارتقاء‌یافته *@
<div class="page-header">
    <MudStack Spacing="0">
        <MudText Typo="Typo.h5">@Title</MudText>
        @if (!string.IsNullOrWhiteSpace(Subtitle))
        {
            <MudText Typo="Typo.body2" Class="mud-text-secondary">@Subtitle</MudText>
        }
    </MudStack>
    @if (!string.IsNullOrWhiteSpace(BackHref))
    {
        <MudButton Variant="Variant.Text" StartIcon="@Icons.Material.Filled.ArrowBack"
                   Href="@BackHref">بازگشت</MudButton>
    }
    else
    {
        <MudButton Variant="Variant.Text" StartIcon="@Icons.Material.Filled.ArrowBack"
                   OnClick="GoBack">بازگشت</MudButton>
    }
</div>

@code {
    [Parameter] public string Title { get; set; } = "";
    [Parameter] public string? Subtitle { get; set; }
    [Parameter] public string? BackHref { get; set; }
    
    [Inject] private IJSRuntime JS { get; set; } = default!;
    private async Task GoBack() => await JS.InvokeVoidAsync("history.back");
}

بخش ۶: چک‌لیست تکمیل هر فاز

فاز ۱ چک‌لیست:

  • CustomMudTheme.cs — Primary→#6366f1, PaletteDark اضافه شد
  • site.css — CSS Variables جدید (brand, semantic, soft, gradient)
  • Shared/LoadingState.razor — ساخته و تست شد
  • Shared/EmptyState.razor — ساخته و تست شد
  • Shared/PageHeader.razor — Subtitle parameter اضافه شد
  • .page-container CSS pattern اضافه شد
  • Build: 0 errors
  • Dark Mode: صحیح
  • Mobile: صحیح

فاز ۲ چک‌لیست:

  • Profile/Personal<PageHeader>
  • Profile/Addresses<PageHeader> + <LoadingState> + <EmptyState>
  • Profile/Wallet<PageHeader>
  • Profile/Settings<PageHeader>
  • Profile/Tree<PageHeader>
  • Profile/WithdrawalRequests<PageHeader> + <EmptyState>
  • Profile/ChangePassword<PageHeader>
  • Profile/Index → inline styles → CSS
  • Club/*<PageHeader> + <LoadingState>
  • Build: 0 errors

فاز ۳ چک‌لیست:

  • Commission/*<PageHeader> + <LoadingState>
  • Network/*<PageHeader> + <LoadingState>
  • PackageDetail → MudContainer wrapper برای loading/error
  • Checkout → Elevation fix + inline cleanup
  • WeeklyBalance → inline gradient → CSS class
  • Build: 0 errors

فاز ۴ چک‌لیست:

  • Store/Products → hero inline → CSS
  • Store/ProductDetail → image inline → CSS class
  • DiscountStore/ProductDetail → rgba → variable
  • Gateway/* → hardcoded → variable
  • Elevation یکسان‌سازی
  • Container spacing یکسان‌سازی
  • Build: 0 errors

فاز ۵ چک‌لیست:

  • Index.razor → hero inline cleanup
  • About.razor → radial-gradient cleanup
  • Blog/Index + Blog/Post → inline cleanup
  • Contact.razor + FAQ.razor → minor cleanup
  • Build: 0 errors

فاز ۶ چک‌لیست:

  • Routing fix (Categories, Blog/Post)
  • MudSnackbar styling
  • Dialog consistency
  • Dark mode full test
  • Mobile responsive full test
  • Build: 0 errors

📋 بخش ۷: خلاصه تغییرات در یک نگاه

فایل‌های تغییر‌یافته:
├── CustomMudTheme.cs              [فاز ۱] — ارتقاء کامل تم
├── site.css                       [فاز ۱-۵] — CSS Variables + class‌های جدید
├── Shared/LoadingState.razor      [فاز ۱] — جدید
├── Shared/EmptyState.razor        [فاز ۱] — جدید  
├── Shared/PageHeader.razor        [فاز ۱] — بهبود
├── Profile/* (۷ فایل)            [فاز ۲] — PageHeader + LoadingState
├── Profile/Index.razor            [فاز ۲] — حذف inline styles
├── Club/* (۲ فایل)               [فاز ۲] — PageHeader + LoadingState
├── Commission/* (۲ فایل)         [فاز ۳] — PageHeader + LoadingState + cleanup
├── Network/* (۱ فایل)            [فاز ۳] — PageHeader + LoadingState
├── PackageDetail.razor            [فاز ۳] — Container fix
├── Checkout.razor                 [فاز ۳] — Elevation + cleanup
├── Store/* (۲ فایل)              [فاز ۴] — inline → CSS
├── DiscountStore/ProductDetail    [فاز ۴] — rgba → variable
├── Gateway/* (۳ فایل)            [فاز ۴] — hardcoded → variable
├── Index.razor                    [فاز ۵] — hero cleanup
├── About.razor                    [فاز ۵] — gradient cleanup
├── Blog/* (۲ فایل)               [فاز ۵] — inline cleanup
├── Contact.razor + FAQ.razor      [فاز ۵] — minor cleanup
└── Categories + Blog/Post         [فاز ۶] — routing fix

مجموع فایل‌های تأثیرپذیر: ~۳۵ فایل
فایل‌های جدید: ۲ (LoadingState, EmptyState)
میزان تغییر UI: ~۵۰٪
میزان تغییر UX: ~۲۰٪
ریسک شکست: پایین (تغییرات تدریجی، build verification در هر فاز)