Files
clinicpro/assets/admin/components/AppointmentTurnCard.test.tsx
T
hamedandClaude Opus 4.8 1a783971c9 feat: port نوبت‌ها (appointments) tab from tauri to patient detail page
Replace the placeholder row list on the patient detail «نوبت‌ها» tab with the
card-grid design ported pixel-for-pixel from clinic-pro-tauri TurnsSection:

- New AppointmentTurnCard mirrors tauri TurnsCard (success icon, title, date/time
  chips, personnel, status). Status uses the live AppointmentStatusDropdown
  instead of the tauri mock.
- New AppointmentsTab in PatientDetailPage: sort/filter toolbar (client-side) +
  reserve/new buttons linking to existing /admin/appointments pages + card grid.
- Add CalendarD/ClockP/UserD/StatusGlobe icons (verbatim from tauri).
- Backend: expose version on GET /patient/{uuid}/appointments so the status
  dropdown can optimistic-lock. No new endpoint.
- Tests: PatientAppointmentsTest (shape/version/order/empty/ownership) +
  AppointmentTurnCard + tab data/empty cases. docs/api/patient.md updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 11:30:12 +03:30

39 lines
1.8 KiB
TypeScript

import { describe, it, expect, vi } from 'vitest';
import { screen } from '@testing-library/react';
import { renderWithProviders } from '../test/utils';
vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn() } }));
vi.mock('../lib/api', () => ({
api: { get: vi.fn(), post: vi.fn(), patch: vi.fn(), put: vi.fn(), delete: vi.fn() },
ApiError: class extends Error {},
}));
import AppointmentTurnCard, { type AppointmentCardData } from './AppointmentTurnCard';
const base: AppointmentCardData = {
uuid: 'a1', starts_at: 1754000000, status: 'confirmed', version: 1,
doctor_name: 'دکتر ژیلا فتحی', service_name: null,
};
describe('AppointmentTurnCard', () => {
it('renders title, date/time labels, doctor and the live status label', () => {
renderWithProviders(<AppointmentTurnCard appointment={base} queryKey={['x']} />);
expect(screen.getByText('نوبت')).toBeInTheDocument(); // no service → generic title
expect(screen.getByText('تاریخ:')).toBeInTheDocument();
expect(screen.getByText('ساعت:')).toBeInTheDocument();
expect(screen.getByText('پرسنل:')).toBeInTheDocument();
expect(screen.getByText('دکتر ژیلا فتحی')).toBeInTheDocument();
expect(screen.getByText('قطعی شده')).toBeInTheDocument(); // confirmed via STATUS_META
});
it('falls back to «—» when the doctor is missing', () => {
renderWithProviders(<AppointmentTurnCard appointment={{ ...base, doctor_name: null }} queryKey={['x']} />);
expect(screen.getByText('—')).toBeInTheDocument();
});
it('prefers the service name as the title when present', () => {
renderWithProviders(<AppointmentTurnCard appointment={{ ...base, service_name: 'لیزر' }} queryKey={['x']} />);
expect(screen.getByText('لیزر')).toBeInTheDocument();
});
});