feat(admin): session edit form, payment edit/delete UI, and audit history modal

- SessionServiceCard menu gains «ویرایش» and «تاریخچه تغییرات» items.
- SessionAuditModal shows the session's change history (field, op badge,
  old->new, actor, time) from /session/{uuid}/audit-log.
- PaymentStep payment rows get edit (modal) + delete (confirm) controls for
  non-wallet payments, calling the new PATCH/DELETE payment endpoints.
- CreateStep accepts an editSession prop (prefill + PATCH); EditSessionPage
  reuses it at /patients/:recordUuid/session/:sessionUuid/edit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
hamed
2026-07-17 15:23:02 +03:30
co-authored by Claude Fable 5
parent 48579dc06f
commit f2ea2ff262
8 changed files with 287 additions and 12 deletions
+23 -2
View File
@@ -13,10 +13,15 @@ export interface SessionPaymentEntry {
export interface SessionCardData {
uuid: string;
services?: Array<{ service_name?: string; name?: string; line_total_rials?: number; price_rials?: number; quantity?: number }>;
services?: Array<{ service_item_uuid?: string; service_name?: string; name?: string; line_total_rials?: number; price_rials?: number; quantity?: number }>;
consumables?: Array<{ inventory_item_uuid?: string; item_name?: string; price_rials?: number; quantity?: number }>;
visit_price_rials?: number;
services_total_rials?: number;
session_at?: number | null;
insurance_base_id?: number | null;
insurance_supplementary_id?: number | null;
base_insurance_discount_percent?: number;
supplementary_discount_percent?: number;
doctor_name?: string | null;
final_price_rials?: number;
patient_debt_rials?: number;
@@ -50,13 +55,17 @@ function Row({ label, value, valueStyle }: { label: string; value: string; value
* pixel-for-pixel from tauri files/services/ServiceCard. Paid cards show
* «مشاهده فاکتور», unpaid ones «تکمیل پرداخت».
*/
export default function SessionServiceCard({ session, onSettle, onViewInvoice, onArchive, settling, issuing }: {
export default function SessionServiceCard({ session, onSettle, onViewInvoice, onArchive, onEdit, onViewAudit, settling, issuing }: {
session: SessionCardData;
onSettle: (uuid: string) => void;
/** کل session پاس می‌شود؛ اگر invoice_uuid نداشت، caller فاکتور را می‌سازد. */
onViewInvoice: (session: SessionCardData) => void;
/** آرشیو/خروج از آرشیو مراجعه. */
onArchive?: (session: SessionCardData, archived: boolean) => void;
/** ویرایش سرویس‌های مراجعه. */
onEdit?: (session: SessionCardData) => void;
/** نمایش تاریخچه‌ی تغییرات (Audit Log). */
onViewAudit?: (session: SessionCardData) => void;
settling?: boolean;
/** true وقتی صدور فاکتور همین لحظه در جریان است (دکمه قفل می‌شود). */
issuing?: boolean;
@@ -104,6 +113,18 @@ export default function SessionServiceCard({ session, onSettle, onViewInvoice, o
style={{ display: 'block', width: '100%', textAlign: 'right', padding: '8px 10px', fontSize: 13, background: 'transparent', border: 'none', borderRadius: 6, cursor: 'pointer', color: 'var(--text)', fontFamily: 'inherit' }}>
مشاهده فاکتور
</button>
{onEdit && (
<button type="button" onClick={() => { setMenuOpen(false); onEdit(session); }}
style={{ display: 'block', width: '100%', textAlign: 'right', padding: '8px 10px', fontSize: 13, background: 'transparent', border: 'none', borderRadius: 6, cursor: 'pointer', color: 'var(--text)', fontFamily: 'inherit' }}>
ویرایش
</button>
)}
{onViewAudit && (
<button type="button" onClick={() => { setMenuOpen(false); onViewAudit(session); }}
style={{ display: 'block', width: '100%', textAlign: 'right', padding: '8px 10px', fontSize: 13, background: 'transparent', border: 'none', borderRadius: 6, cursor: 'pointer', color: 'var(--text)', fontFamily: 'inherit' }}>
تاریخچه تغییرات
</button>
)}
{onArchive && (
<button type="button" onClick={() => { setMenuOpen(false); onArchive(session, !session.archived); }}
style={{ display: 'block', width: '100%', textAlign: 'right', padding: '8px 10px', fontSize: 13, background: 'transparent', border: 'none', borderRadius: 6, cursor: 'pointer', color: session.archived ? 'var(--text)' : '#EF4444', fontFamily: 'inherit' }}>