import { useState } from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { TrashIcon } from '@heroicons/react/24/outline'; import { toast } from 'sonner'; import { api } from '../lib/api'; import type { ApiResponse } from '../lib/api'; import { formatDate, formatRial, tomanToRial } from '../lib/utils'; import PageHeader from '../components/ui/PageHeader'; import StatCard from '../components/ui/StatCard'; import SearchableSelect from '../components/ui/SearchableSelect'; import PriceInput from '../components/ui/PriceInput'; import DataTable, { Column } from '../components/ui/DataTable'; interface IbanItem { id: string; iban: string; bank_name: string | null; owner_name: string | null; verified: boolean } interface SecretaryMe { bank_account: IbanItem[] | null } interface SettlementRow { uuid: string; amount_rials: number; status: string; created_at: number; bank_account?: { iban?: string } | null; } const STATUS_LABEL: Record = { pending: 'در انتظار بررسی', approved: 'تأییدشده', rejected: 'رد شده', paid: 'پرداخت‌شده', }; /** unwrap پاسخ‌های احتمالاً تودرتوی `success(['data' => …])`. */ const unwrap = (res: ApiResponse | undefined): T | undefined => ((res?.data as any)?.data ?? res?.data) as T | undefined; /** تسویه حساب منشی: موجودی، مدیریت شبا و درخواست برداشت — الگوی پنل نماینده. */ export default function SecretarySettlementPage() { const qc = useQueryClient(); const [amountToman, setAmountToman] = useState(0); const [ibanId, setIbanId] = useState(''); const [newIban, setNewIban] = useState(''); const [bankName, setBankName] = useState(''); const balanceQ = useQuery>({ queryKey: ['wallet-balance'], queryFn: () => api.get('/api/v1/wallet/balance'), }); const balance = unwrap(balanceQ.data)?.balance_rials ?? 0; const meQ = useQuery>({ queryKey: ['secretary-me'], queryFn: () => api.get('/api/v1/secretary/me'), }); const ibans = unwrap(meQ.data)?.bank_account ?? []; const verifiedIbans = ibans.filter((b) => b.verified); const listQ = useQuery>({ queryKey: ['secretary-settlements'], queryFn: () => api.get('/api/v1/settlement?page=1&limit=15'), }); const settlements = unwrap(listQ.data) ?? []; const invalidateWallet = () => { qc.invalidateQueries({ queryKey: ['wallet-balance'] }); qc.invalidateQueries({ queryKey: ['secretary-settlements'] }); }; const addIbanMut = useMutation({ mutationFn: () => api.post('/api/v1/secretary/iban', { iban: newIban.trim().toUpperCase(), ...(bankName.trim() ? { bank_name: bankName.trim() } : {}), }), onSuccess: () => { toast.success('شماره شبا ثبت شد؛ پس از تأیید ادمین قابل استفاده است'); setNewIban(''); setBankName(''); qc.invalidateQueries({ queryKey: ['secretary-me'] }); }, onError: (e: Error) => toast.error(e.message), }); const removeIbanMut = useMutation({ mutationFn: (id: string) => api.delete(`/api/v1/secretary/iban/${id}`), onSuccess: () => { toast.success('شماره شبا حذف شد'); qc.invalidateQueries({ queryKey: ['secretary-me'] }); }, onError: (e: Error) => toast.error(e.message), }); const requestMut = useMutation({ mutationFn: () => api.post('/api/v1/settlement', { amount_rials: tomanToRial(amountToman), iban_id: ibanId, }), onSuccess: () => { toast.success('درخواست تسویه ثبت شد'); setAmountToman(0); invalidateWallet(); }, onError: (e: Error) => toast.error(e.message), }); const columns: Column[] = [ { key: 'created_at', header: 'تاریخ', render: (r) => formatDate(r.created_at) }, { key: 'amount_rials', header: 'مبلغ', render: (r) => formatRial(r.amount_rials) }, { key: 'bank_account', header: 'شبا', render: (r) => {r.bank_account?.iban ?? '—'} }, { key: 'status', header: 'وضعیت', render: (r) => STATUS_LABEL[r.status] ?? r.status }, ]; return (

شماره شبا

{ibans.length === 0 ? (

هنوز شبایی ثبت نکرده‌اید.

) : (
{ibans.map((b) => (
{b.iban} {b.bank_name && {b.bank_name}} {b.verified ? 'تأییدشده' : 'در انتظار تأیید'}
))}
)} {ibans.length < 2 && (
setNewIban(e.target.value)} />
setBankName(e.target.value)} />
)}

درخواست تسویه

{verifiedIbans.length === 0 ? (

برای ثبت درخواست تسویه، باید حداقل یک شماره شبای تأییدشده داشته باشید.

) : (
({ value: b.id, label: `${b.iban}${b.bank_name ? ` — ${b.bank_name}` : ''}` }))} value={ibanId || null} onChange={(v) => setIbanId(v ? String(v) : '')} placeholder="انتخاب شبا" />
)}
columns={columns} data={settlements} loading={listQ.isLoading} emptyMessage="درخواست تسویه‌ای ثبت نشده است" />
); }