-
-
- درصد پوشش، فرانشیز و سقف هر بیمهگر برای این خدمت تعیین میشود. این تنظیمات مبنای محاسبهی سهم بیمار و ساخت مطالبات بیمه است.
-
-
- {isLoading ? (
-
در حال بارگذاری...
- ) : contracts.length === 0 ? (
-
-
-
قرارداد بیمهی فعالی ندارید
-
ابتدا از بخش بیمهها یک بیمه را فعال کنید.
-
- ) : (
- item && contracts.map((c) =>
)
- )}
+
+
+
+ پوشش بیمه
-
+
+
+ درصد پوشش، فرانشیز و سقف هر بیمهگر برای این خدمت تعیین میشود. این تنظیمات مبنای محاسبهی سهم بیمار و ساخت مطالبات بیمه است.
+
+
+ {isLoading ? (
+
در حال بارگذاری...
+ ) : contracts.length === 0 ? (
+
+
+
قرارداد بیمهی فعالی ندارید
+
ابتدا از بخش بیمهها یک بیمه را فعال کنید.
+
+ ) : (
+ contracts.map((c) =>
)
+ )}
+
);
}
diff --git a/assets/admin/pages/ClinicServicesPage.test.tsx b/assets/admin/pages/ClinicServicesPage.test.tsx
index c94d3748..e716bc06 100644
--- a/assets/admin/pages/ClinicServicesPage.test.tsx
+++ b/assets/admin/pages/ClinicServicesPage.test.tsx
@@ -36,6 +36,11 @@ beforeEach(() => {
{ uuid: 'st1', full_name: 'مریم امینی', active: true },
{ uuid: 'st2', full_name: 'سحر رحمانی', active: true },
] });
+ // coverage before tenant-insurances (coverage URL also contains "tenant-insurances")
+ if (url.includes('/service-coverage')) return Promise.resolve({ success: true, data: { data: [] } });
+ if (url.includes('/tenant-insurances')) return Promise.resolve({ success: true, data: { data: [
+ { uuid: 'ins1', insurance_name: 'تأمین اجتماعی', insurance_kind: 'basic', coverage_percent: 70 },
+ ] } });
return Promise.resolve({ success: true, data: [] });
});
});
@@ -58,4 +63,16 @@ describe('ClinicServicesPage (خدمات)', () => {
expect(screen.getByText('سحر رحمانی')).toBeInTheDocument();
expect(screen.getByText('سرویس جدید')).toBeInTheDocument();
});
+
+ it('embeds per-insurer coverage inline inside the service edit modal', async () => {
+ renderWithProviders(
, { route: '/admin/clinic-services' });
+ fireEvent.click(await screen.findByText('کندلا ۲۰۲۱'));
+ // open the ⋮ actions menu, then ویرایش
+ fireEvent.click(await screen.findByTitle('عملیات'));
+ fireEvent.click(await screen.findByText('ویرایش'));
+
+ // insurance section + contract render inside the same (edit) modal
+ expect(await screen.findByText('پوشش بیمه')).toBeInTheDocument();
+ expect(await screen.findByText('تأمین اجتماعی')).toBeInTheDocument();
+ });
});
diff --git a/assets/admin/pages/ClinicServicesPage.tsx b/assets/admin/pages/ClinicServicesPage.tsx
index 7f34c386..7f68aa37 100644
--- a/assets/admin/pages/ClinicServicesPage.tsx
+++ b/assets/admin/pages/ClinicServicesPage.tsx
@@ -19,7 +19,7 @@ import Modal from '../components/ui/Modal';
import PriceInput from '../components/ui/PriceInput';
import ConfirmDialog from '../components/ui/ConfirmDialog';
import ServiceTariffModal from '../components/ServiceTariffModal';
-import ServiceInsuranceModal from '../components/ServiceInsuranceModal';
+import ServiceInsuranceSection from '../components/ServiceInsuranceSection';
import SearchableSelect from '../components/ui/SearchableSelect';
import FeatureGate from '../components/ui/FeatureGate';
@@ -78,7 +78,6 @@ function ClinicServicesPageInner() {
const [itemModal, setItemModal] = useState<'create' | ServiceItem | null>(null);
const [toggleItem, setToggleItem] = useState
(null);
const [tariffItem, setTariffItem] = useState(null);
- const [insuranceItem, setInsuranceItem] = useState(null);
const [search, setSearch] = useState('');
const [showInactive, setShowInactive] = useState(true);
const [menuOpen, setMenuOpen] = useState(null);
@@ -360,7 +359,6 @@ function ClinicServicesPageInner() {
-
>
@@ -574,12 +572,25 @@ function ClinicServicesPageInner() {
)}
+
+ {/* پوشش بیمه — پیوسته داخل همان مودال، فقط برای سرویس ذخیرهشده */}
+ {itemModal !== null && typeof itemModal === 'object' ? (
+