import { useEffect, useRef, useState, type CSSProperties } from 'react'; import { formatDate, formatRial } from '../lib/utils'; import { FilesServiceSuccess, FilesServiceMore } from './icons/FilesServiceIcons'; export interface SessionPaymentEntry { uuid: string; method: string; amount_rials: number; paid_at?: number; created_at?: number; created_by_name?: string | null; } export interface SessionCardData { uuid: string; services?: Array<{ service_item_uuid?: string; service_name?: string; name?: string; line_total_rials?: number; price_rials?: number; quantity?: number }>; // مطابق SessionConsumable::toArray در بک‌اند consumables?: Array<{ uuid?: string; inventory_item_uuid?: string; item_name?: string; unit?: string; price_rials?: number; quantity?: number; line_total_rials?: 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; // تفکیک بیمه — سرور محاسبه می‌کند (PatientSession::applyShares) gross_total_rials?: number; base_insurance_rials?: number; supplementary_insurance_rials?: number; patient_share_rials?: number; remaining_rials?: number; patient_debt_rials?: number; is_paid?: boolean; invoice_uuid?: string | null; notes?: string | null; archived?: boolean; created_at?: number; // تسویه چندتکه + تخفیف (backend session settlement fields) discount_type?: 'percent' | 'fixed' | null; discount_value?: number; discount_rials?: number; applied_discount_rule_label?: string | null; paid_total_rials?: number; paid_at?: number | null; payments?: SessionPaymentEntry[]; } /** label:value row inside the service card (mirrors tauri ServiceInfoRow). */ function Row({ label, value, valueStyle }: { label: string; value: string; valueStyle?: CSSProperties }) { return (
{label}: {value}
); } /** * A patient «مراجعه» (session) card — visit + performed services — ported * pixel-for-pixel from tauri files/services/ServiceCard. Paid cards show * «مشاهده فاکتور», unpaid ones «تکمیل پرداخت». */ 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; }) { const paid = !!session.is_paid; const [menuOpen, setMenuOpen] = useState(false); const menuRef = useRef(null); useEffect(() => { if (!menuOpen) return; const onDoc = (e: MouseEvent) => { if (menuRef.current && !menuRef.current.contains(e.target as Node)) setMenuOpen(false); }; document.addEventListener('mousedown', onDoc); return () => document.removeEventListener('mousedown', onDoc); }, [menuOpen]); const names = (session.services ?? []).map((s) => s.service_name || s.name).filter(Boolean) as string[]; if ((session.visit_price_rials ?? 0) > 0) names.unshift('ویزیت'); // A «مراجعه» = the visit plus the services performed in it. const title = 'مراجعه'; const subtitle = names.length ? names.join(' - ') : 'ویزیت'; const debt = session.patient_debt_rials ?? 0; return (
{title} {session.archived && آرشیو} {subtitle}
{menuOpen && (
{onEdit && ( )} {onViewAudit && ( )} {onArchive && ( )}
)}
{!paid && }
{paid ? ( ) : ( )}
); }