feat(tour): add onboarding tours for various admin pages

- Integrated TourButton component into SettingsMenuPage, SkillsPage, SmsWalletPage, StaffPage, StaffSessionDetailPage, StaffTreatmentSessionsPage, SubscriptionPage, TagsSettingsPage, TreatmentCasesPage to enhance user onboarding experience.
- Created new tour definitions for appointments, clinics, staff management, financial management, and patient management, ensuring comprehensive guidance for users navigating the admin panel.
- Updated documentation to reflect the addition of tours and their implementation details.
This commit is contained in:
hamed
2026-08-10 10:10:20 +03:30
parent 20c8eaaad9
commit ecdefa3c24
73 changed files with 1008 additions and 76 deletions
+90 -3
View File
@@ -1,10 +1,97 @@
import type { TourDefinition } from './types';
import { appointmentsTour } from './tours/appointments';
import { appointmentDetailTour, reserveAppointmentsTour } from './tours/appointmentsMore';
import { appointmentCreateTour, appointmentEditTour, patientDetailTour } from './tours/patientDetail';
import { myPatientRecordTour, myPatientsTour } from './tours/myPatients';
import { patientsTour } from './tours/patients';
import {
claimDetailTour, claimsTour, discountsTour, insurancePricingTour, myFinancialTour,
myPaymentDetailTour, myPaymentsTour, smsWalletTour, subscriptionTour,
} from './tours/financial';
import {
clinicServicesTour, inventoryTour, resourceDetailTour, resourcePoolsTour, resourceSkillsTour,
resourceTypesTour, resourcesTour, serviceCategoriesTour, serviceDetailTour, treatmentCasesTour,
} from './tours/services';
import {
accountSettingsTour, appointmentSettingsTour, clinicAppointmentSettingsTour, clinicDoctorsTour,
holidaysTour, practiceDomainTour, recordNumberSettingsTour, settingsMenuTour, tagsSettingsTour,
} from './tours/settings';
import {
clinicDetailTour, clinicsTour, dashboardTour, doctorDetailTour, doctorFormTour, doctorsTour,
mySecretariesTour, secretaryEarningsTour, secretarySettlementTour, staffSessionDetailTour,
staffSessionsTour, staffTour,
} from './tours/clinicStaff';
import {
patientRecordFormTour, representationBlogFormTour, representationBlogsTour,
representationFinanceTour, representationProfileTour, representationSettlementTour,
sessionEditTour, sessionNewTour, sessionPaymentTour,
} from './tours/sessionsAndRepresentation';
/** هر صفحه تور خودش را در tours/ دارد و فقط اینجا ثبت می‌شود. */
export const TOURS: Record<string, TourDefinition> = {
[appointmentsTour.id]: appointmentsTour,
};
const ALL: TourDefinition[] = [
appointmentsTour,
appointmentDetailTour,
reserveAppointmentsTour,
appointmentCreateTour,
appointmentEditTour,
patientsTour,
patientDetailTour,
myPatientsTour,
myPatientRecordTour,
myPaymentsTour,
myPaymentDetailTour,
myFinancialTour,
claimsTour,
claimDetailTour,
insurancePricingTour,
discountsTour,
subscriptionTour,
smsWalletTour,
clinicServicesTour,
serviceDetailTour,
serviceCategoriesTour,
resourcesTour,
resourceTypesTour,
resourcePoolsTour,
resourceSkillsTour,
resourceDetailTour,
inventoryTour,
treatmentCasesTour,
settingsMenuTour,
accountSettingsTour,
tagsSettingsTour,
recordNumberSettingsTour,
appointmentSettingsTour,
clinicAppointmentSettingsTour,
holidaysTour,
practiceDomainTour,
clinicDoctorsTour,
dashboardTour,
clinicsTour,
clinicDetailTour,
doctorsTour,
doctorDetailTour,
doctorFormTour,
mySecretariesTour,
staffTour,
staffSessionsTour,
staffSessionDetailTour,
secretaryEarningsTour,
secretarySettlementTour,
sessionNewTour,
sessionEditTour,
sessionPaymentTour,
patientRecordFormTour,
representationBlogsTour,
representationBlogFormTour,
representationFinanceTour,
representationProfileTour,
representationSettlementTour,
];
export const TOURS: Record<string, TourDefinition> = Object.fromEntries(
ALL.map((tour) => [tour.id, tour]),
);
export function getTour(id?: string): TourDefinition | null {
return id ? TOURS[id] ?? null : null;
+46
View File
@@ -59,4 +59,50 @@ describe('registry', () => {
expect(new Set(anchors).size).toBe(anchors.length);
}
});
it('متن هر استپ فارسی و غیرخالی است', () => {
for (const tour of Object.values(TOURS)) {
for (const step of tour.steps) {
expect(step.title.trim().length).toBeGreaterThan(2);
expect(step.body.trim().length).toBeGreaterThan(10);
// متن راهنما برای کاربر فارسی‌زبان است؛ استپِ انگلیسی‌مانده یعنی جا افتاده.
expect(step.title).toMatch(/[؀-ۿ]/);
expect(step.body).toMatch(/[؀-ۿ]/);
}
}
});
});
/**
* لنگرِ بی‌المان بی‌صدا حذف می‌شود، پس تورِ خراب هیچ خطایی نمی‌دهد و فقط استپش را
* از دست می‌دهد. این تست همان سکوت را می‌شکند: هر anchor باید در کدِ صفحات وجود
* داشته باشد.
*/
describe('انطباق لنگرها با کد صفحات', () => {
it('هیچ استپی به data-tour ناموجود اشاره نمی‌کند', async () => {
// خواندن مستقیم فایل‌ها، نه import.meta.glob: آن فقط زیر Vite کار می‌کند و
// ts-loaderِ Encore همین فایل را هم type-check می‌کند و build را قرمز می‌کرد.
const { readdirSync, readFileSync } = await import('node:fs');
const { join } = await import('node:path');
const walk = (dir: string): string[] =>
readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
const path = join(dir, entry.name);
if (entry.isDirectory()) return walk(path);
return entry.name.endsWith('.tsx') && !entry.name.includes('.test.') ? [path] : [];
});
const sources = walk('assets/admin').map((path) => readFileSync(path, 'utf8'));
const declared = new Set(
sources.flatMap((src) => [...src.matchAll(/data-tour="([a-z0-9-]+)"/g)].map((m) => m[1])),
);
expect(declared.size).toBeGreaterThan(0);
const orphans = Object.values(TOURS).flatMap((tour) =>
tour.steps.filter((s) => !declared.has(s.anchor)).map((s) => `${tour.id}:${s.anchor}`),
);
expect(orphans).toEqual([]);
});
});
@@ -0,0 +1,57 @@
import type { TourDefinition } from '../types';
export const appointmentDetailTour: TourDefinition = {
id: 'appointment-detail',
version: 1,
steps: [
{
anchor: 'appt-patient',
title: 'اطلاعات نوبت',
body: 'نام بیمار، پزشک، خدمت، ساعت و هزینهٔ همین نوبت.',
side: 'bottom',
},
{
anchor: 'appt-status',
title: 'وضعیت و اقدامات',
body: 'وضعیت فعلی نوبت را از اینجا عوض کنید — مثلاً تأیید، حضور بیمار یا لغو.',
side: 'bottom',
},
{
anchor: 'appt-events',
title: 'تاریخچهٔ رویدادها',
body: 'هر تغییر وضعیت با زمان و عاملش ثبت می‌شود؛ برای پیگیری اختلاف مفید است.',
side: 'top',
},
],
};
export const reserveAppointmentsTour: TourDefinition = {
id: 'appointments-reserve',
version: 1,
steps: [
{
anchor: 'page-title',
title: 'نوبت‌های رزرو شده',
body: 'نوبت‌هایی که بیرون از تقویم عادی و به‌صورت دستی رزرو شده‌اند.',
side: 'bottom',
},
{
anchor: 'reserve-doctor',
title: 'انتخاب پزشک',
body: 'در کلینیک، اول پزشک را انتخاب کنید تا نوبت‌های رزروش بیاید.',
side: 'bottom',
},
{
anchor: 'reserve-new',
title: 'نوبت رزرو جدید',
body: 'تا وقتی پزشکی انتخاب نشده، این دکمه غیرفعال است.',
side: 'bottom',
},
{
anchor: 'reserve-list',
title: 'فهرست رزروها',
body: 'هر ردیف یک نوبت رزروشده با بیمار و زمان آن.',
side: 'top',
},
],
};
+105
View File
@@ -0,0 +1,105 @@
import type { TourDefinition } from '../types';
export const dashboardTour: TourDefinition = {
id: 'dashboard',
version: 1,
steps: [
{ anchor: 'page-title', title: 'داشبورد', body: 'خلاصهٔ امروز: نوبت‌ها، درآمد، بیماران و کارهای در انتظار.', side: 'bottom' },
],
};
export const clinicsTour: TourDefinition = {
id: 'clinics',
version: 1,
steps: [
{ anchor: 'page-title', title: 'کلینیک‌ها', body: 'کلینیک‌هایی که به آن‌ها دسترسی دارید.', side: 'bottom' },
{ anchor: 'page-pagination', title: 'صفحه‌بندی', body: 'تعداد کل و جابه‌جایی بین صفحه‌ها.', side: 'top' },
],
};
export const clinicDetailTour: TourDefinition = {
id: 'clinic-detail',
version: 1,
steps: [
{ anchor: 'page-title', title: 'پروندهٔ کلینیک', body: 'اطلاعات، آدرس، تصاویر و تنظیمات این کلینیک.', side: 'bottom' },
],
};
export const doctorsTour: TourDefinition = {
id: 'doctors',
version: 1,
steps: [
{ anchor: 'page-title', title: 'پزشکان', body: 'فهرست پزشکان و دسترسی به پروفایل هرکدام.', side: 'bottom' },
{ anchor: 'page-pagination', title: 'صفحه‌بندی', body: 'تعداد کل پزشکان و حرکت بین صفحه‌ها.', side: 'top' },
],
};
export const doctorDetailTour: TourDefinition = {
id: 'doctor-detail',
version: 1,
steps: [
{ anchor: 'page-title', title: 'پروفایل پزشک', body: 'مشخصات، تخصص‌ها، آدرس‌ها، تعرفه‌ها و وضعیت فعال‌بودن پزشک.', side: 'bottom' },
],
};
export const doctorFormTour: TourDefinition = {
id: 'doctor-new',
version: 1,
steps: [
{ anchor: 'page-title', title: 'افزودن پزشک', body: 'پزشک جدید را با موبایل و تخصصش ثبت کنید.', side: 'bottom' },
{ anchor: 'doctor-form', title: 'فرم', body: 'موبایل کلید حساب است؛ اگر کاربری با آن شماره باشد، به همان وصل می‌شود.', side: 'top' },
],
};
export const mySecretariesTour: TourDefinition = {
id: 'my-secretaries',
version: 1,
steps: [
{ anchor: 'page-title', title: 'منشی‌ها', body: 'منشی‌های شما و دسترسی‌هایشان.', side: 'bottom' },
{ anchor: 'secretaries-tabs', title: 'فعلی و قبلی', body: 'منشی قطع‌همکاری‌شده در تب دوم می‌ماند و حذف نمی‌شود.', side: 'bottom' },
{ anchor: 'secretaries-add', title: 'افزودن منشی', body: 'بعد از ذخیره، پنجرهٔ مجوزها باز می‌شود تا دسترسی‌هایش را دقیق تعیین کنید. سقف تعداد به پلن اشتراک بستگی دارد.', side: 'bottom' },
],
};
export const staffTour: TourDefinition = {
id: 'staff',
version: 1,
steps: [
{ anchor: 'page-title', title: 'مدیریت پرسنل', body: 'کارکنان درمانی که جلسه انجام می‌دهند — با مهارت‌ها و سهمشان.', side: 'bottom' },
{ anchor: 'page-table', title: 'فهرست پرسنل', body: 'مهارت هر نفر تعیین می‌کند در چه سرویسی قابل انتخاب است.', side: 'top' },
],
};
export const staffSessionsTour: TourDefinition = {
id: 'my-sessions',
version: 1,
steps: [
{ anchor: 'page-title', title: 'جلسات امروز من', body: 'جلسه‌هایی که امروز به شما سپرده شده است.', side: 'bottom' },
],
};
export const staffSessionDetailTour: TourDefinition = {
id: 'my-session-detail',
version: 1,
steps: [
{ anchor: 'page-title', title: 'جزئیات جلسه', body: 'خدمت، بیمار، مصرف انبار و ثبت انجام جلسه.', side: 'bottom' },
],
};
export const secretaryEarningsTour: TourDefinition = {
id: 'secretary-earnings',
version: 1,
steps: [
{ anchor: 'page-title', title: 'درآمد نوبت‌های آنلاین', body: 'سهم شما از نوبت‌هایی که آنلاین ثبت و پرداخت شده‌اند.', side: 'bottom' },
{ anchor: 'page-table', title: 'ریز نوبت‌ها', body: 'هر ردیف یک نوبت با سهم شما از آن.', side: 'top' },
],
};
export const secretarySettlementTour: TourDefinition = {
id: 'secretary-settlement',
version: 1,
steps: [
{ anchor: 'page-title', title: 'تسویه حساب', body: 'برداشت سهم نوبت‌های آنلاین به شماره شبای خودتان.', side: 'bottom' },
{ anchor: 'page-table', title: 'درخواست‌ها', body: 'وضعیت هر درخواست برداشت اینجا دیده می‌شود.', side: 'top' },
],
};
+85
View File
@@ -0,0 +1,85 @@
import type { TourDefinition } from '../types';
export const myPaymentsTour: TourDefinition = {
id: 'my-payments',
version: 1,
steps: [
{ anchor: 'page-title', title: 'لیست پرداخت‌ها', body: 'همهٔ پرداخت‌های ثبت‌شدهٔ بیماران شما، جدیدترین بالا.', side: 'bottom' },
{ anchor: 'page-search', title: 'جستجو', body: 'با نام بیمار یا شمارهٔ صورتحساب بگردید.', side: 'bottom' },
{ anchor: 'page-table', title: 'ردیف‌های پرداخت', body: 'با کلیک روی هر بیمار، صورتحساب‌ها و آیتم‌هایش باز می‌شود.', side: 'top' },
{ anchor: 'page-pagination', title: 'صفحه‌بندی', body: 'تعداد کل و جابه‌جایی بین صفحه‌ها.', side: 'top' },
],
};
export const myPaymentDetailTour: TourDefinition = {
id: 'my-payment-detail',
version: 1,
steps: [
{ anchor: 'page-title', title: 'پرداخت‌های این بیمار', body: 'صورتحساب‌های ثبت‌شده برای همین بیمار و مانده‌حسابش.', side: 'bottom' },
{ anchor: 'page-table', title: 'آیتم‌های صورتحساب', body: 'هر ردیف یک خدمت با سهم بیمار و سهم بیمه.', side: 'top' },
],
};
export const myFinancialTour: TourDefinition = {
id: 'my-financial',
version: 1,
steps: [
{ anchor: 'page-title', title: 'مدیریت پرداخت', body: 'درگاه، حساب بانکی و روش‌های دریافت وجه از بیمار.', side: 'bottom' },
],
};
export const claimsTour: TourDefinition = {
id: 'claims',
version: 1,
steps: [
{ anchor: 'page-title', title: 'پرونده‌های بیمه', body: 'مطالبات بیمه به تفکیک بیمار؛ چقدر ثبت شده، چقدر وصول شده.', side: 'bottom' },
{ anchor: 'page-search', title: 'جستجوی بیمار', body: 'با نام یا کد ملی بیمار پیدایش کنید.', side: 'bottom' },
{ anchor: 'page-table', title: 'فهرست مطالبات', body: 'روی هر ردیف بزنید تا ریز خدمات و سهم بیمه‌اش باز شود.', side: 'top' },
],
};
export const claimDetailTour: TourDefinition = {
id: 'claim-detail',
version: 1,
steps: [
{ anchor: 'page-title', title: 'جزئیات مطالبه', body: 'خدمات بیمه‌ایِ همین بیمار و وضعیت وصول هرکدام.', side: 'bottom' },
{ anchor: 'page-table', title: 'ریز خدمات', body: 'سهم بیمه و سهم بیمار برای هر خدمت جدا آمده است.', side: 'top' },
],
};
export const insurancePricingTour: TourDefinition = {
id: 'insurance-pricing',
version: 1,
steps: [
{ anchor: 'page-title', title: 'مدیریت بیمه', body: 'قراردادهای بیمهٔ پایه و تکمیلی و درصد پوشش هرکدام.', side: 'bottom' },
],
};
export const discountsTour: TourDefinition = {
id: 'discounts',
version: 1,
steps: [
{ anchor: 'page-title', title: 'مدیریت تخفیف‌ها', body: 'قوانین تخفیف که هنگام صدور صورتحساب اعمال می‌شوند.', side: 'bottom' },
{ anchor: 'discounts-rules', title: 'قوانین', body: 'برای هر خدمت یا کل فاکتور، درصد یا مبلغ ثابت تعریف کنید.', side: 'top' },
],
};
export const subscriptionTour: TourDefinition = {
id: 'subscription',
version: 1,
steps: [
{ anchor: 'page-title', title: 'اشتراک', body: 'پلن فعلی و پلن‌های قابل خرید.', side: 'bottom' },
{ anchor: 'subscription-current', title: 'پلن فعلی', body: 'روزهای باقی‌مانده و دکمهٔ تمدید همین‌جاست.', side: 'bottom' },
{ anchor: 'subscription-plans', title: 'پلن‌ها', body: 'امکانات هر پلن زیرش نوشته شده؛ خرید از روی همین کارت‌ها انجام می‌شود.', side: 'top' },
],
};
export const smsWalletTour: TourDefinition = {
id: 'sms-wallet',
version: 1,
steps: [
{ anchor: 'page-title', title: 'کیف پول پیامک', body: 'ارسال پیامک به بیماران از موجودی همین کیف پول کم می‌شود.', side: 'bottom' },
{ anchor: 'sms-balance', title: 'موجودی و مصرف', body: 'موجودی فعلی و آمار مصرف. وقتی موجودی کم شود، اینجا هشدار می‌گیرید.', side: 'bottom' },
{ anchor: 'page-pagination', title: 'تاریخچه', body: 'شارژها و مصرف‌های قبلی صفحه‌بندی شده‌اند.', side: 'top' },
],
};
+63
View File
@@ -0,0 +1,63 @@
import type { TourDefinition } from '../types';
export const myPatientsTour: TourDefinition = {
id: 'my-patients',
version: 1,
steps: [
{
anchor: 'page-title',
title: 'پروندهٔ بیماران',
body: 'فهرست مراجعه‌کنندگانی که برایشان پرونده ثبت شده است. با ثبت اولین نوبت، پرونده خودکار ساخته می‌شود.',
side: 'bottom',
},
{
anchor: 'page-action',
title: 'پروندهٔ دستی',
body: 'برای بیماری که هنوز نوبت نگرفته، از اینجا پرونده بسازید.',
side: 'bottom',
},
{
anchor: 'patients-search',
title: 'جستجو و نمای فهرست',
body: 'جستجو با نام، موبایل یا کد ملی. دو آیکون کنارش، نمای کارتی و لیستی را عوض می‌کنند.',
side: 'bottom',
},
{
anchor: 'patients-records',
title: 'پرونده‌ها',
body: 'با کلیک روی هر پرونده، اطلاعات بیمار و مراجعه‌ها و پرداخت‌هایش باز می‌شود.',
side: 'top',
},
{
anchor: 'page-pagination',
title: 'صفحه‌بندی',
body: 'شمار کل پرونده‌ها و جابه‌جایی بین صفحه‌ها.',
side: 'top',
},
],
};
export const myPatientRecordTour: TourDefinition = {
id: 'my-patient-record',
version: 1,
steps: [
{
anchor: 'record-banner',
title: 'شناسنامهٔ بیمار',
body: 'خلاصهٔ هویتی و تماس بیمار، شمارهٔ پرونده و تاریخ تشکیل آن.',
side: 'bottom',
},
{
anchor: 'record-tabs',
title: 'بخش‌های پرونده',
body: 'اطلاعات پرونده، مراجعه‌ها، پرداخت‌ها و نوبت‌ها؛ هر کدام در تب خودش.',
side: 'bottom',
},
{
anchor: 'page-action',
title: 'مراجعهٔ جدید و بازگشت',
body: 'ثبت مراجعهٔ تازه برای همین بیمار، یا برگشتن به فهرست پرونده‌ها.',
side: 'bottom',
},
],
};
@@ -0,0 +1,70 @@
import type { TourDefinition } from '../types';
export const patientDetailTour: TourDefinition = {
id: 'patient-detail',
version: 1,
steps: [
{
anchor: 'patient-banner',
title: 'شناسنامهٔ پرونده',
body: 'نام، شمارهٔ پرونده، برچسب‌ها، نوبت و جلسهٔ بعدی و وضعیت بدهی — همه یک‌جا.',
side: 'bottom',
},
{
anchor: 'patient-tabs',
title: 'بخش‌های پرونده',
body: 'سرویس‌ها، نوبت‌ها، دوره‌های درمان، پرداخت‌ها، کیف پول، یادداشت، ضمیمه و پروندهٔ پزشکی.',
side: 'bottom',
},
],
};
export const appointmentCreateTour: TourDefinition = {
id: 'appointment-create',
version: 1,
steps: [
{
anchor: 'page-title',
title: 'ثبت نوبت جدید',
body: 'چهار قدم دارد: پزشک، مراجعه‌کننده، سرویس و زمان.',
side: 'bottom',
},
{
anchor: 'create-doctor',
title: 'پزشک یا منبع',
body: 'اول پزشک را انتخاب کنید؛ سرویس‌ها و ساعت‌های آزاد از برنامهٔ همو می‌آیند.',
side: 'bottom',
},
{
anchor: 'create-patient',
title: 'مراجعه‌کننده',
body: 'بیمار قبلی را جستجو کنید، یا مشخصات شخص جدید را وارد کنید تا پرونده‌اش ساخته شود.',
side: 'bottom',
},
{
anchor: 'create-service',
title: 'سرویس‌ها',
body: 'اول بخش، بعد یک یا چند سرویس. مدت و هزینهٔ نوبت از همین‌ها حساب می‌شود.',
side: 'bottom',
},
{
anchor: 'create-submit',
title: 'ثبت',
body: 'تا وقتی پزشک، بیمار، سرویس و زمان کامل نشده، دکمه غیرفعال است.',
side: 'top',
},
],
};
export const appointmentEditTour: TourDefinition = {
id: 'appointment-edit',
version: 1,
steps: [
{
anchor: 'edit-service',
title: 'ویرایش نوبت',
body: 'بخش، سرویس، پرسنل، زمان و وضعیت نوبت را از همین‌جا عوض کنید.',
side: 'bottom',
},
],
};
+38
View File
@@ -0,0 +1,38 @@
import type { TourDefinition } from '../types';
export const patientsTour: TourDefinition = {
id: 'patients',
version: 1,
steps: [
{
anchor: 'page-title',
title: 'پرونده‌ها',
body: 'فهرست کامل پرونده‌های بیماران این محیط، با امکان جستجو و فیلتر.',
side: 'bottom',
},
{
anchor: 'patients-search',
title: 'جستجو',
body: 'کد ملی، شمارهٔ پرونده یا نام مراجعه‌کننده را بنویسید.',
side: 'bottom',
},
{
anchor: 'patients-filters',
title: 'فیلترها',
body: 'جنسیت، بیمه، بازهٔ پذیرش، بدهی و برچسب. عدد روی دکمه یعنی چند فیلتر فعال است.',
side: 'bottom',
},
{
anchor: 'patients-new',
title: 'تشکیل پرونده',
body: 'پروندهٔ جدید برای بیماری که هنوز ثبت نشده است.',
side: 'bottom',
},
{
anchor: 'page-pagination',
title: 'صفحه‌بندی',
body: 'نمای کارتی ۱۶ و نمای جدولی ۱۲ پرونده در هر صفحه نشان می‌دهد.',
side: 'top',
},
],
};
+91
View File
@@ -0,0 +1,91 @@
import type { TourDefinition } from '../types';
export const clinicServicesTour: TourDefinition = {
id: 'clinic-services',
version: 1,
steps: [
{ anchor: 'page-title', title: 'سرویس‌ها', body: 'خدماتی که در نوبت‌دهی و صورتحساب استفاده می‌شوند؛ هرکدام مدت و تعرفهٔ خودش را دارد.', side: 'bottom' },
{ anchor: 'page-action', title: 'سرویس جدید', body: 'خدمت تازه را اینجا تعریف کنید تا در ثبت نوبت قابل انتخاب شود.', side: 'bottom' },
],
};
export const serviceDetailTour: TourDefinition = {
id: 'service-detail',
version: 1,
steps: [
{ anchor: 'page-title', title: 'جزئیات سرویس', body: 'تعرفه، مدت، بیمه و تنظیمات نوبت‌دهی همین خدمت.', side: 'bottom' },
],
};
export const serviceCategoriesTour: TourDefinition = {
id: 'service-categories',
version: 1,
steps: [
{ anchor: 'page-title', title: 'دسته‌بندی‌ها', body: 'سرویس‌ها را دسته‌بندی کنید تا در فهرست‌ها و فیلترها مرتب بمانند.', side: 'bottom' },
{ anchor: 'page-table', title: 'دسته‌ها', body: 'هر دسته را می‌توان ویرایش یا حذف کرد.', side: 'top' },
],
};
export const resourcesTour: TourDefinition = {
id: 'resources',
version: 1,
steps: [
{ anchor: 'page-title', title: 'منابع', body: 'اتاق، تخت یا دستگاه — هر چیزی که خودش تقویم نوبت دارد.', side: 'bottom' },
{ anchor: 'page-action', title: 'منبع جدید', body: 'منبع تازه بسازید و پزشک ناظرش را مشخص کنید.', side: 'bottom' },
{ anchor: 'page-table', title: 'فهرست منابع', body: 'با کلیک روی هر منبع، تقویم و سرویس‌هایش باز می‌شود.', side: 'top' },
],
};
export const resourceTypesTour: TourDefinition = {
id: 'resource-types',
version: 1,
steps: [
{ anchor: 'page-title', title: 'نوع منابع', body: 'دسته‌بندی منابع؛ مثلاً اتاق عمل، یونیت دندان‌پزشکی یا دستگاه لیزر.', side: 'bottom' },
{ anchor: 'page-table', title: 'نوع‌ها', body: 'هنگام ساخت منبع، یکی از همین نوع‌ها انتخاب می‌شود.', side: 'top' },
],
};
export const resourcePoolsTour: TourDefinition = {
id: 'resource-pools',
version: 1,
steps: [
{ anchor: 'page-title', title: 'استخر منابع', body: 'چند منبع هم‌کار را در یک استخر بگذارید تا سیستم خودش یکی از آزادها را بدهد.', side: 'bottom' },
{ anchor: 'page-table', title: 'استخرها', body: 'اعضای هر استخر از همین‌جا مدیریت می‌شوند.', side: 'top' },
],
};
export const resourceSkillsTour: TourDefinition = {
id: 'resource-skills',
version: 1,
steps: [
{ anchor: 'page-title', title: 'مهارت‌ها', body: 'مهارت لازم برای هر خدمت؛ فقط منبع یا پرسنلِ دارای آن مهارت قابل انتخاب می‌شود.', side: 'bottom' },
{ anchor: 'page-table', title: 'فهرست مهارت‌ها', body: 'مهارت‌ها را بسازید و بعد به منابع و پرسنل نسبت دهید.', side: 'top' },
],
};
export const resourceDetailTour: TourDefinition = {
id: 'resource-detail',
version: 1,
steps: [
{ anchor: 'page-title', title: 'جزئیات منبع', body: 'مشخصات منبع، سرویس‌هایش، مهارت‌ها و دسترسی به تقویمش.', side: 'bottom' },
],
};
export const inventoryTour: TourDefinition = {
id: 'inventory',
version: 1,
steps: [
{ anchor: 'page-title', title: 'انبارداری', body: 'کالاهای مصرفی و پکیج‌ها؛ مصرف هر جلسه از همین موجودی کم می‌شود.', side: 'bottom' },
{ anchor: 'inventory-tabs', title: 'دو بخش', body: 'کالای مصرفی و پکیج. پکیج چند کالا را با هم مصرف می‌کند.', side: 'bottom' },
{ anchor: 'inventory-stats', title: 'وضعیت انبار', body: 'ارزش موجودی و کالاهایی که به مرز هشدار رسیده‌اند.', side: 'bottom' },
],
};
export const treatmentCasesTour: TourDefinition = {
id: 'treatment-cases',
version: 1,
steps: [
{ anchor: 'page-title', title: 'دوره‌های درمان', body: 'درمان‌های چندجلسه‌ای بیماران و پیشرفت هر دوره.', side: 'bottom' },
{ anchor: 'treatment-tabs', title: 'بخش‌ها', body: 'دوره‌ها و جلسه‌ها را جدا ببینید و بر اساس وضعیت فیلتر کنید.', side: 'bottom' },
],
};
@@ -0,0 +1,80 @@
import type { TourDefinition } from '../types';
export const sessionNewTour: TourDefinition = {
id: 'session-new',
version: 1,
steps: [
{ anchor: 'page-title', title: 'ثبت مراجعه', body: 'یک مراجعهٔ تازه برای همین بیمار ثبت می‌کنید.', side: 'bottom' },
{ anchor: 'session-card', title: 'فرم مراجعه', body: 'خدمت انجام‌شده، پرسنل و مبلغ. بعد از ثبت، صورتحسابش قابل صدور است.', side: 'top' },
],
};
export const sessionEditTour: TourDefinition = {
id: 'session-edit',
version: 1,
steps: [
{ anchor: 'page-title', title: 'ویرایش مراجعه', body: 'خدمت، پرسنل یا مبلغ همین مراجعه را اصلاح کنید.', side: 'bottom' },
],
};
export const sessionPaymentTour: TourDefinition = {
id: 'session-payment',
version: 1,
steps: [
{ anchor: 'page-title', title: 'پرداخت مراجعه', body: 'دریافت وجه بابت این مراجعه و ثبت روش پرداخت.', side: 'bottom' },
{ anchor: 'session-card', title: 'مبلغ و روش', body: 'سهم بیمه از سهم بیمار جدا حساب می‌شود؛ باقی‌مانده همان چیزی است که دریافت می‌کنید.', side: 'top' },
],
};
export const patientRecordFormTour: TourDefinition = {
id: 'patient-record-form',
version: 1,
steps: [
{ anchor: 'page-title', title: 'پروندهٔ بیمار', body: 'ساخت یا ویرایش پروندهٔ یک مراجعه‌کننده.', side: 'bottom' },
{ anchor: 'record-form', title: 'فرم', body: 'موبایل کلید شناسایی بیمار است؛ کد ملی و بیمه بعداً هم قابل تکمیل‌اند.', side: 'top' },
],
};
export const representationBlogsTour: TourDefinition = {
id: 'representation-blogs',
version: 1,
steps: [
{ anchor: 'page-title', title: 'وبلاگ من', body: 'مقاله‌هایی که نوشته‌اید و وضعیت بررسی هرکدام.', side: 'bottom' },
{ anchor: 'page-action', title: 'مقالهٔ جدید', body: 'مقاله بعد از تأیید ادمین روی سایت منتشر می‌شود.', side: 'bottom' },
{ anchor: 'page-table', title: 'فهرست مقاله‌ها', body: 'وضعیت هر مقاله: پیش‌نویس، در انتظار بررسی یا منتشرشده.', side: 'top' },
],
};
export const representationBlogFormTour: TourDefinition = {
id: 'representation-blog-form',
version: 1,
steps: [
{ anchor: 'page-title', title: 'نوشتن مقاله', body: 'عنوان، متن، تصویر و اطلاعات سئو مقاله.', side: 'bottom' },
],
};
export const representationFinanceTour: TourDefinition = {
id: 'representation-finance',
version: 1,
steps: [
{ anchor: 'page-title', title: 'گزارش مالی', body: 'پورسانت شما از اشتراک‌هایی که مجموعه‌های تحت پوششتان خریده‌اند.', side: 'bottom' },
{ anchor: 'page-pagination', title: 'دوره‌ها', body: 'رکوردهای مالی صفحه‌بندی شده‌اند.', side: 'top' },
],
};
export const representationProfileTour: TourDefinition = {
id: 'representation-profile',
version: 1,
steps: [
{ anchor: 'page-title', title: 'پروفایل نماینده', body: 'مشخصات شما، شهر تحت پوشش و اطلاعات حساب بانکی برای تسویه.', side: 'bottom' },
],
};
export const representationSettlementTour: TourDefinition = {
id: 'representation-settlement',
version: 1,
steps: [
{ anchor: 'page-title', title: 'تسویه حساب', body: 'درخواست برداشت پورسانت و وضعیت درخواست‌های قبلی.', side: 'bottom' },
{ anchor: 'page-pagination', title: 'تاریخچه', body: 'درخواست‌های قبلی و نتیجهٔ هرکدام.', side: 'top' },
],
};
+75
View File
@@ -0,0 +1,75 @@
import type { TourDefinition } from '../types';
export const settingsMenuTour: TourDefinition = {
id: 'settings-menu',
version: 1,
steps: [
{ anchor: 'page-title', title: 'تنظیمات', body: 'همهٔ تنظیمات محیط از همین‌جا شاخه می‌گیرد: نوبت‌دهی، سرویس‌ها، بیمه، برچسب‌ها، اشتراک و کاربران.', side: 'bottom' },
],
};
export const accountSettingsTour: TourDefinition = {
id: 'account-settings',
version: 1,
steps: [
{ anchor: 'page-title', title: 'حساب کاربری', body: 'شمارهٔ ورود، رمز عبور و اطلاعات شخصی حسابتان.', side: 'bottom' },
],
};
export const tagsSettingsTour: TourDefinition = {
id: 'tags-settings',
version: 1,
steps: [
{ anchor: 'page-title', title: 'برچسب‌ها', body: 'برچسب‌هایی که به پروندهٔ بیماران می‌چسبانید و بعد با آن‌ها فیلتر می‌کنید.', side: 'bottom' },
],
};
export const recordNumberSettingsTour: TourDefinition = {
id: 'record-number-settings',
version: 1,
steps: [
{ anchor: 'page-title', title: 'شمارهٔ پرونده', body: 'الگوی شماره‌گذاری پرونده‌های جدید — پیشوند، طول و شمارهٔ شروع.', side: 'bottom' },
],
};
export const appointmentSettingsTour: TourDefinition = {
id: 'appointment-settings',
version: 1,
steps: [
{ anchor: 'page-title', title: 'مدیریت نوبت‌دهی', body: 'برنامهٔ هفتگی، مدت نوبت، تعطیلی‌ها و قواعد لغو نوبت.', side: 'bottom' },
],
};
export const clinicAppointmentSettingsTour: TourDefinition = {
id: 'clinic-appointment-settings',
version: 1,
steps: [
{ anchor: 'page-title', title: 'نوبت‌دهی کلینیک', body: 'تنظیمات نوبت‌دهی در سطح کلینیک؛ روی همهٔ پزشکان عضو اثر می‌گذارد.', side: 'bottom' },
],
};
export const holidaysTour: TourDefinition = {
id: 'holidays',
version: 1,
steps: [
{ anchor: 'page-title', title: 'تعطیلات', body: 'روزهایی که نوبت‌دهی بسته است. تعطیلات رسمی کشور از قبل هست و می‌توانید روز دلخواه هم اضافه کنید.', side: 'bottom' },
{ anchor: 'page-table', title: 'فهرست روزها', body: 'هر ردیف یک روز تعطیل؛ حذفش نوبت‌دهی همان روز را باز می‌کند.', side: 'top' },
],
};
export const practiceDomainTour: TourDefinition = {
id: 'practice-domain',
version: 1,
steps: [
{ anchor: 'page-title', title: 'حوزهٔ فعالیت', body: 'نوع کار محیط شما؛ فرم‌های پرونده و گردش درمان بر اساس همین انتخاب می‌شود.', side: 'bottom' },
],
};
export const clinicDoctorsTour: TourDefinition = {
id: 'clinic-doctors',
version: 1,
steps: [
{ anchor: 'page-title', title: 'پزشکان کلینیک', body: 'پزشکان عضو، دعوت پزشک جدید و قطع همکاری.', side: 'bottom' },
{ anchor: 'page-action', title: 'دعوت پزشک', body: 'با شمارهٔ موبایل دعوت بفرستید؛ پزشک بعد از پذیرش، در نوبت‌دهی کلینیک دیده می‌شود.', side: 'bottom' },
],
};