Files
clinicpro/assets/admin/components/paymentMethods/PaymentMethodHead.tsx
T
hamedandClaude Opus 4.8 b459d082a4 feat: port payment management tab from tauri to admin dashboard
Add per-clinic payment methods (bank accounts + POS/card-reader devices)
under the "مدیریت پرداخت" settings tab at /admin/my-financial, ported from
clinic-pro-tauri's mock-only PaymentManagement tab into a real persisted
feature. These records are referenceable (by uuid) from patient invoices to
record which method a service payment was made with.

Backend (new src/PaymentMethod domain):
- BankAccount + Pos entities, repositories, PaymentMethodService (validation,
  ownership scoping, create/update/toggle logic).
- Thin PaymentMethodController exposing /api/v1/my/payment-methods/{bank-accounts,pos}
  (GET/POST/PUT + PATCH .../status), guarded to clinic/doctor/secretary/admin.
- Migration for bank_accounts + pos_devices tables.
- Functional tests (success + validation/404/403 + empty boundaries).
- docs/api/payment-method.md.

Frontend:
- Replace MyFinancialPage content with the payment-management UI (two tabs,
  tables, add/edit modals, status toggle) using the admin design system.
- usePaymentMethods hook (TanStack Query) + presentational components.
- Update page test to cover tabs, data, empty state and the add modal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 11:39:32 +03:30

53 lines
1.7 KiB
TypeScript

import React from 'react';
import { PlusIcon } from '@heroicons/react/24/outline';
export type PaymentTab = 'bank' | 'pos';
/**
* سربرگ صفحهٔ مدیریت پرداخت — پورت مبدأ PaymentManagement/Head.jsx.
* تیتر + سوییچ تب (حساب بانکی / کارت خوان) + دکمهٔ افزودن.
*/
export default function PaymentMethodHead({
activeTab,
onTabChange,
onAdd,
}: {
activeTab: PaymentTab;
onTabChange: (tab: PaymentTab) => void;
onAdd: () => void;
}) {
return (
<div style={{ marginBottom: 20 }}>
<h2 style={{ fontSize: 20, fontWeight: 700, color: 'var(--text)', margin: '0 0 16px' }}>
مدیریت پرداخت‌ها
</h2>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>
<div className="seg" role="tablist">
<button
type="button"
role="tab"
aria-selected={activeTab === 'bank'}
className={activeTab === 'bank' ? 'on' : ''}
onClick={() => onTabChange('bank')}
>
حساب بانکی
</button>
<button
type="button"
role="tab"
aria-selected={activeTab === 'pos'}
className={activeTab === 'pos' ? 'on' : ''}
onClick={() => onTabChange('pos')}
>
کارت خوان
</button>
</div>
<button className="btn primary" onClick={onAdd}>
<PlusIcon style={{ width: 16 }} />
{activeTab === 'bank' ? 'افزودن حساب بانکی' : 'افزودن کارت خوان'}
</button>
</div>
</div>
);
}