feat: enhance resource calendar validation and UI
- Implement real-time validation for overlapping shifts in the ResourceWorkingHoursPanel. - Remove the copy shift functionality to simplify the UI and prevent confusion. - Introduce ResourceExceptionsCard to manage resource exceptions, including leave and maintenance. - Update ClinicAppointmentSettingsPage to utilize new components and improve tab navigation for resource management. - Add comprehensive validation tests for resource calendar to ensure overlapping shifts are correctly handled. - Update API documentation to reflect new validation error messages and rules.
This commit is contained in:
@@ -16,8 +16,11 @@ vi.mock('../components/resources/ResourceWorkingHoursPanel', () => ({
|
||||
default: ({ resourceUuid }: { resourceUuid?: string }) => <div>ساعات کاری {resourceUuid}</div>,
|
||||
DAY_LABELS: [],
|
||||
}));
|
||||
vi.mock('../components/resources/ResourceExceptionsPanel', () => ({
|
||||
default: ({ resourceUuid }: { resourceUuid?: string }) => <div>تعطیلات {resourceUuid}</div>,
|
||||
vi.mock('../components/resources/ResourceExceptionsCard', () => ({
|
||||
default: ({ resourceUuid }: { resourceUuid?: string }) => <div>مرخصی {resourceUuid}</div>,
|
||||
}));
|
||||
vi.mock('../components/holidays/NationalHolidaysCard', () => ({
|
||||
default: () => <div>تعطیلات رسمی سال</div>,
|
||||
}));
|
||||
|
||||
let resources: Array<{ uuid: string; name: string; type_name: string }> = [];
|
||||
@@ -60,17 +63,65 @@ describe('ClinicAppointmentSettingsPage', () => {
|
||||
});
|
||||
|
||||
/** منبع همانجایی مدیریت میشود که برنامهٔ پزشک — نه در یک صفحهٔ جدا. */
|
||||
it('تب منابع، ساعت کاری و تعطیلات منبع را میآورد', async () => {
|
||||
it('تب منابع، برنامهٔ کاری منبع را میآورد', async () => {
|
||||
const user = userEvent.setup();
|
||||
renderWithProviders(<ClinicAppointmentSettingsPage />);
|
||||
|
||||
await user.click(screen.getByRole('button', { name: 'منابع' }));
|
||||
|
||||
await waitFor(() => expect(screen.getByText('ساعات کاری r-1')).toBeInTheDocument());
|
||||
expect(screen.getByText('تعطیلات r-1')).toBeInTheDocument();
|
||||
expect(screen.queryByText('برنامهٔ پزشک')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
/**
|
||||
* سه تب، نه سه بخشِ پشتسرهم: هر سه یک سؤال را جواب میدهند ولی همزمان لازم
|
||||
* نیستند و چیدنشان زیر هم صفحه را سه برابر بلند میکرد.
|
||||
*/
|
||||
it('شیفت، تعطیلات و مرخصی سه تب مجزا هستند', async () => {
|
||||
const user = userEvent.setup();
|
||||
renderWithProviders(<ClinicAppointmentSettingsPage />, {
|
||||
route: '/admin/settings/appointment-settings?scope=resources',
|
||||
});
|
||||
|
||||
// پیشفرض روی شیفت هفتگی است — کارِ اصلی صفحه.
|
||||
await waitFor(() => expect(screen.getByText('ساعات کاری r-1')).toBeInTheDocument());
|
||||
expect(screen.queryByText('تعطیلات رسمی سال')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('مرخصی r-1')).not.toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole('button', { name: 'تعطیلات رسمی' }));
|
||||
expect(await screen.findByText('تعطیلات رسمی سال')).toBeInTheDocument();
|
||||
expect(screen.queryByText('ساعات کاری r-1')).not.toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole('button', { name: 'مرخصی و سرویس' }));
|
||||
expect(await screen.findByText('مرخصی r-1')).toBeInTheDocument();
|
||||
expect(screen.queryByText('تعطیلات رسمی سال')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
/** تب از URL خوانده میشود، پس رفرش و «بازگشت» همان نما را نگه میدارند. */
|
||||
it('تب برنامهٔ کاری را از URL میخواند', async () => {
|
||||
renderWithProviders(<ClinicAppointmentSettingsPage />, {
|
||||
route: '/admin/settings/appointment-settings?scope=resources&calendarTab=exceptions',
|
||||
});
|
||||
|
||||
expect(await screen.findByText('مرخصی r-1')).toBeInTheDocument();
|
||||
expect(screen.queryByText('ساعات کاری r-1')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
/** پیشنمایش دو هفته در این صفحه کاربردی ندارد و فقط ارتفاع اضافه میکرد. */
|
||||
it('پیشنمایش دو هفته را نشان نمیدهد', async () => {
|
||||
const user = userEvent.setup();
|
||||
renderWithProviders(<ClinicAppointmentSettingsPage />, {
|
||||
route: '/admin/settings/appointment-settings?scope=resources',
|
||||
});
|
||||
|
||||
await waitFor(() => expect(screen.getByText('ساعات کاری r-1')).toBeInTheDocument());
|
||||
expect(screen.queryByText('پیشنمایش دو هفته')).not.toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole('button', { name: 'مرخصی و سرویس' }));
|
||||
await screen.findByText('مرخصی r-1');
|
||||
expect(screen.queryByText('پیشنمایش دو هفته')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('بین منابع جابهجا میشود', async () => {
|
||||
const user = userEvent.setup();
|
||||
renderWithProviders(<ClinicAppointmentSettingsPage />);
|
||||
|
||||
Reference in New Issue
Block a user