transactions
This commit is contained in:
@@ -0,0 +1,272 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import * as React from 'react'
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable
|
||||||
|
} from '@tanstack/react-table'
|
||||||
|
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow
|
||||||
|
} from '@/components/ui/table'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
import { ArrowLeft2, ArrowRight2 } from 'iconsax-react'
|
||||||
|
import { ef } from '@/lib/helpers/utfNumbers'
|
||||||
|
import { Transaction } from '../types/Types'
|
||||||
|
|
||||||
|
interface TransactionsTableProps {
|
||||||
|
transactions: Transaction[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatDate = (dateString: string): string => {
|
||||||
|
const date = new Date(dateString);
|
||||||
|
return date.toLocaleDateString('fa-IR', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusText = (status: string): string => {
|
||||||
|
const statusMap: Record<string, string> = {
|
||||||
|
'SUCCESS': 'موفق',
|
||||||
|
'FAILED': 'ناموفق',
|
||||||
|
'PENDING': 'در انتظار',
|
||||||
|
'CANCELLED': 'لغو شده',
|
||||||
|
};
|
||||||
|
return statusMap[status] || status;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusColor = (status: string): string => {
|
||||||
|
const colorMap: Record<string, string> = {
|
||||||
|
'SUCCESS': 'bg-[#00BA4B]',
|
||||||
|
'FAILED': 'bg-red-500',
|
||||||
|
'PENDING': 'bg-yellow-500',
|
||||||
|
'CANCELLED': 'bg-gray-500',
|
||||||
|
};
|
||||||
|
return colorMap[status] || 'bg-transparent border border-primary';
|
||||||
|
};
|
||||||
|
|
||||||
|
export const columns: ColumnDef<Transaction>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: 'order.orderNumber',
|
||||||
|
header: () => <div className='text-right pr-6'>شماره سفارش</div>,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const orderNumber = row.original.order?.orderNumber;
|
||||||
|
return (
|
||||||
|
<div className='text-right pr-6'>{ef(orderNumber?.toString() || '-')}</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'type',
|
||||||
|
header: () => <div className='text-center'>نوع تراکنش</div>,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const type = row.original.order?.paymentMethod?.description || '-';
|
||||||
|
return <div className='text-center'>{type}</div>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'amount',
|
||||||
|
header: () => <div className='text-center'>مبلغ</div>,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const amount = row.original.amount;
|
||||||
|
const formatted = Math.abs(amount).toLocaleString('fa-IR');
|
||||||
|
return <div className='text-center'>{ef(formatted)} ریال</div>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'createdAt',
|
||||||
|
header: () => <div className='text-center'>تاریخ</div>,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const date = formatDate(row.original.createdAt);
|
||||||
|
return <div className='text-center'>{ef(date)}</div>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'status',
|
||||||
|
header: () => <div className='text-center'>وضعیت</div>,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const status = row.original.status;
|
||||||
|
const statusText = getStatusText(status);
|
||||||
|
const statusColor = getStatusColor(status);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='text-right flex items-center justify-center gap-x-2'>
|
||||||
|
<span
|
||||||
|
className={clsx(
|
||||||
|
'size-2 rounded-full',
|
||||||
|
statusColor
|
||||||
|
)}
|
||||||
|
></span>
|
||||||
|
{statusText}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
export function TransactionsTable({ transactions }: TransactionsTableProps) {
|
||||||
|
const [sorting, setSorting] = React.useState<SortingState>([])
|
||||||
|
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
const [columnVisibility, setColumnVisibility] =
|
||||||
|
React.useState<VisibilityState>({})
|
||||||
|
const [rowSelection, setRowSelection] = React.useState({})
|
||||||
|
|
||||||
|
const table = useReactTable({
|
||||||
|
data: transactions,
|
||||||
|
columns,
|
||||||
|
onSortingChange: setSorting,
|
||||||
|
onColumnFiltersChange: setColumnFilters,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
|
onRowSelectionChange: setRowSelection,
|
||||||
|
state: {
|
||||||
|
sorting,
|
||||||
|
columnFilters,
|
||||||
|
columnVisibility,
|
||||||
|
rowSelection
|
||||||
|
},
|
||||||
|
initialState: {
|
||||||
|
pagination: {
|
||||||
|
pageSize: 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='w-full'>
|
||||||
|
<div className='rounded-3xl min-h-[507px] w-full'>
|
||||||
|
<Table className='w-[727px] md:w-full'>
|
||||||
|
<TableHeader>
|
||||||
|
{table.getHeaderGroups().map(headerGroup => (
|
||||||
|
<TableRow
|
||||||
|
className='dark:border-neutral-400 border-[#EAEDF5] h-14'
|
||||||
|
key={headerGroup.id}
|
||||||
|
>
|
||||||
|
{headerGroup.headers.map(header => {
|
||||||
|
return (
|
||||||
|
<TableHead
|
||||||
|
key={header.id}
|
||||||
|
className='font-light text-xs text-disabled-text text-center'
|
||||||
|
>
|
||||||
|
{header.isPlaceholder
|
||||||
|
? null
|
||||||
|
: flexRender(
|
||||||
|
header.column.columnDef.header,
|
||||||
|
header.getContext()
|
||||||
|
)}
|
||||||
|
</TableHead>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{table.getRowModel().rows?.length ? (
|
||||||
|
table.getRowModel().rows.map(row => (
|
||||||
|
<TableRow
|
||||||
|
key={row.id}
|
||||||
|
className='text-center w-full border-b-[#EAEDF5] dark:border-b-background text-xs odd:bg-[#E9EBF433] bg-border dark:odd:bg-background/80 even:bg-container border-0 border-b! h-14 border-r-4! border-r-transparent active:border-r-primary dark:active:border-r-foreground'
|
||||||
|
>
|
||||||
|
{row.getVisibleCells().map(cell => (
|
||||||
|
<TableCell key={cell.id}>
|
||||||
|
{flexRender(
|
||||||
|
cell.column.columnDef.cell,
|
||||||
|
cell.getContext()
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell
|
||||||
|
colSpan={columns.length}
|
||||||
|
className='h-24 text-center'
|
||||||
|
>
|
||||||
|
تراکنشی یافت نشد.
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
<div className='flex items-center justify-end space-x-2 pt-4 px-7 pb-11 select-none'>
|
||||||
|
<div className='flex-1 text-sm text-disabled-text'>
|
||||||
|
نمایش:{' '}
|
||||||
|
<span className='text-primary dark:text-foreground'>
|
||||||
|
{ef(table.getRowModel().rows.length)}
|
||||||
|
</span>{' '}
|
||||||
|
از {ef(table.getFilteredRowModel().rows.length)}
|
||||||
|
</div>
|
||||||
|
<div className='space-x-2 justify-center flex'>
|
||||||
|
<Button
|
||||||
|
variant='ghost'
|
||||||
|
size='sm'
|
||||||
|
className='size-6'
|
||||||
|
onClick={() => table.previousPage()}
|
||||||
|
hidden={!table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
<ArrowRight2 size={12} className='stroke-[#A8ABBF]' />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant='secondary'
|
||||||
|
size='sm'
|
||||||
|
className='dark:bg-disabled bg-[#EAECF5] text-xs size-6'
|
||||||
|
onClick={() => table.previousPage()}
|
||||||
|
hidden={!table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
{ef(table.getState().pagination.pageIndex)}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant='default'
|
||||||
|
className='text-white dark:text-foreground text-xs size-6'
|
||||||
|
size='sm'
|
||||||
|
hidden={!table.getCanPreviousPage() && !table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
{ef(table.getState().pagination.pageIndex + 1)}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant='secondary'
|
||||||
|
size='sm'
|
||||||
|
className='dark:bg-disabled bg-[#EAECF5] text-xs size-6'
|
||||||
|
onClick={() => table.nextPage()}
|
||||||
|
hidden={!table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
{ef(table.getState().pagination.pageIndex + 2)}
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant='ghost'
|
||||||
|
size='sm'
|
||||||
|
className='size-6'
|
||||||
|
onClick={() => table.nextPage()}
|
||||||
|
hidden={!table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
<ArrowLeft2 size={12} className='stroke-[#A8ABBF]' />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -20,3 +20,10 @@ export const useConvertScoreToWallet = () => {
|
|||||||
mutationFn: api.convertScoreToWallet,
|
mutationFn: api.convertScoreToWallet,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useGetTransactions = () => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["transactions"],
|
||||||
|
queryFn: api.getTransactions,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,17 +1,55 @@
|
|||||||
import { DataTableDemo } from '@/components/ui/datatable'
|
'use client';
|
||||||
import { ef } from '@/lib/helpers/utfNumbers'
|
import { ef } from '@/lib/helpers/utfNumbers'
|
||||||
import {
|
import {
|
||||||
ArrowLeft,
|
|
||||||
ArrowRight,
|
|
||||||
MoneyRecive,
|
MoneyRecive,
|
||||||
MoneySend,
|
MoneySend,
|
||||||
Wallet
|
Wallet
|
||||||
} from 'iconsax-react'
|
} from 'iconsax-react'
|
||||||
import React from 'react'
|
import React, { useMemo } from 'react'
|
||||||
|
import { useGetTransactions, useGetUserWallet } from './hooks/useTransactionData';
|
||||||
|
import { Transaction } from './types/Types';
|
||||||
|
import { TransactionsTable } from './components/TransactionsTable';
|
||||||
|
import LoadingOverlay from '@/components/overlays/LoadingOverlay';
|
||||||
|
|
||||||
function TransactionsReviewIndex() {
|
function TransactionsReviewIndex() {
|
||||||
|
const { data: transactionsResponse, isLoading: isLoadingTransactions } = useGetTransactions();
|
||||||
|
const { data: walletResponse, isLoading: isLoadingWallet } = useGetUserWallet();
|
||||||
|
|
||||||
|
const transactions = transactionsResponse?.data || [];
|
||||||
|
const walletAmount = walletResponse?.data?.wallet || 0;
|
||||||
|
|
||||||
|
const stats = useMemo(() => {
|
||||||
|
if (!transactions.length) {
|
||||||
|
return {
|
||||||
|
totalDeposits: 0,
|
||||||
|
totalWithdrawals: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const deposits = transactions
|
||||||
|
.filter((t: Transaction) => t.status === 'SUCCESS' && t.amount > 0)
|
||||||
|
.reduce((sum: number, t: Transaction) => sum + t.amount, 0);
|
||||||
|
|
||||||
|
const withdrawals = transactions
|
||||||
|
.filter((t: Transaction) => t.status === 'SUCCESS' && t.amount < 0)
|
||||||
|
.reduce((sum: number, t: Transaction) => sum + Math.abs(t.amount), 0);
|
||||||
|
|
||||||
|
return {
|
||||||
|
totalDeposits: deposits,
|
||||||
|
totalWithdrawals: withdrawals,
|
||||||
|
};
|
||||||
|
}, [transactions]);
|
||||||
|
|
||||||
|
const formatPrice = (amount: number) => {
|
||||||
|
return ef(amount.toLocaleString('fa-IR'));
|
||||||
|
};
|
||||||
|
|
||||||
|
const isLoading = isLoadingTransactions || isLoadingWallet;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className='flex flex-col h-full pb-10 pt-6 gap-4'>
|
<section className='flex flex-col h-full pb-10 pt-6 gap-4 relative'>
|
||||||
|
{isLoading && <LoadingOverlay />}
|
||||||
|
|
||||||
<h1 className='font-medium text-base'>لیست تراکنش ها</h1>
|
<h1 className='font-medium text-base'>لیست تراکنش ها</h1>
|
||||||
|
|
||||||
<div className='grid grid-cols-3 gap-2 h-28'>
|
<div className='grid grid-cols-3 gap-2 h-28'>
|
||||||
@@ -24,17 +62,10 @@ function TransactionsReviewIndex() {
|
|||||||
</div>
|
</div>
|
||||||
<span className='text-xs2 pt-1'>مجموع واریز ها</span>
|
<span className='text-xs2 pt-1'>مجموع واریز ها</span>
|
||||||
<span className='text-xs font-medium mt-1 mb-0.5'>
|
<span className='text-xs font-medium mt-1 mb-0.5'>
|
||||||
{ef('140,000,000 ریال')}
|
{formatPrice(stats.totalDeposits)} ریال
|
||||||
</span>
|
|
||||||
<span className='text-xs2 text-green-600 mt-0.5 bg-green-100 dark:bg-transparent dark:border dark:border-green-400 w-min px-1 py-px items-center justify-between rounded-md flex gap-0.5'>
|
|
||||||
<ArrowRight
|
|
||||||
size={10}
|
|
||||||
className='stroke-green-600 mb-0.5 -rotate-z-45'
|
|
||||||
/>
|
|
||||||
<span className='mt-0.5'>{ef('30%')}</span>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className='w-full h-full flex flex-col items-center justify-between p-2.5 text-center bg-container rounded-xl'>
|
<div className='w-full h-full flex flex-col items-center justify-center p-2.5 text-center bg-container rounded-xl'>
|
||||||
<div className='size-8 bg-background rounded-full grid items-center'>
|
<div className='size-8 bg-background rounded-full grid items-center'>
|
||||||
<MoneyRecive
|
<MoneyRecive
|
||||||
className='stroke-primary justify-self-center dark:stroke-neutral-200'
|
className='stroke-primary justify-self-center dark:stroke-neutral-200'
|
||||||
@@ -43,17 +74,10 @@ function TransactionsReviewIndex() {
|
|||||||
</div>
|
</div>
|
||||||
<span className='text-xs2 pt-1'>مجموع برداشت ها</span>
|
<span className='text-xs2 pt-1'>مجموع برداشت ها</span>
|
||||||
<span className='text-xs font-medium mt-1 mb-0.5'>
|
<span className='text-xs font-medium mt-1 mb-0.5'>
|
||||||
{ef('140,000,000 ریال')}
|
{formatPrice(stats.totalWithdrawals)} ریال
|
||||||
</span>
|
|
||||||
<span className='text-xs2 text-green-600 mt-0.5 bg-green-100 dark:bg-transparent dark:border dark:border-green-400 w-min px-1 py-px items-center justify-between rounded-md flex gap-0.5'>
|
|
||||||
<ArrowRight
|
|
||||||
size={10}
|
|
||||||
className='stroke-green-600 mb-0.5 -rotate-z-45'
|
|
||||||
/>
|
|
||||||
<span className='mt-0.5'>{ef('30%')}</span>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className='w-full h-full flex flex-col items-center justify-between p-2.5 text-center bg-container rounded-xl'>
|
<div className='w-full h-full flex flex-col items-center justify-center p-2.5 text-center bg-container rounded-xl'>
|
||||||
<div className='size-8 bg-background rounded-full grid items-center'>
|
<div className='size-8 bg-background rounded-full grid items-center'>
|
||||||
<Wallet
|
<Wallet
|
||||||
className='stroke-primary justify-self-center dark:stroke-neutral-200'
|
className='stroke-primary justify-self-center dark:stroke-neutral-200'
|
||||||
@@ -62,20 +86,13 @@ function TransactionsReviewIndex() {
|
|||||||
</div>
|
</div>
|
||||||
<span className='text-xs2 pt-1'>موجودی کیف پول</span>
|
<span className='text-xs2 pt-1'>موجودی کیف پول</span>
|
||||||
<span className='text-xs font-medium mt-1 mb-0.5'>
|
<span className='text-xs font-medium mt-1 mb-0.5'>
|
||||||
{ef('140,000,000 ریال')}
|
{formatPrice(walletAmount)} ریال
|
||||||
</span>
|
|
||||||
<span className='text-xs2 text-red-600 mt-0.5 bg-red-100 dark:bg-transparent dark:border dark:border-red-400 w-min px-1 py-px items-center justify-between rounded-md flex gap-1'>
|
|
||||||
<ArrowLeft
|
|
||||||
size={10}
|
|
||||||
className='stroke-red-600 mb-0.5 -rotate-z-45'
|
|
||||||
/>
|
|
||||||
<span className='mt-0.5'>{ef('30%')}</span>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='w-full h-full bg-container rounded-3xl mt-0'>
|
<div className='w-full h-full bg-container rounded-3xl mt-0'>
|
||||||
<DataTableDemo />
|
<TransactionsTable transactions={transactions} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { api } from "@/config/axios";
|
import { api } from "@/config/axios";
|
||||||
import { CouponsResponse, WalletResponse } from "../types/Types";
|
import {
|
||||||
|
CouponsResponse,
|
||||||
|
WalletResponse,
|
||||||
|
TransactionsResponse,
|
||||||
|
} from "../types/Types";
|
||||||
|
|
||||||
export const getMyCoupons = async (): Promise<CouponsResponse> => {
|
export const getMyCoupons = async (): Promise<CouponsResponse> => {
|
||||||
const { data } = await api.get<CouponsResponse>("/public/coupons/me");
|
const { data } = await api.get<CouponsResponse>("/public/coupons/me");
|
||||||
@@ -15,3 +19,8 @@ export const convertScoreToWallet = async () => {
|
|||||||
const { data } = await api.post("/public/user/convert-score-to-wallet");
|
const { data } = await api.post("/public/user/convert-score-to-wallet");
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getTransactions = async (): Promise<TransactionsResponse> => {
|
||||||
|
const { data } = await api.get<TransactionsResponse>("/public/payments");
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -38,3 +38,63 @@ export interface Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type WalletResponse = BaseResponse<Wallet>;
|
export type WalletResponse = BaseResponse<Wallet>;
|
||||||
|
|
||||||
|
export interface PaymentMethod {
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
deletedAt: string | null;
|
||||||
|
restaurant: string;
|
||||||
|
title: string;
|
||||||
|
method: string;
|
||||||
|
gateway: string | null;
|
||||||
|
description: string;
|
||||||
|
enabled: boolean;
|
||||||
|
order: number;
|
||||||
|
merchantId: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionOrder {
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
deletedAt: string | null;
|
||||||
|
user: string;
|
||||||
|
restaurant: string;
|
||||||
|
deliveryMethod: string;
|
||||||
|
address: string | null;
|
||||||
|
paymentMethod: PaymentMethod;
|
||||||
|
orderNumber: number;
|
||||||
|
couponDiscount: number;
|
||||||
|
couponDetail: unknown | null;
|
||||||
|
itemsDiscount: number;
|
||||||
|
totalDiscount: number;
|
||||||
|
subTotal: number;
|
||||||
|
tax: number;
|
||||||
|
deliveryFee: number;
|
||||||
|
total: number;
|
||||||
|
totalItems: number;
|
||||||
|
description: string | null;
|
||||||
|
tableNumber: string;
|
||||||
|
status: string;
|
||||||
|
paymentStatus: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Transaction {
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
deletedAt: string | null;
|
||||||
|
order: TransactionOrder;
|
||||||
|
amount: number;
|
||||||
|
authority: string | null;
|
||||||
|
gateway: string | null;
|
||||||
|
refId: string | null;
|
||||||
|
status: string;
|
||||||
|
cardPan: string | null;
|
||||||
|
verifyResponse: unknown | null;
|
||||||
|
paidAt: string | null;
|
||||||
|
failedAt: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TransactionsResponse = BaseResponse<Transaction[]>;
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ const StepOtp = ({ phone, slug, code }: Props) => {
|
|||||||
window.location.href = getRedirectPath()
|
window.location.href = getRedirectPath()
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
|
clear()
|
||||||
|
window.location.href = getRedirectPath()
|
||||||
toast(extractErrorMessage(error), 'error')
|
toast(extractErrorMessage(error), 'error')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user