import { useMemo, useState, type ReactNode } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { PlusIcon, PencilIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline'; import { toast } from 'sonner'; import { api } from '../lib/api'; import { formatRial } from '../lib/utils'; import InsuranceModal, { Contract, InsuranceOption, KIND_LABEL, buildInsurancePayload } from './InsuranceModal'; /** Case-insensitive filter over insurance name (and code) — the "جستجو در بیمه ها..." box. */ export function filterInsurances(list: Contract[], query: string): Contract[] { const q = query.trim().toLowerCase(); if (!q) return list; return list.filter((c) => (c.insurance_name ?? '').toLowerCase().includes(q) || String(c.insurance_id).includes(q), ); } export default function TenantInsuranceContracts() { const qc = useQueryClient(); const [modalOpen, setModalOpen] = useState(false); const [editContract, setEditContract] = useState(null); const [search, setSearch] = useState(''); const contractsQuery = useQuery({ queryKey: ['tenant-insurances'], queryFn: () => api.get('/api/v1/billing/tenant-insurances'), }); const pricingQuery = useQuery({ queryKey: ['insurance-pricing'], queryFn: () => api.get('/api/v1/insurance-pricing'), }); const contracts: Contract[] = (contractsQuery.data as any)?.data?.data ?? []; const allInsurances: InsuranceOption[] = (pricingQuery.data as any)?.data?.insurances ?? []; const activeIds = new Set(contracts.map((c) => c.insurance_id)); const available = allInsurances.filter((i) => !activeIds.has(i.insurance_id)); const rows = useMemo(() => filterInsurances(contracts, search), [contracts, search]); const invalidate = () => qc.invalidateQueries({ queryKey: ['tenant-insurances'] }); const saveMut = useMutation({ mutationFn: (payload: ReturnType) => editContract ? api.patch(`/api/v1/billing/tenant-insurances/${editContract.uuid}`, payload) : api.post('/api/v1/billing/tenant-insurances', payload), onSuccess: () => { toast.success(editContract ? 'قرارداد بیمه ویرایش شد' : 'قرارداد بیمه فعال شد'); closeModal(); invalidate(); }, onError: (e: Error) => toast.error(e.message), }); const toggleMut = useMutation({ mutationFn: (c: Contract) => api.patch(`/api/v1/billing/tenant-insurances/${c.uuid}`, { is_active: !c.is_active }), onSuccess: () => invalidate(), onError: (e: Error) => toast.error(e.message), }); const openAdd = () => { setEditContract(null); setModalOpen(true); }; const openEdit = (c: Contract) => { setEditContract(c); setModalOpen(true); }; const closeModal = () => { setModalOpen(false); setEditContract(null); }; return (

مدیریت بیمه

setSearch(e.target.value)} />
{contractsQuery.isLoading ? (
در حال بارگذاری...
) : rows.length === 0 ? (
{search ? 'بیمه‌ای یافت نشد.' : 'هنوز با هیچ بیمه‌ای قرارداد ندارید.'}
) : ( <> {/* Desktop table */}
{rows.map((c, i) => ( ))}
ردیف نام بیمه کد نوع بیمه وضعیت عملیات
{i + 1} {c.insurance_name ?? `#${c.insurance_id}`}
پوشش {c.coverage_percent}٪ {c.franchise_rials > 0 && ` · فرانشیز ${formatRial(c.franchise_rials)}`} {c.annual_ceiling_rials != null && ` · سقف ${formatRial(c.annual_ceiling_rials)}`}
{c.insurance_id} {KIND_LABEL[c.insurance_kind ?? ''] ?? c.insurance_kind ?? '—'} toggleMut.mutate(c)} disabled={toggleMut.isPending} />
{/* Mobile cards */}
{rows.map((c) => (
{c.insurance_name ?? `#${c.insurance_id}`}
{c.insurance_id}} /> toggleMut.mutate(c)} disabled={toggleMut.isPending} />} />
))}
)} saveMut.mutate(payload)} isPending={saveMut.isPending} />
); } function Row({ label, value }: { label: string; value: ReactNode }) { return (
{label}: {value}
); } function StatusToggle({ contract, onToggle, disabled }: { contract: Contract; onToggle: () => void; disabled?: boolean }) { return ( ); }