# جریان کاربری — تسک ۱۶: داشبورد هوشمند ## جریان انتخاب بازه زمانی ``` کاربر وارد صفحه داشبورد می‌شود │ ▼ بازه پیش‌فرض: «این ماه» from = اول ماه جاری (شمسی → Unix) to = now GET /api/v1/dashboard/clinic?from=UNIX&to=UNIX │ ▼ کاربر روی preset کلیک می‌کند: [این هفته] [این ماه] [۳ ماه] [سفارشی] │ ▼ انتخاب «سفارشی»: PersianCalendar range picker باز می‌شود کاربر از/تا را انتخاب می‌کند │ ▼ URL update: ?from=UNIX&to=UNIX TanStack Query refetch می‌شود ``` ## جریان نمایش داشبورد کلینیک/مطب ``` ┌──────────────────────────────────────────────────────────────┐ │ داشبورد کلینیک │ │ [این هفته] [این ماه ★] [۳ ماه] [سفارشی] │ ├──────────┬──────────┬──────────┬──────────────────────────── │ │ نوبت‌های │ بیماران │ درآمد │ موجودی پیامک │ │ امروز: ۸ │ منحصربه │ این ماه │ ۱۵۰,۰۰۰ ریال │ │ │ فرد: ۴۵ │ ۱۲.۵M │ │ ├──────────┴──────────┴──────────┴──────────────────────────── │ │ نمودار نوبت‌ها — این ماه │ │ ┌────────────────────────────────────────────────────────┐ │ │ │ ▄ ▄ ▄ ▄ │ │ │ │ ▄ ▄ ▄ ▄ ▄ ▄ ▄ ▄ ▄ ▄ ▄ │ │ │ │ ────────────────────────────────────── روز │ │ │ └────────────────────────────────────────────────────────┘ │ ├──────────────────────────────────────────────────────────── │ │ نمودار درآمد — این ماه │ │ ┌────────────────────────────────────────────────────────┐ │ │ │ █ █ █ █ │ │ │ │ █ █ █ █ █ █ █ █ █ │ │ │ └────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────┘ ``` ## جریان داشبورد ادمین ``` GET /api/v1/admin/dashboard/stats → کارت‌های آمار کلی GET /api/v1/admin/dashboard/charts?from=UNIX&to=UNIX → نمودارها نمودار اضافه: «فروش اشتراک بر اساس پنل» basic: ۱۵ فروش | professional: ۵ فروش (Bar chart با رنگ‌بندی متفاوت برای هر plan) ``` ## فیلتر نقش — منشی ``` منشی وارد داشبورد می‌شود → فقط آمار نوبت‌ها نمایش داده می‌شود → فیلد درآمد: مخفی → فیلد بیماران: مخفی (اگر پنل Basic+ نباشد) → موجودی پیامک: مخفی ``` ## preset ها — محاسبه از/تا ```typescript function getDateRange(preset: DateRangePreset): DateRange { const now = Math.floor(Date.now() / 1000); switch (preset) { case 'week': // شنبه این هفته const dayOfWeek = new Date().getDay(); // 0=یکشنبه ... 6=شنبه const daysToSaturday = dayOfWeek === 6 ? 0 : dayOfWeek + 1; return { from: now - daysToSaturday * 86400, to: now }; case 'month': // اول ماه جاری شمسی → Unix timestamp // از PersianCalendar helper استفاده می‌شود return { from: startOfCurrentPersianMonth(), to: now }; case '3months': return { from: now - 90 * 86400, to: now }; } } ```