# راهنمای قدمبهقدم صفحات پنل ادمین — فاز ۱ (زیرساخت + صفحهٔ نوبتها) ## پروژه `clinicpro` — پنل ادمین React داخل `assets/admin/`. ## زمینه پنل ادمین حدود ۵۰ صفحه دارد و هیچ راهنمای درونبرنامهای ندارد. کاربر تازهوارد نمیداند هر بخش صفحه چه کار میکند. تصمیم گرفته شد راهنما به شکل **تور قدمبهقدم** باشد. یعنی المانها یکییکی highlight میشوند و کنارشان یک popover فارسی توضیح میدهد. این فایل فقط **فاز ۱** است. فاز ۱ = زیرساخت تور + پیادهسازی روی یک صفحهٔ نمونه. صفحهٔ نمونه: `AppointmentsPage`. دلیل انتخابش: شلوغترین صفحهٔ پنل است و المانهای نقشمحور دارد. بعد از تأیید ظاهر و رفتار تور، فاز ۲ نوشته میشود که همین الگو را روی بقیهٔ صفحات تکرار میکند. **در این فاز هیچ صفحهٔ دیگری را دست نزن.** ## مشکل / هدف هدف: - یک زیرساخت واحد برای تعریف تور هر صفحه. - تعریف تور بهصورت داده باشد، نه کد پراکنده در صفحات. - المانهای هدف با اتریبیوت `data-tour` مشخص شوند. - استپی که المانش در DOM نیست بیسروصدا حذف شود، نه اینکه تور بشکند. - بار اول ورود کاربر به صفحه، تور خودکار اجرا شود. - بعد از دیدن، دیگر خودکار اجرا نشود؛ ولی با یک دکمهٔ `؟` قابل اجرای دوباره باشد. - محتوای تور نسخهدار باشد؛ با بالا بردن نسخه، تور دوباره یکبار خودکار اجرا شود. ## تصمیم فنی — چرا driver.js سه گزینه بررسی شد: - `react-joyride` — سنگینتر و روی React 19 مشکوک است. `react-floater` هنوز peer آن React 18 است. - کامپوننت دستساز — منطق overlay و اسکرول و resize و sticky header باید از صفر نوشته شود. کد زیاد و باگخیز. - `driver.js` نسخهٔ ۱ — بدون dependency، حدود ۵ کیلوبایت gzip، مستقل از فریمورک، خودش overlay و اسکرول و reposition را دارد. انتخاب: **`driver.js`**. استایلش با توکنهای `styles.css` override میشود تا با تم روشن و تیره یکی شود. راستچین بودن مشکلی ندارد چون ریشهٔ اپ `dir="rtl"` است. نصب: ```bash ddev exec npm install driver.js@^1.3.6 ``` ## معیار پذیرش - ✅ موفق: ورود با `09390039833` به `/admin/appointments` برای اولین بار → تور خودکار اجرا میشود. متنها فارسیاند. شمارنده «۱ از N» است. دکمهها «بعدی / قبلی / باشه، فهمیدم». بعد از پایان، در `localStorage['clinicpro-tours']` کلید `seen.appointments` برابر نسخهٔ تور میشود. رفرش صفحه → تور دیگر خودکار اجرا نمیشود. کلیک روی دکمهٔ `؟` کنار عنوان → تور دوباره از استپ اول اجرا میشود. - ❌ خطا: `useTour('does-not-exist')` → هیچ دکمهای رندر نمیشود، هیچ خطایی throw نمیشود و تور اجرا نمیشود. همچنین اگر هیچکدام از المانهای تور در DOM نباشد، `start()` هیچ کاری نمیکند و crash نمیدهد. - ⚠️ مرزی: ورود با نقش `doctor` که تب پزشکان ندارد، و منشیِ بدون مجوز `appointments.create` که دکمهٔ «افزودن نوبت» ندارد → استپهای مربوط به آن المانها حذف میشوند، تور با استپهای کمتر اجرا میشود و شمارنده درست است، مثلاً «۱ از ۵» نه «۱ از ۷». همچنین بالا بردن `version` تور → یکبار دیگر خودکار اجرا میشود. ## فایلهای مرتبط | فایل | نقش | |------|-----| | `assets/admin/lib/tour/types.ts` | جدید — تعریف تایپ استپ و تور | | `assets/admin/lib/tour/resolveSteps.ts` | جدید — تابع خالص فیلتر استپها بر اساس وجود المان | | `assets/admin/lib/tour/registry.ts` | جدید — رجیستری تورها بر اساس id | | `assets/admin/lib/tour/tours/appointments.ts` | جدید — تعریف تور صفحهٔ نوبتها | | `assets/admin/stores/tourStore.ts` | جدید — zustand persist برای تورهای دیدهشده | | `assets/admin/hooks/useTour.ts` | جدید — اجرای تور و اجرای خودکار بار اول | | `assets/admin/components/ui/TourButton.tsx` | جدید — دکمهٔ `؟` راهنمای صفحه | | `assets/admin/components/ui/PageHeader.tsx` | تغییر — پراپ اختیاری `tourId` | | `assets/admin/pages/AppointmentsPage.tsx` | تغییر — افزودن `data-tour` و دکمهٔ راهنما | | `assets/admin/styles.css` | تغییر — override استایل popover با توکنها | | `package.json` | تغییر — افزودن `driver.js` | ## وضعیت فعلی `PageHeader` هیچ جای راهنما ندارد. کد فعلی: ```tsx interface Props { title: string; breadcrumbs?: Crumb[]; action?: React.ReactNode; description?: string; backTo?: string; } export default function PageHeader({ title, breadcrumbs, action, description, backTo }: Props) { ...