import { useQuery } from '@tanstack/react-query'; import { api } from '../lib/api'; import type { ApiResponse } from '../lib/api'; import Modal from './ui/Modal'; import { formatDate, formatDateTime, formatRial } from '../lib/utils'; import { METHOD_LABELS } from './session/PaymentStep'; interface InvoiceItem { uuid: string; title: string; quantity: number; total_rials: number; patient_rials: number } interface SessionPayment { uuid: string; method: string; amount_rials: number; paid_at: number; created_by_name: string | null } interface SessionConsumable { uuid: string; item_name: string; quantity: number; line_total_rials: number } interface SessionData { session_at: number | null; paid_at: number | null; services_total_rials: number; consumables_total_rials: number; discount_rials: number; final_price_rials: number; paid_total_rials: number; payments: SessionPayment[]; consumables: SessionConsumable[]; } interface Invoice { uuid: string; status: string; issued_at: number; total_rials: number; base_insurance_rials: number; supplementary_rials: number; patient_rials: number; items: InvoiceItem[]; session?: SessionData | null; } const STATUS_LABEL: Record = { paid: 'پرداخت شده', finalized: 'بدهکار', draft: 'پیش‌نویس', void: 'باطل' }; /** A titled table block — mirrors tauri InvoiceSummary `SectionTable`. */ function SectionTable({ title, cols, rows }: { title: string; cols: string[]; rows: React.ReactNode[][] }) { return (
{title}
{cols.map((c, i) => ( ))} {rows.map((row, i) => ( {row.map((cell, j) => ( ))} ))}
{c}
{cell}
); } /** خلاصه فاکتور — invoice summary, ported pixel-for-pixel from tauri InvoiceSummary. */ export default function InvoiceSummaryModal({ invoiceUuid, onClose }: { invoiceUuid: string | null; onClose: () => void }) { const { data, isLoading } = useQuery>({ queryKey: ['invoice', invoiceUuid], queryFn: () => api.get(`/api/v1/billing/invoices/${invoiceUuid}`), enabled: !!invoiceUuid, }); // billing show wraps as { data: { data: invoice } } const inv = ((data?.data as any)?.data ?? data?.data ?? null) as Invoice | null; const session = inv?.session ?? null; const paid = inv?.status === 'paid'; // با session: مبالغ واقعی پرداخت؛ بدون آن (فاکتور قدیمی): heuristic قبلی. const remaining = session ? session.final_price_rials - session.paid_total_rials : inv ? (paid ? 0 : inv.patient_rials) : 0; const paidAmount = session ? session.paid_total_rials : inv ? inv.total_rials - remaining : 0; return ( {isLoading || !inv ? (
در حال بارگذاری…
) : (
[it.title, it.quantity, formatRial(it.total_rials)]) : [['—', '—', '—']]} /> {session && ( [c.item_name, c.quantity, formatRial(c.line_total_rials)]) : [['-', '-', '-']]} /> )} {session ? ( 0 ? formatRial(session.discount_rials) : '-', formatRial(inv.base_insurance_rials), formatRial(inv.supplementary_rials), formatRial(session.final_price_rials), ]]} /> ) : ( )} {session && ( [ i + 1, METHOD_LABELS[p.method] ?? p.method, formatRial(p.amount_rials), p.paid_at ? formatDateTime(p.paid_at) : '-', p.created_by_name ?? '-', ]) : [['-', '-', '-', '-', '-']]} /> )} 0 ? '#d32f2f' : '#388e3c', fontWeight: 600 }}>{formatRial(remaining)}, ]]} />
)}
); }