diff --git a/assets/admin/components/ui/DataTable.tsx b/assets/admin/components/ui/DataTable.tsx index d98c04f7..6b06c690 100644 --- a/assets/admin/components/ui/DataTable.tsx +++ b/assets/admin/components/ui/DataTable.tsx @@ -63,9 +63,11 @@ export default function DataTable({
{/* Toolbar row */} {(onSearchChange !== undefined || headerExtra) && ( -
+ // لنگرهای data-tour اینجا تعریف می‌شوند تا هر صفحه‌ای که DataTable دارد + // بدون تغییر کد خودش، در تور راهنما قابل اشاره باشد. +
{onSearchChange !== undefined && ( -
+
({
)} -
+
diff --git a/assets/admin/components/ui/PageHeader.tsx b/assets/admin/components/ui/PageHeader.tsx index 8bef9cc4..232da242 100644 --- a/assets/admin/components/ui/PageHeader.tsx +++ b/assets/admin/components/ui/PageHeader.tsx @@ -21,9 +21,14 @@ interface Props { backTo?: string; /** شناسهٔ تور راهنمای این صفحه؛ اگر در registry ثبت نشده باشد دکمه‌ای نمی‌آید. */ tourId?: string; + /** + * محتوای صفحه نشسته است و تورِ بار اول می‌تواند خودکار اجرا شود. + * صفحه‌ای که داده‌اش دیر می‌آید، `!isLoading` بدهد تا تور روی صفحهٔ نیمه‌ساخته نیفتد. + */ + tourReady?: boolean; } -export default function PageHeader({ title, breadcrumbs, action, description, backTo, tourId }: Props) { +export default function PageHeader({ title, breadcrumbs, action, description, backTo, tourId, tourReady = true }: Props) { return (
@@ -51,15 +56,15 @@ export default function PageHeader({ title, breadcrumbs, action, description, ba ))} )} -
+

{title}

- +
{description && (

{description}

)}
- {action &&
{action}
} + {action &&
{action}
}
); } diff --git a/assets/admin/components/ui/Pagination.tsx b/assets/admin/components/ui/Pagination.tsx index 936b091f..cc626980 100644 --- a/assets/admin/components/ui/Pagination.tsx +++ b/assets/admin/components/ui/Pagination.tsx @@ -28,7 +28,7 @@ export default function Pagination({ page, total, limit, onPageChange }: Props) } return ( -
+
نمایش {formatNumber(from)}–{formatNumber(to)} از {formatNumber(total)} مورد diff --git a/assets/admin/components/ui/TourButton.tsx b/assets/admin/components/ui/TourButton.tsx index d3dcbcbf..19009656 100644 --- a/assets/admin/components/ui/TourButton.tsx +++ b/assets/admin/components/ui/TourButton.tsx @@ -8,17 +8,21 @@ import { getTour } from '../../lib/tour/registry'; * وجود تور قبل از هر هوکی بررسی می‌شود تا صفحه‌ای که راهنما ندارد — یعنی بیشتر * صفحات پنل — هیچ درخواستی برای وضعیت تورها نفرستد. */ -export default function TourButton({ tourId }: { tourId?: string }) { +export default function TourButton({ tourId, ready = false }: { tourId?: string; ready?: boolean }) { const tour = getTour(tourId); if (!tour) return null; - return ; + return ; } -/** اجرای خودکار وظیفهٔ خود صفحه است؛ این دکمه فقط دستی اجرا می‌کند. */ -function TourLauncher({ tourId }: { tourId: string }) { - const { start } = useTour(tourId); +/** + * `ready` یعنی محتوای صفحه نشسته است و اجرای خودکارِ بار اول مجاز است. + * صفحه‌ای که دکمه را مستقیم می‌گذارد و آماده‌بودنش را نمی‌داند، آن را false می‌گذارد + * و تور فقط با کلیک اجرا می‌شود. + */ +function TourLauncher({ tourId, ready }: { tourId: string; ready: boolean }) { + const { start } = useTour(tourId, { ready }); return (
diff --git a/assets/admin/pages/AppointmentDetailPage.tsx b/assets/admin/pages/AppointmentDetailPage.tsx index a397fb92..e8f3683f 100644 --- a/assets/admin/pages/AppointmentDetailPage.tsx +++ b/assets/admin/pages/AppointmentDetailPage.tsx @@ -106,6 +106,8 @@ export default function AppointmentDetailPage() {
-

اطلاعات بیمار

+

اطلاعات بیمار

{appt.patient_mobile}} /> @@ -139,7 +141,7 @@ export default function AppointmentDetailPage() {
-

وضعیت و اقدامات

+

وضعیت و اقدامات

وضعیت فعلی:

@@ -198,7 +200,7 @@ export default function AppointmentDetailPage() {
-

تاریخچه رویدادها

+

تاریخچه رویدادها

{eventsQuery.isLoading ? (
) : events.length === 0 ? ( diff --git a/assets/admin/pages/AppointmentEditPage.tsx b/assets/admin/pages/AppointmentEditPage.tsx index 8cda2210..f78461e0 100644 --- a/assets/admin/pages/AppointmentEditPage.tsx +++ b/assets/admin/pages/AppointmentEditPage.tsx @@ -10,6 +10,7 @@ import SearchableSelect from '../components/ui/SearchableSelect'; import { formatRial, rialToToman, tomanToRial } from '../lib/utils'; import { DEFAULT_SERVICE_CATEGORY } from '../lib/insuranceShares'; import BackButton from '../components/ui/BackButton'; +import TourButton from '../components/ui/TourButton'; import { useAppointmentInsurance } from '../hooks/useAppointmentInsurance'; import { useDoctorBookingServices } from '../hooks/useDoctorBookingServices'; import ServiceSlotPicker from '../components/appointments/ServiceSlotPicker'; @@ -194,12 +195,13 @@ export default function AppointmentEditPage() { return (
-
+
+
-
مشخصات سرویس:
+
مشخصات سرویس:
diff --git a/assets/admin/pages/AppointmentSettingsPage.tsx b/assets/admin/pages/AppointmentSettingsPage.tsx index 7ba6ff27..c7d5e2f4 100644 --- a/assets/admin/pages/AppointmentSettingsPage.tsx +++ b/assets/admin/pages/AppointmentSettingsPage.tsx @@ -9,6 +9,7 @@ import { ScheduleSection } from '../components/schedule/ScheduleSection'; import type { AddressData } from '../components/schedule/ScheduleSection'; import SearchableSelect from '../components/ui/SearchableSelect'; import { usePermissions } from '../hooks/usePermissions'; +import TourButton from '../components/ui/TourButton'; const PERSONAL = 'personal'; @@ -75,7 +76,7 @@ export default function AppointmentSettingsPage() { style={{ background: 'var(--surface)', minWidth: 0 }} className="px-4 py-4 md:px-6 md:py-6 rounded-[var(--r-lg)]" > -

مدیریت نوبت دهی

+

مدیریت نوبت دهی

diff --git a/assets/admin/pages/CatalogCategoriesPage.tsx b/assets/admin/pages/CatalogCategoriesPage.tsx index afec00e8..d6866044 100644 --- a/assets/admin/pages/CatalogCategoriesPage.tsx +++ b/assets/admin/pages/CatalogCategoriesPage.tsx @@ -68,6 +68,7 @@ export default function CatalogCategoriesPage() {
- setSelected(null)}> + setSelected(null)}> {selected && (
diff --git a/assets/admin/pages/ClaimsPage.tsx b/assets/admin/pages/ClaimsPage.tsx index 1f2743df..728e6040 100644 --- a/assets/admin/pages/ClaimsPage.tsx +++ b/assets/admin/pages/ClaimsPage.tsx @@ -183,6 +183,7 @@ export default function ClaimsPage() { diff --git a/assets/admin/pages/ClinicAppointmentSettingsPage.tsx b/assets/admin/pages/ClinicAppointmentSettingsPage.tsx index dd627d54..17dde713 100644 --- a/assets/admin/pages/ClinicAppointmentSettingsPage.tsx +++ b/assets/admin/pages/ClinicAppointmentSettingsPage.tsx @@ -87,6 +87,7 @@ function ClinicAppointmentSettingsContent() { در دید، بدون اسکرول. پایین‌تر از هدر، کاربر باید دنبالش می‌گشت. */} diff --git a/assets/admin/pages/ClinicDoctorsPage.tsx b/assets/admin/pages/ClinicDoctorsPage.tsx index cb910111..9e49f2d8 100644 --- a/assets/admin/pages/ClinicDoctorsPage.tsx +++ b/assets/admin/pages/ClinicDoctorsPage.tsx @@ -48,6 +48,7 @@ function ClinicDoctorsContent() { {/* عنوان و بازگشت و اکشن هر سه در PageHeader — همان قاعدهٔ بقیهٔ صفحات پنل. */}
-

کلینیک‌ها

+

کلینیک‌ها

{formatNumber(total)} کلینیک ثبت‌شده
/ - افزودن پزشک جدید + افزودن پزشک جدید +
-
+
{/* ── Section: اطلاعات حساب ──────────────────────────────── */} diff --git a/assets/admin/pages/DoctorsPage.tsx b/assets/admin/pages/DoctorsPage.tsx index 5afa32cc..29393499 100644 --- a/assets/admin/pages/DoctorsPage.tsx +++ b/assets/admin/pages/DoctorsPage.tsx @@ -16,6 +16,7 @@ import ChangeLoginMobileModal from '../components/ChangeLoginMobileModal'; import Pagination from '../components/ui/Pagination'; import SearchableSelect from '../components/ui/SearchableSelect'; import { useAuthStore } from '../stores/authStore'; +import TourButton from '../components/ui/TourButton'; // ── Types ───────────────────────────────────────────────────────────────── @@ -239,7 +240,7 @@ export default function DoctorsPage() { {/* Header */}
-

پزشکان

+

پزشکان

مدیریت پزشکان، تخصص‌ها و وضعیت همکاری
diff --git a/assets/admin/pages/EditSessionPage.tsx b/assets/admin/pages/EditSessionPage.tsx index c397636a..f8814e18 100644 --- a/assets/admin/pages/EditSessionPage.tsx +++ b/assets/admin/pages/EditSessionPage.tsx @@ -9,6 +9,7 @@ import CreateStep from '../components/session/CreateStep'; import PaymentStep from '../components/session/PaymentStep'; import { CloseModalD } from '../components/icons/FilesServiceIcons'; import { Breadcrumb } from '../components/PatientCaseBanner'; +import TourButton from '../components/ui/TourButton'; /** ویرایش مراجعه‌ی ثبت‌شده — دو تب: ویرایش سرویس‌ها + مدیریت پرداخت‌ها. */ export default function EditSessionPage() { @@ -47,7 +48,10 @@ export default function EditSessionPage() {
-

ویرایش مراجعه

+
+

ویرایش مراجعه

+ +
@@ -105,7 +109,7 @@ export default function InventoryPage() { {/* Body */} {tab === 'stock' ? ( <> - +
{itemsLoading ? (
در حال بارگذاری...
) : filteredItems.length === 0 ? ( diff --git a/assets/admin/pages/MyFinancialPage.tsx b/assets/admin/pages/MyFinancialPage.tsx index 98f70639..35167b71 100644 --- a/assets/admin/pages/MyFinancialPage.tsx +++ b/assets/admin/pages/MyFinancialPage.tsx @@ -59,6 +59,7 @@ function MyFinancialPageContent() {
diff --git a/assets/admin/pages/MyPatientsPage.tsx b/assets/admin/pages/MyPatientsPage.tsx index dcce8dce..1e4ad33a 100644 --- a/assets/admin/pages/MyPatientsPage.tsx +++ b/assets/admin/pages/MyPatientsPage.tsx @@ -606,6 +606,8 @@ function MyPatientsPageInner() {
{canCreate && ( } /> diff --git a/assets/admin/pages/RepresentationFinancePage.tsx b/assets/admin/pages/RepresentationFinancePage.tsx index 9cddcb9b..44ac825c 100644 --- a/assets/admin/pages/RepresentationFinancePage.tsx +++ b/assets/admin/pages/RepresentationFinancePage.tsx @@ -8,6 +8,7 @@ import { api } from '../lib/api'; import type { ApiResponse, PaginatedResponse } from '../lib/api'; import { formatRial, formatNumber, formatDate } from '../lib/utils'; import Pagination from '../components/ui/Pagination'; +import TourButton from '../components/ui/TourButton'; interface FinanceRow { uuid: string; @@ -79,7 +80,7 @@ export default function RepresentationFinancePage() {
-

گزارش مالی

+

گزارش مالی

درآمد ثبت‌شده از پورسانت نوبت‌ها — تفکیک هر تراکنش
diff --git a/assets/admin/pages/RepresentationProfilePage.tsx b/assets/admin/pages/RepresentationProfilePage.tsx index f34dff4b..e76b3145 100644 --- a/assets/admin/pages/RepresentationProfilePage.tsx +++ b/assets/admin/pages/RepresentationProfilePage.tsx @@ -6,6 +6,7 @@ import { api } from '../lib/api'; import type { ApiResponse } from '../lib/api'; import PersianDatePicker from '../components/ui/PersianDatePicker'; import { toEnglishDigits, digitsOnly } from '../lib/utils'; +import TourButton from '../components/ui/TourButton'; // تبدیل تاریخ میلادی ISO (YYYY-MM-DD) به شمسی Y/m/d برای استعلام api.ir function toJalali(iso: string): string { @@ -126,7 +127,7 @@ export default function RepresentationProfilePage() {
-

پروفایل نماینده

+

پروفایل نماینده

تأیید هویت و مدیریت شماره‌های شبا
diff --git a/assets/admin/pages/RepresentationSettlementPage.tsx b/assets/admin/pages/RepresentationSettlementPage.tsx index 9401d445..7e450339 100644 --- a/assets/admin/pages/RepresentationSettlementPage.tsx +++ b/assets/admin/pages/RepresentationSettlementPage.tsx @@ -7,6 +7,7 @@ import { formatRial, formatDate, tomanToRial } from '../lib/utils'; import Pagination from '../components/ui/Pagination'; import SearchableSelect from '../components/ui/SearchableSelect'; import { digitsOnly } from '../lib/utils'; +import TourButton from '../components/ui/TourButton'; interface WalletBalance { balance_rials: number } interface RepSummary { income: { settlable_rials: number; settled_rials: number; pending_rials: number } } @@ -101,7 +102,7 @@ export default function RepresentationSettlementPage() {
-

تسویه حساب

+

تسویه حساب

درخواست برداشت از کیف‌پول نماینده
diff --git a/assets/admin/pages/ReserveAppointmentsPage.tsx b/assets/admin/pages/ReserveAppointmentsPage.tsx index 4c2ee63c..50d50471 100644 --- a/assets/admin/pages/ReserveAppointmentsPage.tsx +++ b/assets/admin/pages/ReserveAppointmentsPage.tsx @@ -17,6 +17,8 @@ import SearchableSelect from '../components/ui/SearchableSelect'; import Pagination from '../components/ui/Pagination'; import NewAppointmentDrawer from '../components/NewAppointmentDrawer'; import BackButton from '../components/ui/BackButton'; +import TourButton from '../components/ui/TourButton'; +import { useTour } from '../hooks/useTour'; import { AppointmentInfoModal, TransferReserveModal } from '../components/AppointmentActions'; const LIMIT = 20; @@ -119,16 +121,21 @@ export default function ReserveAppointmentsPage() { const th: React.CSSProperties = { padding: '10px 14px', textAlign: 'right', fontWeight: 600, color: 'var(--text-2)', whiteSpace: 'nowrap' }; const td: React.CSSProperties = { padding: '10px 14px', textAlign: 'right', color: 'var(--text)', verticalAlign: 'middle' }; + useTour('appointments-reserve', { ready: !isLoading }); + return (
-

نوبت های رزرو شده

+
+

نوبت های رزرو شده

+ +
{isClinic && ( -
+
({ value: d.uuid, label: d.name }))} value={doctorUuid || null} @@ -140,7 +147,7 @@ export default function ReserveAppointmentsPage() {
)} {primaryRole !== 'representation' && ( - @@ -148,7 +155,7 @@ export default function ReserveAppointmentsPage() {
-
+
{isLoading ? (
در حال بارگذاری...
) : items.length === 0 ? ( diff --git a/assets/admin/pages/ResourceDetailPage.tsx b/assets/admin/pages/ResourceDetailPage.tsx index 4db56c27..5cef1172 100644 --- a/assets/admin/pages/ResourceDetailPage.tsx +++ b/assets/admin/pages/ResourceDetailPage.tsx @@ -72,6 +72,7 @@ export default function ResourceDetailPage() { title={resource.name} description={`${resource.type_name}${resource.subject_kind ? ` · ${SUBJECT_LABEL[resource.subject_kind]}` : ' · تجهیزات'}`} backTo="/admin/resources" + tourId="resource-detail" breadcrumbs={[{ label: 'منابع', to: '/admin/resources' }, { label: resource.name }]} action={ canUpdate ? ( diff --git a/assets/admin/pages/ResourcePoolsPage.tsx b/assets/admin/pages/ResourcePoolsPage.tsx index ba68b774..50beea13 100644 --- a/assets/admin/pages/ResourcePoolsPage.tsx +++ b/assets/admin/pages/ResourcePoolsPage.tsx @@ -66,6 +66,7 @@ export default function ResourcePoolsPage() {
- + {summary && !summary.enabled ? (
diff --git a/assets/admin/pages/SecretarySettlementPage.tsx b/assets/admin/pages/SecretarySettlementPage.tsx index 804b95b1..c1e92bf9 100644 --- a/assets/admin/pages/SecretarySettlementPage.tsx +++ b/assets/admin/pages/SecretarySettlementPage.tsx @@ -109,7 +109,7 @@ export default function SecretarySettlementPage() { return (
- +
diff --git a/assets/admin/pages/ServiceDetailPage.tsx b/assets/admin/pages/ServiceDetailPage.tsx index 2e367814..25524fe5 100644 --- a/assets/admin/pages/ServiceDetailPage.tsx +++ b/assets/admin/pages/ServiceDetailPage.tsx @@ -436,6 +436,7 @@ function ServiceDetailPageInner() {
- +
+ + +
{/* card — tauri width 748 centered */}
-
+
)} diff --git a/assets/admin/pages/TreatmentCasesPage.tsx b/assets/admin/pages/TreatmentCasesPage.tsx index 082d383c..b08a2aa2 100644 --- a/assets/admin/pages/TreatmentCasesPage.tsx +++ b/assets/admin/pages/TreatmentCasesPage.tsx @@ -58,9 +58,9 @@ export default function TreatmentCasesPage() { return ( <> - + -
+
{TABS.map((t) => (