feat(admin): show visit datetime and itemized cost breakdown in session details
DetailsStep now renders the appointment's visit date/time first (from session_at, falling back to created_at) and an itemized cost table (visit + each service line with its line total) plus the grand total. Extend SessionCardData with session_at, services_total_rials, and per-line price fields already returned by the session API. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,8 +12,10 @@ export interface SessionPaymentEntry {
|
||||
|
||||
export interface SessionCardData {
|
||||
uuid: string;
|
||||
services?: Array<{ service_name?: string; name?: string }>;
|
||||
services?: Array<{ service_name?: string; name?: string; line_total_rials?: number; price_rials?: number; quantity?: number }>;
|
||||
visit_price_rials?: number;
|
||||
services_total_rials?: number;
|
||||
session_at?: number | null;
|
||||
doctor_name?: string | null;
|
||||
final_price_rials?: number;
|
||||
patient_debt_rials?: number;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { toast } from 'sonner';
|
||||
import { formatRial } from '../../lib/utils';
|
||||
import { formatRial, formatDateTime } from '../../lib/utils';
|
||||
import type { SessionCardData } from '../SessionServiceCard';
|
||||
import { METHOD_LABELS } from './PaymentStep';
|
||||
import { useIssueInvoice } from '../../hooks/useIssueInvoice';
|
||||
@@ -34,13 +34,34 @@ export default function DetailsStep({ session, recordUuid, onBack, onFinish }: P
|
||||
const discountRials = session.discount_rials ?? 0;
|
||||
const debt = session.patient_debt_rials ?? 0;
|
||||
const payments = session.payments ?? [];
|
||||
const visitPrice = session.visit_price_rials ?? 0;
|
||||
const serviceNames = (session.services ?? []).map((s) => s.service_name || s.name).filter(Boolean) as string[];
|
||||
if ((session.visit_price_rials ?? 0) > 0) serviceNames.unshift('ویزیت');
|
||||
if (visitPrice > 0) serviceNames.unshift('ویزیت');
|
||||
|
||||
// زمان مراجعه: زمان واقعی نوبت؛ در نبود آن، زمان ثبت پرونده.
|
||||
const visitAt = session.session_at ?? session.created_at ?? null;
|
||||
|
||||
// آیتمهای هزینهی تفکیکشده: ویزیت + هر سرویس، با جمع کل.
|
||||
const costItems: Array<{ label: string; rials: number }> = [];
|
||||
if (visitPrice > 0) costItems.push({ label: 'ویزیت', rials: visitPrice });
|
||||
(session.services ?? []).forEach((s) => {
|
||||
costItems.push({
|
||||
label: (s.service_name || s.name) ?? 'سرویس',
|
||||
rials: s.line_total_rials ?? (s.price_rials ?? 0) * (s.quantity ?? 1),
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* گام جزییات — پورت tauri Step3Final با دیتای واقعی */}
|
||||
<div dir="rtl" className="dark:border-[#404040] dark:bg-[#222433]" style={{ padding: 16, border: '1px dashed #A7A7E0' }}>
|
||||
{visitAt && (
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, marginBottom: 16 }}>
|
||||
<span className="dark:text-[#A1A1A1]" style={{ fontSize: 13, color: '#616161' }}>تاریخ و ساعت مراجعه:</span>
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 14, fontWeight: 600, color: '#2f2f2f' }}>{formatDateTime(visitAt)}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 32, marginBottom: 16 }}>
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 14, fontWeight: 500, color: '#2f2f2f' }}>
|
||||
{serviceNames.length ? serviceNames.join(' - ') : 'ویزیت'}
|
||||
@@ -49,6 +70,21 @@ export default function DetailsStep({ session, recordUuid, onBack, onFinish }: P
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 14, fontWeight: 500, color: '#525252' }}>{session.doctor_name || '—'}</span>
|
||||
</div>
|
||||
|
||||
{costItems.length > 0 && (
|
||||
<div className="dark:border-[#404040]" style={{ marginBottom: 16, borderTop: '1px solid #EEE', borderBottom: '1px solid #EEE', padding: '4px 0' }}>
|
||||
{costItems.map((it, i) => (
|
||||
<div key={i} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '6px 0' }}>
|
||||
<span className="dark:text-[#A1A1A1]" style={{ fontSize: 13, color: '#616161' }}>{it.label}</span>
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 14, fontWeight: 500, color: '#525252' }}>{formatRial(it.rials)}</span>
|
||||
</div>
|
||||
))}
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '8px 0 4px', borderTop: '1px dashed #E0E0E0' }}>
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 13, fontWeight: 700, color: '#2f2f2f' }}>جمع کل</span>
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 14, fontWeight: 700, color: '#2f2f2f' }}>{formatRial(finalPrice)}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', gap: 72, marginBottom: 16 }}>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 14, fontWeight: 500, color: '#525252' }}>هزینه سرویس:</span>
|
||||
|
||||
Reference in New Issue
Block a user