import { useState } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { ChevronDownIcon } from '@heroicons/react/24/outline'; import { toast } from 'sonner'; import { api } from '../lib/api'; import type { ApiResponse } from '../lib/api'; import type { PatientRecord } from '../types'; import { formatRial } from '../lib/utils'; import type { SessionCardData } from '../components/SessionServiceCard'; import SessionStepper from '../components/SessionStepper'; import SearchableSelect from '../components/ui/SearchableSelect'; import PersianDateInput from '../components/ui/PersianDateInput'; import { ArrowLeftPH, ArrowLeftD, CloseModalD, Step2PaymentCard, FilesServiceBalanceWallet, TrashRed, } from '../components/icons/FilesServiceIcons'; /** روش‌های پرداخت — همان چهار گزینه‌ی آکاردئون tauri Step2Payment. */ const METHODS: { key: string; label: string }[] = [ { key: 'wallet', label: 'پرداخت از طریق کیف پول' }, { key: 'pos', label: 'پرداخت از طریق کارت خوان' }, { key: 'cash', label: 'پرداخت نقدی' }, { key: 'card', label: 'کارت به کارت' }, ]; const METHOD_LABELS: Record = { wallet: 'پرداخت از کیف پول', pos: 'پرداخت کارتخوان', cash: 'پرداخت نقدی', card: 'کارت به کارت', }; const todayISO = () => new Date().toISOString().slice(0, 10); /** YYYY-MM-DD → unix (ظهر همان روز تا با هر timezone یک روز بماند) */ const isoToUnix = (iso: string) => Math.floor(new Date(`${iso}T12:00:00`).getTime() / 1000); /** * تکمیل پرداخت مراجعه — پورت صفحه‌ی tauri /files/create-service در حالت payment: * استپر دوگامی «پرداخت ← جزییات» با تخفیف تسویه، پرداخت چندتکه و تاریخ پرداخت. */ export default function SessionPaymentPage() { const { recordUuid = '', sessionUuid = '' } = useParams(); const nav = useNavigate(); const qc = useQueryClient(); const steps = ['پرداخت', 'جزییات']; const [activeStep, setActiveStep] = useState(0); const [discountType, setDiscountType] = useState(''); const [discountValue, setDiscountValue] = useState(''); const [paymentDate, setPaymentDate] = useState(todayISO()); const [expanded, setExpanded] = useState(null); const [amount, setAmount] = useState(''); const recordQ = useQuery>({ queryKey: ['patient-detail', recordUuid], queryFn: () => api.get(`/api/v1/patient/${recordUuid}`), enabled: !!recordUuid, }); const record = recordQ.data?.data as PatientRecord | undefined; const patientName = record?.user_name || record?.profile?.full_name || '—'; const sessionsQ = useQuery>({ queryKey: ['patient-sessions', recordUuid], queryFn: () => api.get(`/api/v1/patient/${recordUuid}/sessions`), enabled: !!recordUuid, }); const session = (sessionsQ.data?.data ?? []).find((s) => s.uuid === sessionUuid); const walletQ = useQuery>({ queryKey: ['patient-wallet', recordUuid], queryFn: () => api.get(`/api/v1/patient/${recordUuid}/wallet`), enabled: !!recordUuid, }); const walletBalance = (walletQ.data?.data as any)?.balance_rials ?? 0; const invalidate = () => { qc.invalidateQueries({ queryKey: ['patient-sessions', recordUuid] }); qc.invalidateQueries({ queryKey: ['patient-wallet', recordUuid] }); }; const discountMut = useMutation({ mutationFn: (body: object) => api.patch(`/api/v1/session/${sessionUuid}`, body), onSuccess: () => { invalidate(); toast.success('تخفیف به‌روزرسانی شد'); }, onError: (e: Error) => toast.error(e.message), }); const payMut = useMutation({ mutationFn: (body: object) => api.post(`/api/v1/session/${sessionUuid}/payments`, body), onSuccess: () => { invalidate(); setAmount(''); toast.success('پرداخت ثبت شد'); }, onError: (e: Error) => toast.error(e.message), }); const applyDiscount = () => { if (!discountType || !discountValue) return; discountMut.mutate({ discount_type: discountType, discount_value: Number(discountValue) }); }; const removeDiscount = () => { setDiscountType(''); setDiscountValue(''); discountMut.mutate({ discount_type: null }); }; const submitPayment = (method: string) => { if (!amount) return; payMut.mutate({ method, amount_rials: Number(amount), paid_at: isoToUnix(paymentDate) }); }; const finalPrice = session?.final_price_rials ?? 0; const discountRials = session?.discount_rials ?? 0; const debt = session?.patient_debt_rials ?? 0; const payments = session?.payments ?? []; const serviceNames = (session?.services ?? []).map((s) => s.service_name || s.name).filter(Boolean) as string[]; if ((session?.visit_price_rials ?? 0) > 0) serviceNames.unshift('ویزیت'); const finish = () => nav(`/admin/patients/${recordUuid}?tab=services`); if (sessionsQ.isLoading) { return
در حال بارگذاری...
; } if (!session) { return
مراجعه یافت نشد
; } const fieldLabel: React.CSSProperties = { fontSize: 14, color: '#6B7280', marginBottom: 8, display: 'block' }; const primaryBtn: React.CSSProperties = { background: '#5559CE', color: '#fff', border: 'none', borderRadius: 4, height: 46, fontSize: 14, fontWeight: 500, cursor: 'pointer' }; const ghostBtn: React.CSSProperties = { background: 'transparent', color: '#5559CE', border: '1px solid #5559CE', borderRadius: 4, height: 46, fontSize: 14, fontWeight: 500, cursor: 'pointer' }; return (
{/* breadcrumb — tauri AddService header */}
nav(-1)} className="bg-white dark:bg-[#222433]" style={{ display: 'flex', alignItems: 'center', gap: 4, padding: '6px 8px', borderRadius: 12, cursor: 'pointer' }} > بازگشت
پرونده {patientName}
{/* card — tauri width 748 centered */}
{activeStep === 0 ? ( <> {/* هزینه سرویس */}
هزینه سرویس: {formatRial(finalPrice)}
{/* تخفیف — port of tauri DiscountInput (نوع + مقدار + ثبت) */} تخفیف:
setDiscountType(v ? String(v) : '')} placeholder="مبلغ تخفیف" />
setDiscountValue(e.target.value)} style={{ flex: 1, minWidth: 0, height: 40, padding: '0 12px', fontSize: 13, border: 'none', outline: 'none', background: 'transparent', color: 'inherit' }} />
حذف تخفیف

مبلغ تخفیف:{' '} {formatRial(discountRials)}

{/* تاریخ پرداخت */} تاریخ پرداخت {/* روش‌های پرداخت */} انتخاب روش های پرداخت:
موجودی کیف پول:
{formatRial(walletBalance)}
{/* آکاردئون چهار روش — باز شدن هر روش: مبلغ + ثبت پرداخت */}
{METHODS.map((m) => { const open = expanded === m.key; return (
{open && (
setAmount(e.target.value)} style={{ flex: 1, height: 40 }} />
)}
); })}
{/* پرداخت شده‌ها — باکس خط‌چین tauri */}
پرداخت شده ها: {payments.length === 0 ? ( پرداختی ثبت نشده است ) : (
{payments.map((p) => (
{METHOD_LABELS[p.method] ?? p.method} مبلغ : {formatRial(p.amount_rials)}
))}
)}
مبلغ باقی‌مانده : {formatRial(debt)}
{/* ACTIONS */}
) : ( <> {/* گام جزییات — پورت tauri Step3Final با دیتای واقعی */}
{serviceNames.length ? serviceNames.join(' - ') : 'ویزیت'} {session.doctor_name || '—'}
هزینه سرویس: {formatRial(finalPrice)} تخفیف: {formatRial(discountRials)}
پرداخت شده ها: {payments.length === 0 ? ( پرداختی ثبت نشده است ) : payments.map((p) => (
{METHOD_LABELS[p.method] ?? p.method} مبلغ: {formatRial(p.amount_rials)}
))}
مبلغ باقی مانده: {formatRial(debt)}
)}
); }