'use client'; import { useEffect, useState } from 'react'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Select } from '@/components/ui/select'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { paymentApi, type TransactionListDto } from '@/lib/payment-api'; function formatVND(amount: string | number): string { const num = typeof amount === 'string' ? Number(amount) : amount; if (num >= 1_000_000_000) return `${(num / 1_000_000_000).toFixed(1)} tỷ đ`; if (num >= 1_000_000) return `${(num / 1_000_000).toFixed(0)} triệu đ`; return num.toLocaleString('vi-VN') + ' đ'; } const STATUS_LABELS: Record = { PENDING: { label: 'Chờ xử lý', variant: 'secondary' }, PROCESSING: { label: 'Đang xử lý', variant: 'secondary' }, COMPLETED: { label: 'Thành công', variant: 'default' }, FAILED: { label: 'Thất bại', variant: 'destructive' }, REFUNDED: { label: 'Hoàn tiền', variant: 'outline' }, }; const TYPE_LABELS: Record = { SUBSCRIPTION: 'Gói dịch vụ', LISTING_FEE: 'Phí đăng tin', DEPOSIT: 'Đặt cọc', FEATURED_LISTING: 'Tin nổi bật', }; const PROVIDER_LABELS: Record = { VNPAY: 'VNPay', MOMO: 'MoMo', ZALOPAY: 'ZaloPay', BANK_TRANSFER: 'Chuyển khoản', }; export default function PaymentsPage() { const [transactions, setTransactions] = useState(null); const [loading, setLoading] = useState(true); const [statusFilter, setStatusFilter] = useState(''); const [page, setPage] = useState(0); const limit = 20; useEffect(() => { setLoading(true); paymentApi .getTransactions({ status: statusFilter || undefined, limit, offset: page * limit, }) .then((data) => setTransactions(data)) .catch(() => setTransactions(null)) .finally(() => setLoading(false)); }, [statusFilter, page]); const totalPages = transactions ? Math.ceil(transactions.total / limit) : 0; // Summary stats const completedTotal = transactions?.items .filter((t) => t.status === 'COMPLETED') .reduce((sum, t) => sum + Number(t.amountVND), 0) ?? 0; return (

Thanh toán

Lịch sử giao dịch và quản lý thanh toán

{/* Summary cards */}
Tổng giao dịch {loading ? '...' : (transactions?.total ?? 0)} Đã thanh toán {loading ? '...' : formatVND(completedTotal)} Đang chờ {loading ? '...' : (transactions?.items.filter((t) => t.status === 'PENDING' || t.status === 'PROCESSING').length ?? 0)}
{/* Transactions table */}
Lịch sử giao dịch Tất cả giao dịch thanh toán của bạn
{loading ? (
Đang tải...
) : !transactions || transactions.items.length === 0 ? (
Chưa có giao dịch nào
) : ( <> {/* Desktop table */}
Ngày Loại Nhà cung cấp Số tiền Trạng thái Mã GD {transactions.items.map((tx) => { const statusInfo = STATUS_LABELS[tx.status] ?? { label: tx.status, variant: 'secondary' as const }; return ( {new Date(tx.createdAt).toLocaleDateString('vi-VN')} {TYPE_LABELS[tx.type] ?? tx.type} {PROVIDER_LABELS[tx.provider] ?? tx.provider} {formatVND(tx.amountVND)} {statusInfo.label} {tx.providerTxId ? tx.providerTxId.slice(0, 12) + '...' : '—'} ); })}
{/* Mobile cards */}
{transactions.items.map((tx) => { const statusInfo = STATUS_LABELS[tx.status] ?? { label: tx.status, variant: 'secondary' as const }; return (
{TYPE_LABELS[tx.type] ?? tx.type} {statusInfo.label}
{new Date(tx.createdAt).toLocaleDateString('vi-VN')} —{' '} {PROVIDER_LABELS[tx.provider] ?? tx.provider} {formatVND(tx.amountVND)}
); })}
{/* Pagination */} {totalPages > 1 && (

Trang {page + 1}/{totalPages} ({transactions.total} giao dịch)

)} )}
); }