import React, { useEffect } from 'react'; import { Routes, Route, Navigate, useLocation } from 'react-router-dom'; import { useAuthStore } from './stores/authStore'; import AdminLayout from './components/layout/AdminLayout'; import LoginPage from './pages/LoginPage'; import DashboardPage from './pages/DashboardPage'; import SelectContextPage from './pages/SelectContextPage'; import UsersPage from './pages/UsersPage'; import UserDetailPage from './pages/UserDetailPage'; import DoctorsPage from './pages/DoctorsPage'; import DoctorDetailPage from './pages/DoctorDetailPage'; import DoctorFormPage from './pages/DoctorFormPage'; import ClinicsPage from './pages/ClinicsPage'; import ClinicDetailPage from './pages/ClinicDetailPage'; import AppointmentsPage from './pages/AppointmentsPage'; import AppointmentCreatePage from './pages/AppointmentCreatePage'; import AppointmentDetailPage from './pages/AppointmentDetailPage'; import AppointmentEditPage from './pages/AppointmentEditPage'; import ReserveAppointmentsPage from './pages/ReserveAppointmentsPage'; import PaymentsPage from './pages/PaymentsPage'; import PaymentDetailPage from './pages/PaymentDetailPage'; import SettlementsPage from './pages/SettlementsPage'; import SettlementDetailPage from './pages/SettlementDetailPage'; import RepresentationsPage from './pages/RepresentationsPage'; import RepresentationDetailPage from './pages/RepresentationDetailPage'; import CommentsPage from './pages/CommentsPage'; import RatingsPage from './pages/RatingsPage'; import SmsPage from './pages/SmsPage'; import LogsPage from './pages/LogsPage'; import CategoriesPage from './pages/CategoriesPage'; import BlogsPage from './pages/BlogsPage'; import BlogFormPage from './pages/BlogFormPage'; import SecretariesPage from './pages/SecretariesPage'; import MyClinicPage from './pages/MyClinicPage'; import SettingsPage from './pages/SettingsPage'; import FinancialReportPage from './pages/FinancialReportPage'; import RepresentationSettlementPage from './pages/RepresentationSettlementPage'; import RepresentationFinancePage from './pages/RepresentationFinancePage'; import RepresentationProfilePage from './pages/RepresentationProfilePage'; import DoctorProfilePage from './pages/DoctorProfilePage'; import MyPatientsPage from './pages/MyPatientsPage'; import MyPaymentsPage from './pages/MyPaymentsPage'; import MyPaymentDetailPage from './pages/MyPaymentDetailPage'; import NewSessionPage from './pages/NewSessionPage'; import SessionPaymentPage from './pages/SessionPaymentPage'; import InsurancePricingPage from './pages/InsurancePricingPage'; import ClaimsPage from './pages/ClaimsPage'; import DoctorClaimsPage from './pages/DoctorClaimsPage'; import MyFinancialPage from './pages/MyFinancialPage'; import ClinicFormPage from './pages/ClinicFormPage'; import PreRegistrationsPage from './pages/PreRegistrationsPage'; import StaffPage from './pages/StaffPage'; import SubscriptionPage from './pages/SubscriptionPage'; import ClinicServicesPage from './pages/ClinicServicesPage'; import SmsWalletPage from './pages/SmsWalletPage'; import MySecretariesPage from './pages/MySecretariesPage'; import AdminSubscriptionPage from './pages/AdminSubscriptionPage'; import SettingsMenuPage from './pages/SettingsMenuPage'; import AccountSettingsPage from './pages/AccountSettingsPage'; import TagsSettingsPage from './pages/TagsSettingsPage'; import AppointmentSettingsPage from './pages/AppointmentSettingsPage'; import PatientsListPage from './pages/PatientsListPage'; import InventoryPage from './pages/InventoryPage'; import PatientRecordFormPage from './pages/PatientRecordFormPage'; import PatientDetailPage from './pages/PatientDetailPage'; import PaymentSuccessPage from './pages/PaymentSuccessPage'; import PwaInstallBanner from './components/ui/PwaInstallBanner'; // ── Guards ────────────────────────────────────────────────────────────────── const ALLOWED_ROLES = ['admin', 'doctor', 'clinic', 'secretary', 'representation'] as const; function PrivateRoute({ children }: { children: React.ReactNode }) { const { isAuthenticated, primaryRole, availableContexts, dbUuid, fetchMe, logout } = useAuthStore(); const location = useLocation(); const [accessDenied, setAccessDenied] = React.useState(false); useEffect(() => { if (isAuthenticated && !primaryRole) { fetchMe(); } }, [isAuthenticated, primaryRole, fetchMe]); useEffect(() => { if (isAuthenticated && primaryRole && !ALLOWED_ROLES.includes(primaryRole as any)) { setAccessDenied(true); logout(); } }, [isAuthenticated, primaryRole, logout]); if (accessDenied) { return ; } if (!isAuthenticated) return ; // اگر context هنوز لود نشده — صبر کن if (!primaryRole) { return
در حال بارگذاری...
; } // اگر چند context دارد و هنوز انتخاب نشده و روی صفحه انتخاب نیستیم if (availableContexts.length > 1 && !dbUuid && location.pathname !== '/admin/select-context') { return ; } return <>{children}; } function PublicRoute({ children }: { children: React.ReactNode }) { const isAuthenticated = useAuthStore((s) => s.isAuthenticated); return isAuthenticated ? : <>{children}; } function RoleRoute({ roles, blockClinicScope, children }: { roles: string[]; blockClinicScope?: boolean; children: React.ReactNode }) { const primaryRole = useAuthStore((s) => s.primaryRole); const context = useAuthStore((s) => s.context); if (!primaryRole) return
در حال بارگذاری...
; if (!roles.includes(primaryRole)) return ; // پزشکِ مهمان در محیط کلینیک به ابزارهای مدیریتی دسترسی ندارد. if (blockClinicScope && primaryRole === 'doctor' && context?.scope === 'clinic') { return ; } return <>{children}; } // ── App ────────────────────────────────────────────────────────────────────── export default function App() { return ( <> {/* Public */} } /> {/* انتخاب محیط کاری — نیاز به auth دارد اما خارج از AdminLayout */} } /> {/* Protected */} } > } /> {/* داشبورد — همه نقش‌ها */} } /> {/* نوبت‌ها — همه نقش‌ها به‌جز نماینده */} } /> } /> } /> } /> } /> {/* فقط ادمین */} } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> {/* کلینیک من — fallback اگر dbUuid هنوز لود نشده */} } /> {/* ادمین + کلینیک */} } /> {/* فقط ادمین — کلینیک از طریق دعوتنامه در صفحه کلینیک خود دکتر اضافه می‌کند */} } /> } /> } /> } /> } /> } /> } /> } /> {/* دکتر / منشی / کلینیک */} } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> {/* فاز ۲ — دکتر / کلینیک */} } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> {/* فقط ادمین */} } /> } /> } /> ); }