Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
180 lines
4.8 KiB
TypeScript
180 lines
4.8 KiB
TypeScript
'use client'
|
|
|
|
import type { PaginationListColumnType } from '@/types'
|
|
import PaginatedList from '@/components/PaginatedList'
|
|
import StatusChip from '@/components/ui/StatusChip'
|
|
import PageNavbar from '@/components/layouts/PageNavbar'
|
|
import AdminTableViewButton from '@/components/ui/AdminTableViewButton'
|
|
import { APP_ROUTES } from '@/constants/routes'
|
|
import { formatCurrency, formatPersonName, coerceToString } from '@/helpers'
|
|
import { formatIranianMobile, formatPersianDate } from '@/lib/formatters'
|
|
import { getPaymentStatus, PAYMENT_STATUS_FILTER_ITEMS } from '@/constants/status'
|
|
import { API_ROUTES } from '@/services/config'
|
|
|
|
interface DepositUser {
|
|
id: string
|
|
mobile: string
|
|
firstName: string | null
|
|
lastName: string | null
|
|
}
|
|
|
|
const PURPOSE_LABELS: Record<string, string> = {
|
|
top_up: 'شارژ کیف پول',
|
|
booking_checkout: 'پرداخت رزرو',
|
|
}
|
|
|
|
const PURPOSE_FILTER_ITEMS = [
|
|
{ code: 'top_up', name: PURPOSE_LABELS.top_up },
|
|
{ code: 'booking_checkout', name: PURPOSE_LABELS.booking_checkout },
|
|
]
|
|
|
|
const columns: PaginationListColumnType[] = [
|
|
{
|
|
field: 'depositCode',
|
|
label: 'کد واریز',
|
|
filterable: false,
|
|
sortable: false,
|
|
type: 'text',
|
|
},
|
|
{
|
|
field: 'user',
|
|
label: 'کاربر',
|
|
filterable: false,
|
|
sortable: false,
|
|
},
|
|
{
|
|
field: 'purpose',
|
|
label: 'هدف',
|
|
filterable: true,
|
|
sortable: false,
|
|
type: 'select',
|
|
filterItems: PURPOSE_FILTER_ITEMS,
|
|
},
|
|
{
|
|
field: 'amount',
|
|
label: 'مبلغ',
|
|
filterable: false,
|
|
sortable: true,
|
|
},
|
|
{
|
|
field: 'status',
|
|
label: 'وضعیت',
|
|
filterable: true,
|
|
sortable: true,
|
|
type: 'select',
|
|
filterItems: PAYMENT_STATUS_FILTER_ITEMS,
|
|
},
|
|
{
|
|
field: 'gatewayProvider',
|
|
label: 'درگاه',
|
|
filterable: true,
|
|
sortable: false,
|
|
type: 'text',
|
|
},
|
|
{
|
|
field: 'gatewayTrackingId',
|
|
label: 'شناسه درگاه',
|
|
filterable: false,
|
|
sortable: false,
|
|
type: 'text',
|
|
},
|
|
{
|
|
field: 'gatewayRefId',
|
|
label: 'RRN درگاه',
|
|
filterable: false,
|
|
sortable: false,
|
|
type: 'text',
|
|
},
|
|
{
|
|
field: 'completedAt',
|
|
label: 'تاریخ تکمیل',
|
|
filterable: false,
|
|
sortable: true,
|
|
type: 'date',
|
|
},
|
|
{
|
|
field: 'createdAt',
|
|
label: 'تاریخ ثبت',
|
|
filterable: true,
|
|
sortable: true,
|
|
type: 'dateFromTo',
|
|
},
|
|
{
|
|
field: 'actions',
|
|
label: 'عملیات',
|
|
},
|
|
]
|
|
|
|
const WalletDepositsPage = () => {
|
|
return (
|
|
<section className="h-full w-full text-right">
|
|
<PageNavbar pageTitle="واریزهای کیف پول" />
|
|
<div className="admin-page-container">
|
|
<PaginatedList
|
|
columns={columns}
|
|
url={API_ROUTES.WALLET_DEPOSITS.ADMIN_LIST}
|
|
>
|
|
{{
|
|
user: (row) => {
|
|
const user = row.user as DepositUser | undefined
|
|
|
|
if (!user) return '—'
|
|
|
|
const name = formatPersonName(user.firstName ?? undefined, user.lastName ?? undefined)
|
|
|
|
return (
|
|
<div className="flex flex-col">
|
|
<span>{name}</span>
|
|
<span
|
|
className="text-xs text-tertiary-300"
|
|
dir="ltr"
|
|
>
|
|
{formatIranianMobile(user.mobile)}
|
|
</span>
|
|
</div>
|
|
)
|
|
},
|
|
purpose: (_row, cellValue) => PURPOSE_LABELS[coerceToString(cellValue)] ?? coerceToString(cellValue) ?? '—',
|
|
amount: (_row, cellValue) => formatCurrency(Number(cellValue ?? 0)),
|
|
status: (_row, cellValue) => <StatusChip {...getPaymentStatus(coerceToString(cellValue))} />,
|
|
gatewayProvider: (_row, cellValue) => coerceToString(cellValue) || '—',
|
|
gatewayTrackingId: (_row, cellValue) => (
|
|
<span
|
|
className="font-mono text-xs"
|
|
dir="ltr"
|
|
>
|
|
{coerceToString(cellValue) || '—'}
|
|
</span>
|
|
),
|
|
gatewayRefId: (_row, cellValue) => (
|
|
<span
|
|
className="font-mono text-xs"
|
|
dir="ltr"
|
|
>
|
|
{coerceToString(cellValue) || '—'}
|
|
</span>
|
|
),
|
|
completedAt: (_row, cellValue) => formatPersianDate(cellValue),
|
|
createdAt: (_row, cellValue) => formatPersianDate(cellValue),
|
|
actions: (row) => {
|
|
const user = row.user as DepositUser | undefined
|
|
|
|
if (!user) return '—'
|
|
|
|
return (
|
|
<AdminTableViewButton
|
|
label="مشاهده کاربر"
|
|
mode="navigate"
|
|
to={APP_ROUTES.USER_DETAIL(user.id)}
|
|
/>
|
|
)
|
|
},
|
|
}}
|
|
</PaginatedList>
|
|
</div>
|
|
</section>
|
|
)
|
|
}
|
|
|
|
export default WalletDepositsPage
|