feat: Implement SMS sending functionality with KavehNegar and Rangineh providers
- Add SendSmsMessage class for encapsulating SMS message data. - Create KavehNegarProvider and RanginehProvider classes implementing SmsProviderInterface for sending SMS. - Implement SmsLogRepository and SmsTemplateRepository for managing SMS logs and templates. - Develop SendSmsHandler for handling SMS sending messages. - Create SmsService to manage SMS dispatching and logging. - Add UserProfileController for managing user profiles with CRUD operations. - Implement UserProfile entity and repository for user profile data management. - Update symfony.lock and bootstrap.php for project dependencies and environment setup.
This commit is contained in:
@@ -0,0 +1,482 @@
|
||||
# ClinicPro Admin — UI Design Specification
|
||||
> سبک بصری: Panelix Premium React Admin Dashboard
|
||||
|
||||
---
|
||||
|
||||
## 1. Design System پایه
|
||||
|
||||
### رنگبندی (Color Palette)
|
||||
|
||||
```css
|
||||
/* Primary — Purple (Panelix style) */
|
||||
--color-primary-50: #f5f3ff;
|
||||
--color-primary-100: #ede9fe;
|
||||
--color-primary-200: #ddd6fe;
|
||||
--color-primary-300: #c4b5fd;
|
||||
--color-primary-400: #a78bfa;
|
||||
--color-primary-500: #8b5cf6; /* main */
|
||||
--color-primary-600: #7c3aed;
|
||||
--color-primary-700: #6d28d9;
|
||||
--color-primary-800: #5b21b6;
|
||||
--color-primary-900: #4c1d95;
|
||||
|
||||
/* Neutrals */
|
||||
--color-gray-50: #f9fafb;
|
||||
--color-gray-100: #f3f4f6;
|
||||
--color-gray-200: #e5e7eb;
|
||||
--color-gray-300: #d1d5db;
|
||||
--color-gray-400: #9ca3af;
|
||||
--color-gray-500: #6b7280;
|
||||
--color-gray-600: #4b5563;
|
||||
--color-gray-700: #374151;
|
||||
--color-gray-800: #1f2937;
|
||||
--color-gray-900: #111827;
|
||||
|
||||
/* Status Colors */
|
||||
--color-success: #10b981;
|
||||
--color-warning: #f59e0b;
|
||||
--color-danger: #ef4444;
|
||||
--color-info: #3b82f6;
|
||||
|
||||
/* Background */
|
||||
--color-bg-body: #f1f5f9; /* light gray page bg */
|
||||
--color-bg-card: #ffffff;
|
||||
--color-bg-sidebar: #0f172a; /* dark navy sidebar */
|
||||
--color-bg-sidebar-active: rgba(139, 92, 246, 0.15);
|
||||
```
|
||||
|
||||
### تایپوگرافی
|
||||
|
||||
```
|
||||
Font Family: "Vazirmatn", "Inter", sans-serif ← فارسی + لاتین
|
||||
Direction: RTL
|
||||
|
||||
Heading 1: 28px / font-bold / gray-900
|
||||
Heading 2: 22px / font-bold / gray-900
|
||||
Heading 3: 18px / font-semibold / gray-800
|
||||
Heading 4: 16px / font-semibold / gray-700
|
||||
Body: 14px / font-normal / gray-600
|
||||
Caption: 12px / font-normal / gray-500
|
||||
Label: 12px / font-medium / gray-700 / uppercase + tracking-wide
|
||||
```
|
||||
|
||||
### Spacing & Border Radius
|
||||
|
||||
```
|
||||
Spacing scale: 4px base (4, 8, 12, 16, 20, 24, 32, 40, 48, 64)
|
||||
Border radius:
|
||||
sm: 6px (badges, chips)
|
||||
md: 10px (inputs, buttons)
|
||||
lg: 16px (cards)
|
||||
xl: 24px (modals)
|
||||
full: 9999px (avatars, toggles)
|
||||
Box shadow:
|
||||
card: 0 1px 3px rgba(0,0,0,.08), 0 1px 2px rgba(0,0,0,.06)
|
||||
modal: 0 20px 60px rgba(0,0,0,.15)
|
||||
dropdown: 0 4px 20px rgba(0,0,0,.10)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Layout Structure
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ TOPBAR (64px) │
|
||||
├────────────┬────────────────────────────────────────────┤
|
||||
│ │ │
|
||||
│ SIDEBAR │ MAIN CONTENT │
|
||||
│ (260px) │ │
|
||||
│ │ ┌──────────────────────────────────────┐ │
|
||||
│ collapsed │ │ Page Header (title + breadcrumb) │ │
|
||||
│ → 72px │ ├──────────────────────────────────────┤ │
|
||||
│ │ │ │ │
|
||||
│ │ │ Content Area (padding 24px) │ │
|
||||
│ │ │ │ │
|
||||
│ │ └──────────────────────────────────────┘ │
|
||||
└────────────┴────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Sidebar
|
||||
|
||||
### حالت باز (260px)
|
||||
|
||||
```
|
||||
┌──────────────────────────────┐
|
||||
│ ◉ ClinicPro [← collapse] │ ← logo + toggle button
|
||||
├──────────────────────────────┤
|
||||
│ 🔍 جستجوی سریع... │ ← search input
|
||||
├──────────────────────────────┤
|
||||
│ GENERAL │ ← section label (gray-500, 11px, uppercase)
|
||||
│ ◉ داشبورد │ ← active item (purple bg + purple text + bold)
|
||||
│ ○ کاربران │
|
||||
│ ○ پزشکان │
|
||||
│ ○ کلینیکها │
|
||||
├──────────────────────────────┤
|
||||
│ MANAGEMENT │
|
||||
│ ○ نوبتها [3] │ ← badge count
|
||||
│ ○ پرداختها │
|
||||
│ ○ تسویهحساب [5] │
|
||||
├──────────────────────────────┤
|
||||
│ CONTENT │
|
||||
│ ○ نظرات [12] │
|
||||
│ ○ امتیازها │
|
||||
│ ○ بلاگ │
|
||||
│ ○ پیامک │
|
||||
├──────────────────────────────┤
|
||||
│ SYSTEM │
|
||||
│ ○ دستهبندیها │
|
||||
│ ○ نمایندگان │
|
||||
│ ○ منشیها │
|
||||
├──────────────────────────────┤
|
||||
│ ┌────────────────────────┐ │
|
||||
│ │ 👤 Admin │ ← admin profile card at bottom
|
||||
│ │ admin@clinicpro.ir │
|
||||
│ │ [تنظیمات] [خروج] │
|
||||
│ └────────────────────────┘ │
|
||||
└──────────────────────────────┘
|
||||
```
|
||||
|
||||
### حالت جمعشده (72px) — Flyout on hover
|
||||
```
|
||||
┌──────┐
|
||||
│ ◉ │ ← logo icon
|
||||
├──────┤
|
||||
│ 🔍 │ ← hover → flyout search
|
||||
├──────┤
|
||||
│ ⊞ │ ← icon only, hover → flyout label + submenu
|
||||
│ 👥 │
|
||||
│ 🩺 │
|
||||
│ 🏥 │
|
||||
│ 📅 │
|
||||
│ 💳 │
|
||||
│ 🏦 │ ← badge dot (نه عدد)
|
||||
│ 💬 │ ← badge dot
|
||||
│ ⭐ │
|
||||
│ 📝 │
|
||||
│ 📱 │
|
||||
│ 🗂 │
|
||||
│ 🤝 │
|
||||
│ 🔐 │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
**رفتار sidebar:**
|
||||
- `transition: width 300ms cubic-bezier(0.4, 0, 0.2, 1)`
|
||||
- Overlay در موبایل (< 768px)
|
||||
- Active item: `bg-primary-500/15` + right border `4px solid #8b5cf6`
|
||||
- Hover item: `bg-gray-700/40`
|
||||
|
||||
---
|
||||
|
||||
## 4. Topbar
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ ≡ [Breadcrumb: داشبورد / پزشکان] 🔔 5 👤 Admin ▾ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- ارتفاع: 64px
|
||||
- پسزمینه: سفید + `box-shadow: 0 1px 0 #e5e7eb`
|
||||
- **Notification Bell:** dropdown با لیست آخرین رویدادها
|
||||
- **User Menu:** تصویر آواتار + نام + dropdown (پروفایل / تنظیمات / خروج)
|
||||
|
||||
---
|
||||
|
||||
## 5. Cards
|
||||
|
||||
### Stat Card (آمار خلاصه)
|
||||
```
|
||||
┌──────────────────────────────────┐
|
||||
│ ┌────┐ │
|
||||
│ │ 🩺 │ کل پزشکان │ ← icon در مربع رنگی (purple-100)
|
||||
│ └────┘ 1,284 │ ← عدد بزرگ (28px bold)
|
||||
│ ↑ 12% نسبت به ماه قبل │ ← trend badge (سبز/قرمز)
|
||||
└──────────────────────────────────┘
|
||||
bg: white, radius: 16px, shadow: card, padding: 24px
|
||||
```
|
||||
|
||||
### Data Card (محتوا / جداول)
|
||||
```
|
||||
┌────────────────────────────────────────────┐
|
||||
│ عنوان کارت [اقدام ▾] │ ← header
|
||||
├────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ محتوا (جدول / نمودار / فرم) │
|
||||
│ │
|
||||
└────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. DataTable (جدول داده)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ [🔍 جستجو...] [فیلتر ▾] [ستونها ▾] [صادرکردن ↓] │
|
||||
├──────────┬────────────┬──────────┬────────┬─────────────────────┤
|
||||
│ ☐ نام │ موبایل │ نقش │ وضعیت │ اقدامات │
|
||||
├──────────┼────────────┼──────────┼────────┼─────────────────────┤
|
||||
│ ☐ علی م. │ 0912*** │ پزشک │ ● فعال │ 👁 ✏️ 🗑 │
|
||||
│ ☐ سارا ح │ 0935*** │ کلینیک │ ○ غیر │ 👁 ✏️ 🗑 │
|
||||
├──────────┴────────────┴──────────┴────────┴─────────────────────┤
|
||||
│ نمایش 1-10 از 284 [← قبلی] 1 2 3 ... 29 [بعدی →] │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**ویژگیها:**
|
||||
- Sortable columns (کلیک روی header → ↑↓)
|
||||
- Row hover: `bg-gray-50`
|
||||
- Sticky header هنگام scroll
|
||||
- Loading state: skeleton rows (shimmer animation)
|
||||
- Empty state: آیکون + پیام توصیفی + دکمه اقدام
|
||||
- Bulk actions: با انتخاب checkbox ها → نوار بالا ظاهر میشود
|
||||
|
||||
---
|
||||
|
||||
## 7. Status Badges
|
||||
|
||||
```jsx
|
||||
// وضعیت نوبت
|
||||
<Badge variant="yellow">در انتظار پرداخت</Badge> /* waiting_for_payment */
|
||||
<Badge variant="blue">رزرو شده</Badge> /* reserved */
|
||||
<Badge variant="purple">ورود به مطب</Badge> /* checked_in */
|
||||
<Badge variant="orange">در صف انتظار</Badge> /* waiting */
|
||||
<Badge variant="indigo">در حال ویزیت</Badge> /* in_progress */
|
||||
<Badge variant="green">ویزیت شده</Badge> /* visited / completed */
|
||||
<Badge variant="red">لغو شده</Badge> /* cancelled_* */
|
||||
<Badge variant="gray">لغو خودکار</Badge> /* auto_cancel_unpaid */
|
||||
<Badge variant="rose">غیبت</Badge> /* no_show */
|
||||
|
||||
// وضعیت پرداخت
|
||||
<Badge variant="yellow">در انتظار</Badge> /* pending */
|
||||
<Badge variant="green">موفق</Badge> /* received */
|
||||
<Badge variant="red">لغو شده</Badge> /* canceled */
|
||||
<Badge variant="blue">استرداد</Badge> /* refund */
|
||||
|
||||
// وضعیت SMS Template
|
||||
<Badge variant="gray">پیشنویس</Badge> /* draft */
|
||||
<Badge variant="yellow">در انتظار تأیید</Badge> /* pending_approval */
|
||||
<Badge variant="green">تأیید شده</Badge> /* approved */
|
||||
<Badge variant="red">رد شده</Badge> /* rejected */
|
||||
```
|
||||
|
||||
**ساختار badge:**
|
||||
```
|
||||
padding: 2px 10px
|
||||
border-radius: 9999px
|
||||
font-size: 12px / font-medium
|
||||
با dot رنگی (●) در ابتدا
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. فرمها (Forms)
|
||||
|
||||
### Input
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ برچسب │
|
||||
│ ┌─────────────────────────────┐ │
|
||||
│ │ 🔍 placeholder... │ │ ← icon اختیاری
|
||||
│ └─────────────────────────────┘ │
|
||||
│ پیام خطا (قرمز، 12px) │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
- Border: `1px solid #d1d5db` → focus: `2px solid #8b5cf6`
|
||||
- Height input: 44px
|
||||
- Border-radius: 10px
|
||||
- Error state: border قرمز + shake animation
|
||||
- Disabled: opacity 50%
|
||||
|
||||
### Select / Dropdown
|
||||
- کتابخانه: `react-select` با استایل custom (RTL support)
|
||||
- Multi-select برای تخصصها، بیمهها، تگها
|
||||
|
||||
### Permission Matrix (منشی)
|
||||
```
|
||||
مشاهده ایجاد ویرایش حذف
|
||||
نوبتها ☑ ☑ ☐ ☐
|
||||
آدرسها ☑ ☐ ☐ ☐
|
||||
اطلاعات کلینیک ☑ — ☐ —
|
||||
بیمهها ☑ ☐ ☐ ☐
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. نمودارها (Charts)
|
||||
|
||||
### داشبورد اصلی
|
||||
```
|
||||
Row 1: [Stat Card x4] ← کاربران / پزشکان / نوبت امروز / درآمد امروز
|
||||
|
||||
Row 2: [Area Chart — درآمد ماهانه (60%)] | [Donut Chart — نوبتها بر اساس وضعیت (40%)]
|
||||
|
||||
Row 3: [Bar Chart — آمار ماهانه نمایندگان (60%)] | [لیست آخرین نوبتها (40%)]
|
||||
```
|
||||
|
||||
**کتابخانه:** `Recharts` یا `ApexCharts`
|
||||
- رنگ اصلی نمودارها: shades of purple + secondary colors
|
||||
- Tooltip: سفید با سایه، اعداد فارسی
|
||||
- X-axis: نام ماههای شمسی (فروردین ... اسفند)
|
||||
- Responsive: `<ResponsiveContainer width="100%" height={300}>`
|
||||
|
||||
---
|
||||
|
||||
## 10. Modal / Dialog
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ │ ← backdrop: rgba(0,0,0,.4)
|
||||
│ ┌────────────────────────────────────────────┐ │
|
||||
│ │ عنوان Modal ✕ │ │ ← header: border-bottom
|
||||
│ ├────────────────────────────────────────────┤ │
|
||||
│ │ │ │
|
||||
│ │ محتوا │ │
|
||||
│ │ │ │
|
||||
│ ├────────────────────────────────────────────┤ │
|
||||
│ │ [لغو] [تأیید / ذخیره] │ │ ← footer: border-top
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- انیمیشن ورود: `scale(0.95) → scale(1)` + `opacity 0 → 1` (200ms)
|
||||
- Confirm Dialog برای حذف: دکمه «حذف» قرمز + آیکون هشدار
|
||||
- Width: sm=400px / md=600px / lg=800px / xl=1000px
|
||||
|
||||
---
|
||||
|
||||
## 11. Toast Notifications
|
||||
|
||||
```
|
||||
موقعیت: top-left (RTL)
|
||||
┌─────────────────────────────────┐
|
||||
│ ✓ پزشک با موفقیت ویرایش شد. │ ← success (سبز)
|
||||
└─────────────────────────────────┘
|
||||
┌─────────────────────────────────┐
|
||||
│ ✕ خطا در ذخیره اطلاعات. │ ← error (قرمز)
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
- Auto dismiss: 4 ثانیه
|
||||
- Stack: حداکثر 3 نوتیفیکیشن همزمان
|
||||
- کتابخانه: `react-hot-toast` یا `sonner`
|
||||
|
||||
---
|
||||
|
||||
## 12. Empty States & Loading
|
||||
|
||||
### Loading (Skeleton)
|
||||
```
|
||||
┌──────────────────────────────┐
|
||||
│ ▓▓▓▓▓▓▓▓▓ ░░░░░░░░░░░ │ ← shimmer animation
|
||||
│ ░░░░░░░░░░░░░░░░░░░░░░░░ │
|
||||
│ ░░░░░░░░░░░ ▓▓▓▓▓▓▓▓▓▓ │
|
||||
└──────────────────────────────┘
|
||||
```
|
||||
- `animate-pulse` با رنگ `gray-200`
|
||||
|
||||
### Empty State
|
||||
```
|
||||
┌──────────────────────────────────┐
|
||||
│ │
|
||||
│ [SVG Illustration] │
|
||||
│ │
|
||||
│ هیچ موردی یافت نشد │
|
||||
│ توضیح کوتاه... │
|
||||
│ │
|
||||
│ [افزودن اولین مورد] │
|
||||
│ │
|
||||
└──────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 13. Page Header (هر صفحه)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ پزشکان [+ افزودن پزشک] │
|
||||
│ داشبورد / پزشکان │ ← breadcrumb
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 14. تکنولوژی Stack
|
||||
|
||||
| لایه | کتابخانه |
|
||||
|------|----------|
|
||||
| Framework | React 19 + TypeScript |
|
||||
| Routing | React Router v7 |
|
||||
| Styling | Tailwind CSS v4 |
|
||||
| State (server) | TanStack Query v5 |
|
||||
| State (client) | Zustand |
|
||||
| Forms | React Hook Form + Zod |
|
||||
| Charts | Recharts |
|
||||
| Table | TanStack Table v8 |
|
||||
| Icons | Heroicons v2 |
|
||||
| Date (Jalali) | `@date-io/date-fns-jalali` + `react-datepicker` |
|
||||
| Numbers | `react-number-format` |
|
||||
| Toast | `sonner` |
|
||||
| Select | `react-select` |
|
||||
| Rich Text | `@tiptap/react` |
|
||||
| File Upload | `react-dropzone` |
|
||||
| RTL | `dir="rtl"` + Tailwind `rtl:` variants |
|
||||
| Font | Vazirmatn (از Google Fonts یا CDN) |
|
||||
|
||||
---
|
||||
|
||||
## 15. Responsive Breakpoints
|
||||
|
||||
| نام | عرض | رفتار |
|
||||
|-----|-----|--------|
|
||||
| mobile | < 768px | Sidebar → Drawer overlay |
|
||||
| tablet | 768px–1024px | Sidebar collapsed (72px) |
|
||||
| desktop | > 1024px | Sidebar باز (260px) |
|
||||
|
||||
---
|
||||
|
||||
## 16. Dark Mode (اختیاری — فاز دوم)
|
||||
|
||||
```css
|
||||
/* با Tailwind dark: variant */
|
||||
.dark {
|
||||
--color-bg-body: #0f172a;
|
||||
--color-bg-card: #1e293b;
|
||||
--color-bg-sidebar: #0a0f1e;
|
||||
}
|
||||
```
|
||||
Toggle در topbar ← ذخیره در `localStorage`
|
||||
|
||||
---
|
||||
|
||||
## 17. نمونه رنگبندی صفحه داشبورد
|
||||
|
||||
```
|
||||
[صفحه] bg: #f1f5f9
|
||||
│
|
||||
├── Sidebar (bg: #0f172a, text: gray-400, active: purple-500)
|
||||
│
|
||||
└── Main
|
||||
├── Topbar (bg: white, border-bottom: gray-200)
|
||||
│
|
||||
└── Content (padding: 24px)
|
||||
├── [Stat Card] bg:white, icon-box: purple-100
|
||||
├── [Stat Card] bg:white, icon-box: green-100
|
||||
├── [Stat Card] bg:white, icon-box: blue-100
|
||||
└── [Stat Card] bg:white, icon-box: orange-100
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## منابع
|
||||
- طراحی مرجع: [Panelix Premium React Admin Dashboard](https://themeforest.net/item/panelix-premium-react-admin-dashboard-template/63163276)
|
||||
- فونت: [Vazirmatn](https://rastikerdar.github.io/vazirmatn/)
|
||||
- آیکون: [Heroicons](https://heroicons.com/)
|
||||
- رنگبندی: [Tailwind CSS Colors](https://tailwindcss.com/docs/customizing-colors)
|
||||
@@ -0,0 +1,446 @@
|
||||
# Admin Panel — User Flow (React)
|
||||
|
||||
---
|
||||
|
||||
## 1. Authentication
|
||||
|
||||
```
|
||||
[Login Page]
|
||||
│
|
||||
├─► Enter mobile number
|
||||
├─► Enter password
|
||||
└─► Submit
|
||||
│
|
||||
├─ Success ──► Store JWT + Refresh Token ──► Redirect to Dashboard
|
||||
└─ Fail ─────► Show error message
|
||||
```
|
||||
|
||||
**Pages:** `/login`
|
||||
**API:** `POST /api/v1/user/login`
|
||||
|
||||
---
|
||||
|
||||
## 2. Dashboard (صفحه اصلی)
|
||||
|
||||
```
|
||||
[Dashboard]
|
||||
├─► آمار کلی
|
||||
│ ├─ تعداد کل کاربران
|
||||
│ ├─ تعداد پزشکان فعال
|
||||
│ ├─ تعداد کلینیکها
|
||||
│ ├─ نوبتهای امروز
|
||||
│ ├─ پرداختهای امروز (مبلغ)
|
||||
│ ├─ تعداد نظرات در انتظار تأیید
|
||||
│ └─ تعداد درخواستهای تسویهحساب
|
||||
│
|
||||
├─► فعالیتهای اخیر
|
||||
│ ├─ آخرین نوبتهای ثبتشده
|
||||
│ ├─ آخرین پرداختها
|
||||
│ └─ آخرین کاربران ثبتنامشده
|
||||
│
|
||||
└─► نمودارها
|
||||
├─ درآمد ماهانه (Jalali)
|
||||
└─ آمار نوبتها به تفکیک وضعیت
|
||||
```
|
||||
|
||||
**Pages:** `/admin/dashboard`
|
||||
|
||||
---
|
||||
|
||||
## 3. مدیریت کاربران (User Management)
|
||||
|
||||
```
|
||||
[لیست کاربران]
|
||||
├─► جستجو (mobile, name, email)
|
||||
├─► فیلتر بر اساس role / status
|
||||
├─► صفحهبندی
|
||||
│
|
||||
├─── ردیف کاربر ──►
|
||||
│ ├─ مشاهده جزئیات ──► [صفحه پروفایل کاربر]
|
||||
│ │ ├─ اطلاعات پایه (نام، موبایل، ایمیل، نقش)
|
||||
│ │ ├─ پروفایل پزشکی (گروه خونی، بیماریها، ...)
|
||||
│ │ ├─ تاریخچه نوبتها
|
||||
│ │ └─ تاریخچه پرداختها
|
||||
│ │
|
||||
│ ├─ ویرایش اطلاعات پایه
|
||||
│ ├─ تغییر وضعیت (فعال / غیرفعال)
|
||||
│ └─ حذف کاربر ──► [Confirm Dialog]
|
||||
│
|
||||
└─── دکمه «افزودن کاربر» ──► [فرم ثبت کاربر جدید]
|
||||
```
|
||||
|
||||
**Pages:** `/admin/users`, `/admin/users/:uuid`
|
||||
**API:**
|
||||
- `GET /api/v1/users` (لیست)
|
||||
- `PATCH /api/v1/user/:id` (ویرایش)
|
||||
- `DELETE /api/v1/user/:id` (حذف)
|
||||
- `GET /api/v1/user-profile/:uuid` (پروفایل)
|
||||
|
||||
---
|
||||
|
||||
## 4. مدیریت پزشکان (Doctor Management)
|
||||
|
||||
```
|
||||
[لیست پزشکان]
|
||||
├─► فیلتر: استان / شهر / تخصص / جنسیت / درجه / وضعیت فعال
|
||||
├─► جستجو: نام / کد نظام پزشکی
|
||||
│
|
||||
├─── ردیف پزشک ──►
|
||||
│ ├─ مشاهده پروفایل ──► [صفحه پزشک]
|
||||
│ │ ├─ اطلاعات پایه + تصویر
|
||||
│ │ ├─ آدرس مطبها (لیست + نقشه)
|
||||
│ │ ├─ تخصصها و خدمات
|
||||
│ │ ├─ بیمههای پذیرفتهشده
|
||||
│ │ ├─ منشیها
|
||||
│ │ ├─ میانگین امتیاز (5 شاخص)
|
||||
│ │ └─ آمار نوبتها
|
||||
│ │
|
||||
│ ├─ ویرایش پروفایل
|
||||
│ ├─ فعال/غیرفعال کردن
|
||||
│ └─ حذف ──► [Confirm Dialog]
|
||||
│
|
||||
└─── دکمه «افزودن پزشک»
|
||||
```
|
||||
|
||||
**Pages:** `/admin/doctors`, `/admin/doctors/:uuid`
|
||||
**API:**
|
||||
- `GET /api/v1/doctors`
|
||||
- `POST /api/v1/doctor`
|
||||
- `PATCH /api/v1/doctor/:uuid`
|
||||
- `DELETE /api/v1/doctor/:uuid`
|
||||
|
||||
---
|
||||
|
||||
## 5. مدیریت کلینیکها (Clinic Management)
|
||||
|
||||
```
|
||||
[لیست کلینیکها]
|
||||
├─► فیلتر: استان / شهر / تخصص
|
||||
│
|
||||
├─── ردیف کلینیک ──►
|
||||
│ ├─ مشاهده ──► [صفحه کلینیک]
|
||||
│ │ ├─ اطلاعات + لوگو + گالری تصاویر
|
||||
│ │ ├─ ساعات کاری
|
||||
│ │ ├─ پزشکان عضو
|
||||
│ │ ├─ بیمههای پذیرفتهشده
|
||||
│ │ └─ موقعیت روی نقشه
|
||||
│ │
|
||||
│ ├─ ویرایش
|
||||
│ ├─ فعال/غیرفعال کردن
|
||||
│ └─ حذف ──► [Confirm Dialog]
|
||||
│
|
||||
└─── دکمه «افزودن کلینیک»
|
||||
```
|
||||
|
||||
**Pages:** `/admin/clinics`, `/admin/clinics/:uuid`
|
||||
|
||||
---
|
||||
|
||||
## 6. مدیریت نوبتها (Appointment Management)
|
||||
|
||||
```
|
||||
[لیست نوبتها]
|
||||
├─► فیلتر: تاریخ / پزشک / وضعیت / نماینده
|
||||
├─► جستجو: موبایل بیمار / نام پزشک
|
||||
│
|
||||
├─── ردیف نوبت ──►
|
||||
│ ├─ مشاهده جزئیات ──► [صفحه نوبت]
|
||||
│ │ ├─ اطلاعات بیمار
|
||||
│ │ ├─ اطلاعات پزشک + آدرس
|
||||
│ │ ├─ زمان نوبت
|
||||
│ │ ├─ وضعیت (با رنگبندی)
|
||||
│ │ └─ اطلاعات پرداخت
|
||||
│ │
|
||||
│ ├─ تغییر وضعیت (dropdown کامل همه stateها)
|
||||
│ └─ لغو نوبت ──► [Confirm + دلیل اختیاری]
|
||||
│
|
||||
└─── فیلتر سریع بر اساس وضعیت:
|
||||
waiting_for_payment | reserved | checked_in | waiting |
|
||||
in_progress | visited | completed | cancelled_* | no_show
|
||||
```
|
||||
|
||||
**وضعیتهای نوبت با رنگبندی:**
|
||||
| وضعیت | رنگ |
|
||||
|--------|------|
|
||||
| waiting_for_payment | زرد |
|
||||
| reserved | آبی |
|
||||
| checked_in | بنفش |
|
||||
| waiting | نارنجی |
|
||||
| in_progress | آبی تیره |
|
||||
| visited / completed | سبز |
|
||||
| cancelled_* / no_show | قرمز |
|
||||
| auto_cancel_unpaid | خاکستری |
|
||||
|
||||
**Pages:** `/admin/appointments`, `/admin/appointments/:uuid`
|
||||
|
||||
---
|
||||
|
||||
## 7. مدیریت پرداختها (Payment Management)
|
||||
|
||||
```
|
||||
[لیست پرداختها]
|
||||
├─► فیلتر: تاریخ / وضعیت / درگاه (mellat/sep)
|
||||
├─► جستجو: شماره مرجع / موبایل
|
||||
│
|
||||
├─── ردیف پرداخت ──►
|
||||
│ └─ مشاهده جزئیات ──► [صفحه پرداخت]
|
||||
│ ├─ شناسه پرداخت، مبلغ، درگاه
|
||||
│ ├─ وضعیت: pending/received/canceled/refund
|
||||
│ ├─ زمان پرداخت
|
||||
│ ├─ لینک به نوبت مرتبط
|
||||
│ └─ دکمه «استرداد» (اگر وضعیت received)
|
||||
│
|
||||
└─── آمار خلاصه بالای صفحه:
|
||||
├─ مجموع پرداختهای موفق امروز
|
||||
├─ مجموع مبلغ امروز
|
||||
└─ تعداد پرداختهای در انتظار
|
||||
```
|
||||
|
||||
**Pages:** `/admin/payments`, `/admin/payments/:uuid`
|
||||
|
||||
---
|
||||
|
||||
## 8. مدیریت تسویهحساب (Settlement Management)
|
||||
|
||||
```
|
||||
[لیست درخواستهای تسویه]
|
||||
├─► فیلتر: وضعیت (pending/approved/rejected) / نماینده
|
||||
│
|
||||
├─── ردیف تسویه ──►
|
||||
│ └─ مشاهده ──► [صفحه تسویه]
|
||||
│ ├─ نام نماینده + موجودی کیفپول
|
||||
│ ├─ مبلغ درخواستشده
|
||||
│ ├─ اطلاعات حساب بانکی (شماره کارت، بانک)
|
||||
│ ├─ تاریخ درخواست
|
||||
│ └─ اقدامات:
|
||||
│ ├─ تأیید ──► PATCH approve
|
||||
│ └─ رد کردن ──► [فرم دلیل رد] ──► PATCH reject
|
||||
│
|
||||
└─── آمار: مجموع در انتظار / تأییدشده این ماه
|
||||
```
|
||||
|
||||
**Pages:** `/admin/settlements`, `/admin/settlements/:uuid`
|
||||
|
||||
---
|
||||
|
||||
## 9. مدیریت نمایندگان (Representation Management)
|
||||
|
||||
```
|
||||
[لیست نمایندگان]
|
||||
│
|
||||
├─── ردیف نماینده ──►
|
||||
│ └─ مشاهده ──► [صفحه نماینده]
|
||||
│ ├─ اطلاعات دامنه، شهر، درصد کمیسیون
|
||||
│ ├─ حسابهای بانکی (لیست + افزودن)
|
||||
│ ├─ کیفپول: موجودی + تاریخچه تراکنشها
|
||||
│ ├─ آمار ماهانه (نمودار Jalali)
|
||||
│ └─ آمار سالانه درآمد
|
||||
│
|
||||
└─── دکمه «افزودن نماینده» ──► [فرم]
|
||||
├─ نام دامنه
|
||||
├─ شهر
|
||||
├─ درصد کمیسیون
|
||||
└─ حساب بانکی پیشفرض
|
||||
```
|
||||
|
||||
**Pages:** `/admin/representations`, `/admin/representations/:uuid`
|
||||
|
||||
---
|
||||
|
||||
## 10. مدیریت نظرات (Comment Moderation)
|
||||
|
||||
```
|
||||
[صف تأیید نظرات]
|
||||
├─► فیلتر: تأییدنشده / تأییدشده / همه
|
||||
├─► جستجو: نام پزشک / متن
|
||||
│
|
||||
├─── ردیف نظر ──►
|
||||
│ ├─ نام کاربر، نام پزشک، تاریخ
|
||||
│ ├─ عنوان و متن نظر
|
||||
│ ├─ تأیید ──► PATCH approve
|
||||
│ └─ رد / حذف ──► [Confirm Dialog]
|
||||
│
|
||||
└─── آمار: تعداد در انتظار تأیید (badge در منو)
|
||||
```
|
||||
|
||||
**Pages:** `/admin/comments`
|
||||
|
||||
---
|
||||
|
||||
## 11. مدیریت امتیازدهی (Rating Management)
|
||||
|
||||
```
|
||||
[لیست امتیازها]
|
||||
├─► فیلتر: پزشک / بازه زمانی
|
||||
│
|
||||
├─── ردیف امتیاز ──►
|
||||
│ ├─ نام بیمار، نام پزشک، تاریخ
|
||||
│ ├─ 5 شاخص (صحت تشخیص، مهارت، رفتار، نظافت، زمان انتظار)
|
||||
│ ├─ ستاره کلی
|
||||
│ └─ حذف ──► [Confirm Dialog]
|
||||
│
|
||||
└─── نمودار میانگین امتیازها به تفکیک پزشک
|
||||
```
|
||||
|
||||
**Pages:** `/admin/ratings`
|
||||
|
||||
---
|
||||
|
||||
## 12. مدیریت پیامک (SMS Management)
|
||||
|
||||
```
|
||||
[پنل SMS]
|
||||
├─► تب «قالبهای نمونه» (قالبهای ادمین)
|
||||
│ ├─ لیست قالبهای sample
|
||||
│ ├─ افزودن قالب نمونه ──► [فرم]
|
||||
│ └─ ویرایش / حذف
|
||||
│
|
||||
├─► تب «در انتظار تأیید»
|
||||
│ ├─ لیست قالبهای submitted توسط پزشکان/کلینیکها
|
||||
│ ├─── ردیف قالب ──►
|
||||
│ │ ├─ نام، دستهبندی، محتوا، ارسالکننده
|
||||
│ │ ├─ تأیید ──► PATCH approve
|
||||
│ │ └─ رد ──► [فرم دلیل رد] ──► PATCH reject
|
||||
│
|
||||
└─► تب «لاگهای ارسال»
|
||||
├─ فیلتر: وضعیت (queued/sent/failed) / provider / تاریخ
|
||||
└─ مشاهده جزئیات هر پیام
|
||||
```
|
||||
|
||||
**Pages:** `/admin/sms`
|
||||
**API:**
|
||||
- `GET /api/v1/sms/sample-templates`
|
||||
- `PATCH /api/v1/sms/templates/:uuid/approve`
|
||||
- `PATCH /api/v1/sms/templates/:uuid/reject`
|
||||
|
||||
---
|
||||
|
||||
## 13. مدیریت دستهبندیها (Categories)
|
||||
|
||||
```
|
||||
[صفحه دستهبندیها]
|
||||
├─► تببندی بر اساس نوع:
|
||||
│ ├─ استانها (state)
|
||||
│ ├─ شهرها (city) ──► وابسته به استان انتخابی
|
||||
│ ├─ تخصصها (specialty)
|
||||
│ ├─ خدمات پزشک (doctor_service)
|
||||
│ ├─ نوع بیمه (insurance_type)
|
||||
│ ├─ بیمه تکمیلی (supplementary_insurance)
|
||||
│ └─ تگهای بلاگ (tag)
|
||||
│
|
||||
└─── هر تب:
|
||||
├─ لیست با جستجو
|
||||
├─ افزودن ──► [فرم: نام، کد، parent (اگر نیاز)]
|
||||
├─ ویرایش
|
||||
└─ حذف ──► [Confirm Dialog]
|
||||
```
|
||||
|
||||
**Pages:** `/admin/categories`
|
||||
|
||||
---
|
||||
|
||||
## 14. مدیریت بلاگ (Blog Management)
|
||||
|
||||
```
|
||||
[لیست مقالات]
|
||||
├─► فیلتر: وضعیت (draft/published) / نویسنده / تگ
|
||||
│
|
||||
├─── ردیف مقاله ──►
|
||||
│ ├─ عنوان، نویسنده، تاریخ، تعداد بازدید
|
||||
│ ├─ مشاهده / ویرایش ──► [ادیتور مقاله]
|
||||
│ └─ حذف ──► [Confirm Dialog]
|
||||
│
|
||||
└─── دکمه «نوشتن مقاله» ──► [ادیتور]
|
||||
├─ عنوان، خلاصه، محتوا (Rich Text)
|
||||
├─ آپلود تصویر
|
||||
├─ انتخاب تگها
|
||||
└─ انتشار / ذخیره پیشنویس
|
||||
```
|
||||
|
||||
**Pages:** `/admin/blogs`, `/admin/blogs/new`, `/admin/blogs/:uuid/edit`
|
||||
|
||||
---
|
||||
|
||||
## 15. مدیریت منشیها (Secretary Management)
|
||||
|
||||
```
|
||||
[لیست منشیها] (کلی، همه پزشکان)
|
||||
├─► فیلتر: پزشک / وضعیت فعال
|
||||
│
|
||||
├─── ردیف منشی ──►
|
||||
│ ├─ نام، موبایل، نام پزشک
|
||||
│ ├─ مشاهده دسترسیها (JSON permissions)
|
||||
│ ├─ ویرایش دسترسیها ──► [فرم Checkboxها]
|
||||
│ │ appointments: view/create/cancel/update_status
|
||||
│ │ addresses: view/create/update/delete
|
||||
│ │ clinic_info: view/update
|
||||
│ │ insurances: view/create/update/delete
|
||||
│ ├─ فعال/غیرفعال
|
||||
│ └─ حذف ──► [Confirm Dialog]
|
||||
```
|
||||
|
||||
**Pages:** `/admin/secretaries`
|
||||
|
||||
---
|
||||
|
||||
## 16. ساختار Navigation (Sidebar)
|
||||
|
||||
```
|
||||
Sidebar
|
||||
├─ 📊 داشبورد
|
||||
├─ 👥 کاربران
|
||||
├─ 🩺 پزشکان
|
||||
├─ 🏥 کلینیکها
|
||||
├─ 📅 نوبتها
|
||||
├─ 💳 پرداختها
|
||||
├─ 🏦 تسویهحساب [badge: pending count]
|
||||
├─ 🤝 نمایندگان
|
||||
├─ 💬 نظرات [badge: pending count]
|
||||
├─ ⭐ امتیازها
|
||||
├─ 📱 پیامک
|
||||
├─ 🗂 دستهبندیها
|
||||
├─ 📝 بلاگ
|
||||
└─ 🔐 منشیها
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 17. Global Components
|
||||
|
||||
| Component | توضیح |
|
||||
|-----------|--------|
|
||||
| `<DataTable>` | جدول با sort، filter، pagination |
|
||||
| `<StatusBadge>` | نمایش وضعیت با رنگبندی |
|
||||
| `<ConfirmDialog>` | تأیید عملیات حساس |
|
||||
| `<SearchInput>` | جستجوی debounced |
|
||||
| `<FilterPanel>` | فیلترهای collapsible |
|
||||
| `<ImageUpload>` | آپلود تصویر با preview |
|
||||
| `<JalaliDatePicker>` | انتخاب تاریخ شمسی |
|
||||
| `<PersianNumber>` | نمایش اعداد فارسی |
|
||||
| `<Notification>` | Toast notifications |
|
||||
| `<PermissionCheckbox>` | ماتریس دسترسیهای منشی |
|
||||
|
||||
---
|
||||
|
||||
## 18. Auth Guard & Route Protection
|
||||
|
||||
```
|
||||
[App Router]
|
||||
├─ /login ──────────────────► PublicRoute (redirect to /admin/dashboard if logged in)
|
||||
└─ /admin/* ─────────────────► PrivateRoute
|
||||
├─ Check JWT validity
|
||||
├─ Verify ROLE_ADMIN
|
||||
├─ Auto refresh token if expired
|
||||
└─ Redirect to /login if unauthenticated
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 19. State Management پیشنهادی
|
||||
|
||||
```
|
||||
React Query (TanStack Query) ──► همه API calls (cache + refetch)
|
||||
Zustand ──► auth state، sidebar state، notification queue
|
||||
React Hook Form + Zod ──► همه فرمها با validation
|
||||
React Router v6 ──► routing
|
||||
```
|
||||
Reference in New Issue
Block a user