import { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { CheckIcon, XMarkIcon, PaperAirplaneIcon, BanknotesIcon } from '@heroicons/react/24/outline'; import { toast } from 'sonner'; import { api } from '../lib/api'; import { formatRial, formatNumber, formatDate } from '../lib/utils'; import PageHeader from '../components/ui/PageHeader'; import Modal from '../components/ui/Modal'; import SearchableSelect from '../components/ui/SearchableSelect'; import FeatureGate from '../components/ui/FeatureGate'; interface ClaimItem { invoice_item_id: number; claimed_rials: number; approved_rials: number | null; title: string | null; is_visit: boolean; quantity: number; total_rials: number | null; visit_date: number | null; } interface Claim { uuid: string; insurance_id: number; insurance_name: string | null; insurance_kind: string; total_claimed_rials: number; total_approved_rials: number | null; total_paid_rials: number | null; status: string; reject_reason: string | null; items: ClaimItem[]; } interface DebtRow { insurance_id: number; insurance_name: string | null; claimed: number; approved: number; paid: number; debt: number; } const STATUS_META: Record = { pending: { label: 'در انتظار', cls: 'gray' }, submitted: { label: 'ارسال‌شده', cls: 'blue' }, approved: { label: 'تأییدشده', cls: 'amber' }, rejected: { label: 'ردشده', cls: 'red' }, paid: { label: 'پرداخت‌شده', cls: 'green' }, }; const KIND_LABEL: Record = { base: 'پایه', supplementary: 'تکمیلی' }; const STATUS_FILTERS = ['', 'pending', 'submitted', 'approved', 'rejected', 'paid']; export default function ClaimsPage() { const qc = useQueryClient(); const [statusFilter, setStatusFilter] = useState(''); const [rejectTarget, setRejectTarget] = useState(null); const [rejectReason, setRejectReason] = useState(''); const claimsQuery = useQuery<{ data: { data: Claim[] } }>({ queryKey: ['claims', statusFilter], queryFn: () => api.get(`/api/v1/billing/claims${statusFilter ? `?status=${statusFilter}` : ''}`), }); const debtQuery = useQuery<{ data: { data: DebtRow[] } }>({ queryKey: ['insurance-debt'], queryFn: () => api.get('/api/v1/billing/reports/insurance-debt'), }); const claims = (claimsQuery.data as any)?.data?.data ?? []; const debt = (debtQuery.data as any)?.data?.data ?? []; const transitionMut = useMutation({ mutationFn: ({ uuid, action, body }: { uuid: string; action: string; body?: object }) => api.post(`/api/v1/billing/claims/${uuid}/${action}`, body ?? {}), onSuccess: () => { toast.success('وضعیت مطالبه به‌روزرسانی شد'); setRejectTarget(null); setRejectReason(''); qc.invalidateQueries({ queryKey: ['claims'] }); qc.invalidateQueries({ queryKey: ['insurance-debt'] }); }, onError: (e: Error) => toast.error(e.message), }); return (

بدهی بیمه‌ها

{debtQuery.isLoading ? (
در حال بارگذاری...
) : debt.length === 0 ? (
بدهی‌ای ثبت نشده است.
) : (
{debt.map((d: DebtRow) => (
{d.insurance_name ?? `بیمه #${formatNumber(d.insurance_id)}`} ادعا {formatRial(d.claimed)} · پرداخت {formatRial(d.paid)} 0 ? 'var(--danger)' : 'var(--success, #16a34a)' }}>بدهی {formatRial(d.debt)}
))}
)}

مطالبات

({ value: s, label: s === '' ? 'همه وضعیت‌ها' : STATUS_META[s]?.label ?? s }))} value={statusFilter} onChange={(v) => setStatusFilter(v ? String(v) : '')} placeholder="همه وضعیت‌ها" />
{claimsQuery.isLoading ? (
در حال بارگذاری...
) : claims.length === 0 ? (
مطالبه‌ای یافت نشد.
) : (
{claims.map((c: Claim) => { const meta = STATUS_META[c.status] ?? { label: c.status, cls: 'gray' }; return (
{c.insurance_name ?? `بیمه #${formatNumber(c.insurance_id)}`} {KIND_LABEL[c.insurance_kind] ?? c.insurance_kind} {meta.label}
ادعا {formatRial(c.total_claimed_rials)} {c.total_approved_rials != null && ` · تأیید ${formatRial(c.total_approved_rials)}`} {c.total_paid_rials != null && ` · پرداخت ${formatRial(c.total_paid_rials)}`} {c.reject_reason && ` · دلیل رد: ${c.reject_reason}`}
{c.status === 'pending' && ( )} {c.status === 'submitted' && ( <> )} {c.status === 'approved' && ( )}
{c.items.length > 0 && (
{c.items.map((it, idx) => ( ))}
شرح تاریخ مراجعه تعداد مبلغ کل سهم بیمه (ادعا) تأییدشده
{it.is_visit ? 'ویزیت' : 'خدمت'} {it.title ?? '—'} {it.visit_date ? formatDate(it.visit_date) : '—'} {formatNumber(it.quantity)} {it.total_rials != null ? formatRial(it.total_rials) : '—'} {formatRial(it.claimed_rials)} {it.approved_rials != null ? formatRial(it.approved_rials) : '—'}
)}
); })}
)}
setRejectTarget(null)} title="رد مطالبه" footer={ <> } >