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:
hamed
2026-07-16 11:40:51 +03:30
co-authored by Claude Opus 4.8
parent b82ab4db9c
commit 069189863c
5 changed files with 196 additions and 40 deletions
@@ -146,12 +146,16 @@ describe('PatientDetailPage (پرونده تب‌دار)', () => {
expect(link).toHaveAttribute('href', '/admin/patients/r1/session/new');
});
it('lists patient payments with status label on the payments tab', async () => {
it('groups payments by مراجعه (session) accordions on the پرداخت‌ها tab', async () => {
renderDetail();
await loaded();
fireEvent.click(screen.getByText('پرداخت‌ها'));
expect(await screen.findByText('موفق')).toBeInTheDocument();
expect(screen.getByText(/mellat/)).toBeInTheDocument();
// settlement badges from the two seeded sessions (s1 unpaid, s2 paid)
expect(await screen.findByText('پرداخت شده')).toBeInTheDocument();
expect(screen.getByText('تسویه نشده')).toBeInTheDocument();
expect(screen.getByText('روکش')).toBeInTheDocument(); // paid session header
// first (unpaid) panel is open by default → empty settlement message
expect(screen.getByText('هیچ پرداختی ثبت نشده است.')).toBeInTheDocument();
});
it('shows wallet balance on the wallet tab', async () => {