feat: port پرداختها (payments) tab from tauri to patient detail page
Replace the flat gateway-payment list on the patient detail «پرداختها» tab with the session-grouped accordion design ported from clinic-pro-tauri PaymentsSection: - New SessionPaymentAccordion mirrors the tauri accordion: header (service, date, final price, پرداخت شده/تسویه نشده badge) + a settlement line (date, amount, method, personnel=doctor) or the «هیچ پرداختی ثبت نشده است.» empty message. - New PaymentsTab reuses the already-fetched sessions query (real model = one payment_method per session) — no extra request, no backend change, no new API. - Add FilesServicePaymentsCheck icon (verbatim from tauri). - Remove the now-unused paymentsQ (gateway list), PAYMENT_STATUS map and the dead TabList helper (both its callers replaced by the ported card/accordion tabs). - Tests: SessionPaymentAccordion (paid/unpaid/collapsed/toggle) + updated the page payments-tab test to assert session accordions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import SessionPaymentAccordion, { type SessionPaymentData } from './SessionPaymentAccordion';
|
||||
|
||||
const paid: SessionPaymentData = {
|
||||
uuid: 's1', services: [{ service_name: 'روکش' }], final_price_rials: 2500000,
|
||||
doctor_name: 'دکتر فتحی', payment_method: 'cash', is_paid: true,
|
||||
created_at: 1700000000, updated_at: 1700003600,
|
||||
};
|
||||
const unpaid: SessionPaymentData = {
|
||||
uuid: 's2', services: [{ service_name: 'اسکیلینگ' }], final_price_rials: 1800000,
|
||||
doctor_name: 'دکتر راد', payment_method: 'pending', is_paid: false, created_at: 1700000000,
|
||||
};
|
||||
|
||||
describe('SessionPaymentAccordion', () => {
|
||||
it('shows the settled badge + settlement line (method/personnel) when expanded', () => {
|
||||
render(<SessionPaymentAccordion session={paid} expanded onToggle={() => {}} />);
|
||||
expect(screen.getByText('روکش')).toBeInTheDocument();
|
||||
expect(screen.getByText('پرداخت شده')).toBeInTheDocument();
|
||||
expect(screen.getByText('نحوه پرداخت:')).toBeInTheDocument();
|
||||
expect(screen.getByText('نقدی')).toBeInTheDocument(); // cash → نقدی
|
||||
expect(screen.getByText('دکتر فتحی')).toBeInTheDocument(); // personnel = doctor
|
||||
});
|
||||
|
||||
it('shows the unsettled badge + empty message for an unpaid session', () => {
|
||||
render(<SessionPaymentAccordion session={unpaid} expanded onToggle={() => {}} />);
|
||||
expect(screen.getByText('تسویه نشده')).toBeInTheDocument();
|
||||
expect(screen.getByText('هیچ پرداختی ثبت نشده است.')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('hides the details when collapsed', () => {
|
||||
render(<SessionPaymentAccordion session={paid} expanded={false} onToggle={() => {}} />);
|
||||
expect(screen.getByText('پرداخت شده')).toBeInTheDocument(); // header still visible
|
||||
expect(screen.queryByText('نحوه پرداخت:')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls onToggle when the summary is clicked', () => {
|
||||
const onToggle = vi.fn();
|
||||
render(<SessionPaymentAccordion session={paid} expanded={false} onToggle={onToggle} />);
|
||||
screen.getByRole('button').click();
|
||||
expect(onToggle).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user