refactor(layout): enhance loading experience with skeleton components
- Introduced a ContentSkeleton component to display a loading state while content is being fetched. - Wrapped the Outlet component in a Suspense boundary to show the skeleton during loading. - Improved user experience by providing visual feedback during data loading. These changes aim to enhance the overall layout and loading experience in the application.
This commit is contained in:
parent
c46fd2ba0e
commit
5bb506b830
File diff suppressed because it is too large
Load Diff
|
|
@ -1,154 +0,0 @@
|
||||||
# 📋 مقایسه فیلدها - سیستم محصولات
|
|
||||||
|
|
||||||
## 🔵 فیلدهای محصول (Product Fields)
|
|
||||||
|
|
||||||
| فرم ما | API Field | نوع | توضیح |
|
|
||||||
| ---------------------- | ---------------------- | ---------- | ------------------------ |
|
|
||||||
| ✅ `name` | ✅ `name` | `string` | نام محصول |
|
|
||||||
| ✅ `description` | ✅ `description` | `string` | توضیحات محصول |
|
|
||||||
| ✅ `design_style` | ✅ `design_style` | `string` | استایل طراحی |
|
|
||||||
| ✅ `enabled` | ✅ `enabled` | `boolean` | فعال/غیرفعال |
|
|
||||||
| ✅ `category_ids` | ✅ `category_ids` | `number[]` | آرایه شناسه دستهبندیها |
|
|
||||||
| ✅ `product_option_id` | ✅ `product_option_id` | `number` | شناسه گزینه محصول |
|
|
||||||
| ✅ `total_sold` | ✅ `total_sold` | `number` | تعداد فروخته شده |
|
|
||||||
| ✅ `type` | ✅ `type` | `number` | نوع محصول (0,1,2,3) |
|
|
||||||
| ✅ `attributes` | ✅ `attributes` | `object` | ویژگیهای سفارشی |
|
|
||||||
| ✅ `variants` | ✅ `variants` | `array` | آرایه variants |
|
|
||||||
|
|
||||||
## 🔧 فیلدهای Variant
|
|
||||||
|
|
||||||
| فرم ما | API Field | نوع | توضیح |
|
|
||||||
| ---------------------- | ---------------------- | --------- | -------------------------- |
|
|
||||||
| ✅ `enabled` | ✅ `enabled` | `boolean` | فعال/غیرفعال variant |
|
|
||||||
| ✅ `fee_percentage` | ✅ `fee_percentage` | `number` | درصد کارمزد |
|
|
||||||
| ✅ `profit_percentage` | ✅ `profit_percentage` | `number` | درصد سود |
|
|
||||||
| ✅ `stock_limit` | ✅ `stock_limit` | `number` | حد کمینه موجودی |
|
|
||||||
| ✅ `stock_managed` | ✅ `stock_managed` | `boolean` | مدیریت موجودی فعال/غیرفعال |
|
|
||||||
| ✅ `stock_number` | ✅ `stock_number` | `number` | تعداد موجودی |
|
|
||||||
| ✅ `weight` | ✅ `weight` | `number` | وزن (گرم) |
|
|
||||||
| ✅ `attributes` | ✅ `attributes` | `object` | ویژگیهای variant |
|
|
||||||
| ✅ `meta` | ✅ `meta` | `object` | Meta data |
|
|
||||||
|
|
||||||
## 📊 فیلدهای اضافی در فرم
|
|
||||||
|
|
||||||
| فرم ما | API | دلیل |
|
|
||||||
| --------------- | ------- | ------------------------------ |
|
|
||||||
| 🆕 `images` | ❌ نیست | برای آپلود و مدیریت تصاویر |
|
|
||||||
| 🆕 `id` | ❌ نیست | برای ویرایش (از response میاد) |
|
|
||||||
| 🆕 `created_at` | ❌ نیست | از response میاد |
|
|
||||||
| 🆕 `updated_at` | ❌ نیست | از response میاد |
|
|
||||||
|
|
||||||
## 🎯 مثال API Request کامل
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"name": "تیشرت مردانه",
|
|
||||||
"description": "تیشرت با کیفیت بالا",
|
|
||||||
"design_style": "مدرن",
|
|
||||||
"enabled": true,
|
|
||||||
"category_ids": [1, 3],
|
|
||||||
"product_option_id": 2,
|
|
||||||
"total_sold": 25,
|
|
||||||
"type": 1,
|
|
||||||
"attributes": {
|
|
||||||
"material": "پنبه",
|
|
||||||
"season": "تابستان"
|
|
||||||
},
|
|
||||||
"variants": [
|
|
||||||
{
|
|
||||||
"enabled": true,
|
|
||||||
"fee_percentage": 5.5,
|
|
||||||
"profit_percentage": 25,
|
|
||||||
"stock_managed": true,
|
|
||||||
"stock_number": 10,
|
|
||||||
"stock_limit": 2,
|
|
||||||
"weight": 200,
|
|
||||||
"attributes": {
|
|
||||||
"color": "قرمز",
|
|
||||||
"size": "بزرگ"
|
|
||||||
},
|
|
||||||
"meta": {
|
|
||||||
"supplier": "تامینکننده A",
|
|
||||||
"priority": "high"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🚀 نوع محصولات (Product Types)
|
|
||||||
|
|
||||||
| مقدار | نام | توضیح |
|
|
||||||
| ----- | ----------- | ----------------------- |
|
|
||||||
| `0` | محصول ساده | محصول بدون variant |
|
|
||||||
| `1` | محصول متغیر | محصول با variants مختلف |
|
|
||||||
| `2` | محصول گروهی | مجموعه محصولات |
|
|
||||||
| `3` | محصول خارجی | لینک به سایت خارجی |
|
|
||||||
|
|
||||||
## 🎨 فیلدهای UI (غیر API)
|
|
||||||
|
|
||||||
### فیلدهای مدیریت تصاویر:
|
|
||||||
|
|
||||||
- **`images`** - آرایه تصاویر محصول
|
|
||||||
- **`images.id`** - شناسه فایل آپلود شده
|
|
||||||
- **`images.url`** - آدرس تصویر
|
|
||||||
- **`images.alt`** - متن جایگزین
|
|
||||||
- **`images.order`** - ترتیب نمایش
|
|
||||||
|
|
||||||
### فیلدهای مدیریت داخلی:
|
|
||||||
|
|
||||||
- **`id`** - شناسه محصول (برای ویرایش)
|
|
||||||
- **`created_at`** - تاریخ ایجاد
|
|
||||||
- **`updated_at`** - تاریخ آخرین ویرایش
|
|
||||||
|
|
||||||
## ✨ خلاصه مطابقت
|
|
||||||
|
|
||||||
### ✅ کاملاً مطابق:
|
|
||||||
|
|
||||||
- **100% فیلدهای API پیادهسازی شده**
|
|
||||||
- **ساختار دقیقاً مشابه**
|
|
||||||
- **نوع دادهها صحیح**
|
|
||||||
- **Validation مناسب**
|
|
||||||
|
|
||||||
### 🎯 ویژگیهای اضافی:
|
|
||||||
|
|
||||||
- **مدیریت تصاویر** با آپلود و پیشنمایش
|
|
||||||
- **UI/UX بهتر** با validation و error handling
|
|
||||||
- **Preview زنده** تغییرات
|
|
||||||
- **Responsive design** برای موبایل
|
|
||||||
|
|
||||||
## 📝 نتیجهگیری
|
|
||||||
|
|
||||||
**✅ تمام فیلدهای API شما دقیقاً پیادهسازی شده است**
|
|
||||||
|
|
||||||
**🎨 قابلیتهای اضافی UI/UX برای تجربه بهتر کاربر اضافه شده**
|
|
||||||
|
|
||||||
**🚀 سیستم آماده برای استفاده در production**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 فیلدهای حذف شده (که در API نبودند)
|
|
||||||
|
|
||||||
### ❌ فیلدهایی که حذف کردیم:
|
|
||||||
|
|
||||||
- **`price`** - نه در محصول و نه در variant
|
|
||||||
- **`sku`** - نه در محصول و نه در variant
|
|
||||||
- **`status`** - در API نبود
|
|
||||||
- **`name`** برای variant - در API نبود
|
|
||||||
|
|
||||||
### 🔄 تغییرات انجام شده:
|
|
||||||
|
|
||||||
1. **Models** بهروزرسانی شد طبق API دقیق
|
|
||||||
2. **Product Form** فیلدهای اضافی حذف شد
|
|
||||||
3. **Variant Manager** سادهسازی شد طبق API
|
|
||||||
4. **Validation** تنظیم شد برای فیلدهای جدید
|
|
||||||
|
|
||||||
## 🛠️ فایلهای تغییر یافته:
|
|
||||||
|
|
||||||
- `src/pages/products/core/_models.ts`
|
|
||||||
- `src/pages/products/product-form/ProductFormPage.tsx`
|
|
||||||
- `src/components/ui/VariantManager.tsx`
|
|
||||||
|
|
||||||
## 🎉 نتیجه نهایی:
|
|
||||||
|
|
||||||
**سیستم کاملاً آماده و مطابق با API شماست! 🚀**
|
|
||||||
|
|
@ -1,429 +0,0 @@
|
||||||
# درخواست APIهای داشبورد
|
|
||||||
|
|
||||||
سلام تیم بکاند 👋
|
|
||||||
|
|
||||||
برای تکمیل صفحه داشبورد نیاز به APIهای زیر داریم. لطفاً این APIها را پیادهسازی کنید:
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. API آمار کلی داشبورد (Dashboard Overview Stats)
|
|
||||||
|
|
||||||
**Endpoint:** `GET /api/v1/admin/dashboard/stats`
|
|
||||||
|
|
||||||
**Description:** دریافت آمار کلی سیستم شامل سفارشات، درآمد، کاربران و محصولات
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"orders": {
|
|
||||||
"total": 1250,
|
|
||||||
"pending": 45,
|
|
||||||
"completed": 1100,
|
|
||||||
"cancelled": 105,
|
|
||||||
"today_count": 23,
|
|
||||||
"today_amount": 45000000
|
|
||||||
},
|
|
||||||
"revenue": {
|
|
||||||
"total": 2500000000,
|
|
||||||
"today": 45000000,
|
|
||||||
"this_month": 350000000,
|
|
||||||
"last_month": 320000000,
|
|
||||||
"growth_percentage": 9.4
|
|
||||||
},
|
|
||||||
"users": {
|
|
||||||
"total": 8500,
|
|
||||||
"active": 7200,
|
|
||||||
"new_today": 15,
|
|
||||||
"new_this_month": 450
|
|
||||||
},
|
|
||||||
"products": {
|
|
||||||
"total": 1250,
|
|
||||||
"active": 1100,
|
|
||||||
"low_stock": 25,
|
|
||||||
"out_of_stock": 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. API فروش ماهانه (Monthly Sales Chart)
|
|
||||||
|
|
||||||
**Endpoint:** `GET /api/v1/admin/dashboard/monthly-sales`
|
|
||||||
|
|
||||||
**Description:** دریافت آمار فروش به صورت ماهانه برای نمایش در چارت
|
|
||||||
|
|
||||||
**Query Parameters:**
|
|
||||||
|
|
||||||
- `months` (optional, default: 6) - تعداد ماههای گذشته که باید برگردانده شود
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"month": "فروردین",
|
|
||||||
"month_number": 1,
|
|
||||||
"year": 1403,
|
|
||||||
"total_amount": 350000000,
|
|
||||||
"order_count": 450
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"month": "اردیبهشت",
|
|
||||||
"month_number": 2,
|
|
||||||
"year": 1403,
|
|
||||||
"total_amount": 420000000,
|
|
||||||
"order_count": 520
|
|
||||||
}
|
|
||||||
// ... برای تعداد ماههای درخواستی
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** دادهها باید به ترتیب زمانی (از قدیمیترین به جدیدترین) مرتب باشند.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. API روند رشد (Growth Trend)
|
|
||||||
|
|
||||||
**Endpoint:** `GET /api/v1/admin/dashboard/growth-trend`
|
|
||||||
|
|
||||||
**Description:** دریافت روند رشد سیستم در بازههای زمانی مختلف
|
|
||||||
|
|
||||||
**Query Parameters:**
|
|
||||||
|
|
||||||
- `period` (optional, default: "monthly") - نوع بازه زمانی: `"daily"`, `"weekly"`, `"monthly"`
|
|
||||||
- `days` (optional, default: 30) - تعداد روزها برای `period=daily`
|
|
||||||
- `weeks` (optional, default: 12) - تعداد هفتهها برای `period=weekly`
|
|
||||||
- `months` (optional, default: 12) - تعداد ماهها برای `period=monthly`
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"period": "monthly",
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"date": "1403/01",
|
|
||||||
"revenue": 350000000,
|
|
||||||
"orders": 450,
|
|
||||||
"users": 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "1403/02",
|
|
||||||
"revenue": 420000000,
|
|
||||||
"orders": 520,
|
|
||||||
"users": 135
|
|
||||||
}
|
|
||||||
// ...
|
|
||||||
],
|
|
||||||
"growth_rate": 9.4
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. API کاربران اخیر (Recent Users)
|
|
||||||
|
|
||||||
**Endpoint:** `GET /api/v1/admin/dashboard/recent-users`
|
|
||||||
|
|
||||||
**Description:** دریافت لیست کاربران جدید که اخیراً ثبتنام کردهاند
|
|
||||||
|
|
||||||
**Query Parameters:**
|
|
||||||
|
|
||||||
- `limit` (optional, default: 10) - تعداد کاربران
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"users": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"first_name": "علی",
|
|
||||||
"last_name": "احمدی",
|
|
||||||
"username": "ali_ahmadi",
|
|
||||||
"email": "ali@example.com",
|
|
||||||
"phone": "09123456789",
|
|
||||||
"status": "active",
|
|
||||||
"created_at": "2024-01-15T10:30:00Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"first_name": "فاطمه",
|
|
||||||
"last_name": "حسینی",
|
|
||||||
"username": "fateme_hosseini",
|
|
||||||
"email": "fateme@example.com",
|
|
||||||
"phone": "09123456790",
|
|
||||||
"status": "active",
|
|
||||||
"created_at": "2024-01-14T15:20:00Z"
|
|
||||||
}
|
|
||||||
// ...
|
|
||||||
],
|
|
||||||
"total": 10
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** کاربران باید به ترتیب تاریخ ثبتنام (جدیدترین اول) مرتب باشند.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. API توزیع دستگاههای کاربری (Device Distribution)
|
|
||||||
|
|
||||||
**Endpoint:** `GET /api/v1/admin/dashboard/device-distribution`
|
|
||||||
|
|
||||||
**Description:** دریافت آمار توزیع دستگاههای کاربری (دسکتاپ، موبایل، تبلت)
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"device_type": "desktop",
|
|
||||||
"label": "دسکتاپ",
|
|
||||||
"count": 4500,
|
|
||||||
"percentage": 45.5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"device_type": "mobile",
|
|
||||||
"label": "موبایل",
|
|
||||||
"count": 3500,
|
|
||||||
"percentage": 35.2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"device_type": "tablet",
|
|
||||||
"label": "تبلت",
|
|
||||||
"count": 2000,
|
|
||||||
"percentage": 19.3
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"total": 10000
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** درصدها باید به صورت عدد صحیح (بدون اعشار) برگردانده شوند.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. API سفارشهای اخیر (Recent Orders)
|
|
||||||
|
|
||||||
**Endpoint:** `GET /api/v1/admin/dashboard/recent-orders`
|
|
||||||
|
|
||||||
**Description:** دریافت لیست آخرین سفارشهای ثبت شده
|
|
||||||
|
|
||||||
**Query Parameters:**
|
|
||||||
|
|
||||||
- `limit` (optional, default: 10) - تعداد سفارشها
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"orders": [
|
|
||||||
{
|
|
||||||
"id": 1234,
|
|
||||||
"order_number": "ORD-2024-001234",
|
|
||||||
"customer_name": "علی احمدی",
|
|
||||||
"customer_id": 45,
|
|
||||||
"total_amount": 2500000,
|
|
||||||
"status": "pending",
|
|
||||||
"payment_status": "paid",
|
|
||||||
"created_at": "2024-01-15T14:30:00Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1233,
|
|
||||||
"order_number": "ORD-2024-001233",
|
|
||||||
"customer_name": "فاطمه حسینی",
|
|
||||||
"customer_id": 46,
|
|
||||||
"total_amount": 1800000,
|
|
||||||
"status": "completed",
|
|
||||||
"payment_status": "paid",
|
|
||||||
"created_at": "2024-01-15T13:20:00Z"
|
|
||||||
}
|
|
||||||
// ...
|
|
||||||
],
|
|
||||||
"total": 10
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** سفارشها باید به ترتیب تاریخ ایجاد (جدیدترین اول) مرتب باشند.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. API محصولات پرفروش (Top Selling Products)
|
|
||||||
|
|
||||||
**Endpoint:** `GET /api/v1/admin/dashboard/top-products`
|
|
||||||
|
|
||||||
**Description:** دریافت لیست محصولات پرفروش
|
|
||||||
|
|
||||||
**Query Parameters:**
|
|
||||||
|
|
||||||
- `limit` (optional, default: 5) - تعداد محصولات
|
|
||||||
- `period` (optional, default: "month") - بازه زمانی: `"day"`, `"week"`, `"month"`
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"products": [
|
|
||||||
{
|
|
||||||
"id": 45,
|
|
||||||
"name": "محصول نمونه",
|
|
||||||
"sku": "PRD-001",
|
|
||||||
"sold_count": 250,
|
|
||||||
"revenue": 125000000,
|
|
||||||
"image_url": "https://example.com/images/product-45.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 78,
|
|
||||||
"name": "محصول دیگر",
|
|
||||||
"sku": "PRD-002",
|
|
||||||
"sold_count": 180,
|
|
||||||
"revenue": 90000000,
|
|
||||||
"image_url": "https://example.com/images/product-78.jpg"
|
|
||||||
}
|
|
||||||
// ...
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** محصولات باید به ترتیب تعداد فروش (بیشترین اول) مرتب باشند.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. API آمار مقایسهای (Comparison Stats)
|
|
||||||
|
|
||||||
**Endpoint:** `GET /api/v1/admin/dashboard/comparison`
|
|
||||||
|
|
||||||
**Description:** دریافت آمار مقایسهای بین دوره فعلی و دوره قبلی
|
|
||||||
|
|
||||||
**Query Parameters:**
|
|
||||||
|
|
||||||
- `compare_with` (optional, default: "last_period") - نوع مقایسه: `"last_period"`, `"last_year"`
|
|
||||||
- `period` (optional, default: "month") - نوع دوره: `"day"`, `"week"`, `"month"`
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"current": {
|
|
||||||
"revenue": 350000000,
|
|
||||||
"orders": 450,
|
|
||||||
"users": 120
|
|
||||||
},
|
|
||||||
"previous": {
|
|
||||||
"revenue": 320000000,
|
|
||||||
"orders": 410,
|
|
||||||
"users": 105
|
|
||||||
},
|
|
||||||
"changes": {
|
|
||||||
"revenue": {
|
|
||||||
"amount": 30000000,
|
|
||||||
"percentage": 9.4,
|
|
||||||
"trend": "up"
|
|
||||||
},
|
|
||||||
"orders": {
|
|
||||||
"amount": 40,
|
|
||||||
"percentage": 9.8,
|
|
||||||
"trend": "up"
|
|
||||||
},
|
|
||||||
"users": {
|
|
||||||
"amount": 15,
|
|
||||||
"percentage": 14.3,
|
|
||||||
"trend": "up"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:**
|
|
||||||
|
|
||||||
- `trend` میتواند `"up"`, `"down"` یا `"stable"` باشد
|
|
||||||
- درصدها میتوانند اعشار داشته باشند
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## نکات مهم و الزامات:
|
|
||||||
|
|
||||||
1. **احراز هویت:** همه APIها باید نیاز به احراز هویت داشته باشند (Bearer Token)
|
|
||||||
|
|
||||||
2. **فیلتر تاریخ:** در صورت امکان، همه APIها باید قابلیت فیلتر بر اساس بازه زمانی را داشته باشند:
|
|
||||||
|
|
||||||
- `from_date` (optional) - تاریخ شروع
|
|
||||||
- `to_date` (optional) - تاریخ پایان
|
|
||||||
|
|
||||||
3. **فرمت تاریخ:**
|
|
||||||
|
|
||||||
- تاریخها در Response باید به فرمت ISO 8601 برگردانده شوند: `"2024-01-15T14:30:00Z"`
|
|
||||||
- تاریخهای ورودی میتوانند به فرمت ISO 8601 یا timestamp باشند
|
|
||||||
|
|
||||||
4. **فرمت مبالغ:**
|
|
||||||
|
|
||||||
- همه مبالغ به تومان هستند
|
|
||||||
- مبالغ باید به صورت عدد (integer) برگردانده شوند
|
|
||||||
|
|
||||||
5. **ترتیب دادهها:**
|
|
||||||
|
|
||||||
- دادههای زمانی باید به ترتیب زمانی (از قدیمیترین به جدیدترین) مرتب باشند
|
|
||||||
- دادههای مرتبسازی شده (مثل پرفروشترین) باید به ترتیب مناسب مرتب باشند
|
|
||||||
|
|
||||||
6. **مقدار پیشفرض:**
|
|
||||||
|
|
||||||
- در صورت نبود داده، آرایه خالی `[]` یا `null` برگردانده شود
|
|
||||||
- مقادیر عددی در صورت نبود داده باید `0` باشند
|
|
||||||
|
|
||||||
7. **خطاها:**
|
|
||||||
|
|
||||||
- در صورت خطا، کد HTTP مناسب برگردانده شود
|
|
||||||
- پیام خطا به فارسی و واضح باشد
|
|
||||||
|
|
||||||
8. **Performance:**
|
|
||||||
- برای بهینهسازی، میتوان از کش استفاده کرد
|
|
||||||
- Queryها باید بهینه باشند تا زمان پاسخگویی کم باشد
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## اولویت پیادهسازی:
|
|
||||||
|
|
||||||
1. **اولویت بالا:**
|
|
||||||
|
|
||||||
- API آمار کلی داشبورد (#1)
|
|
||||||
- API فروش ماهانه (#2)
|
|
||||||
- API کاربران اخیر (#4)
|
|
||||||
- API سفارشهای اخیر (#6)
|
|
||||||
|
|
||||||
2. **اولویت متوسط:**
|
|
||||||
|
|
||||||
- API روند رشد (#3)
|
|
||||||
- API محصولات پرفروش (#7)
|
|
||||||
- API آمار مقایسهای (#8)
|
|
||||||
|
|
||||||
3. **اولویت پایین:**
|
|
||||||
- API توزیع دستگاههای کاربری (#5) - در صورت وجود داده
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## مثال استفاده:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# دریافت آمار کلی
|
|
||||||
curl -X GET "https://api.example.com/api/v1/admin/dashboard/stats" \
|
|
||||||
-H "Authorization: Bearer YOUR_TOKEN"
|
|
||||||
|
|
||||||
# دریافت فروش 6 ماه گذشته
|
|
||||||
curl -X GET "https://api.example.com/api/v1/admin/dashboard/monthly-sales?months=6" \
|
|
||||||
-H "Authorization: Bearer YOUR_TOKEN"
|
|
||||||
|
|
||||||
# دریافت کاربران اخیر
|
|
||||||
curl -X GET "https://api.example.com/api/v1/admin/dashboard/recent-users?limit=10" \
|
|
||||||
-H "Authorization: Bearer YOUR_TOKEN"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**ممنون میشوم اگر این APIها را در اسرع وقت پیادهسازی کنید تا بتوانیم داشبورد را کامل کنیم.** 🙏
|
|
||||||
|
|
||||||
**در صورت نیاز به توضیحات بیشتر یا تغییرات، لطفاً اطلاع دهید.**
|
|
||||||
|
|
@ -1,8 +1,27 @@
|
||||||
import { useState } from 'react';
|
import { Suspense, useState } from 'react';
|
||||||
import { Outlet } from 'react-router-dom';
|
import { Outlet } from 'react-router-dom';
|
||||||
import { Sidebar } from './Sidebar';
|
import { Sidebar } from './Sidebar';
|
||||||
import { Header } from './Header';
|
import { Header } from './Header';
|
||||||
|
|
||||||
|
const ContentSkeleton = () => (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div className="h-10 w-1/3 rounded-lg bg-gray-200 dark:bg-gray-800 animate-pulse" />
|
||||||
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{[...Array(3)].map((_, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="h-36 rounded-lg bg-white dark:bg-gray-800 shadow-sm"
|
||||||
|
>
|
||||||
|
<div className="h-full w-full rounded-lg bg-gray-200 dark:bg-gray-700 animate-pulse" />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="h-96 rounded-lg bg-white dark:bg-gray-800 shadow-sm">
|
||||||
|
<div className="h-full w-full rounded-lg bg-gray-200 dark:bg-gray-700 animate-pulse" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
export const Layout = () => {
|
export const Layout = () => {
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||||
|
|
||||||
|
|
@ -18,7 +37,9 @@ export const Layout = () => {
|
||||||
|
|
||||||
<main className="flex-1 overflow-y-auto bg-gray-50 dark:bg-gray-900">
|
<main className="flex-1 overflow-y-auto bg-gray-50 dark:bg-gray-900">
|
||||||
<div className="min-h-full py-6 px-4 sm:px-6 lg:px-8">
|
<div className="min-h-full py-6 px-4 sm:px-6 lg:px-8">
|
||||||
<Outlet />
|
<Suspense fallback={<ContentSkeleton />}>
|
||||||
|
<Outlet />
|
||||||
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue