transaction and charge wallet online
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
VITE_TOKEN_NAME = 'dsc_token'
|
VITE_TOKEN_NAME = 'dsc_token'
|
||||||
VITE_REFRESH_TOKEN_NAME = 'dsc_refresh_token'
|
VITE_REFRESH_TOKEN_NAME = 'dsc_refresh_token'
|
||||||
# VITE_BASE_URL = 'https://danak-dsc-api.run.danakcorp.com'
|
VITE_BASE_URL = 'https://danak-dsc-api.run.danakcorp.com'
|
||||||
VITE_BASE_URL = 'http://192.168.0.221:4000'
|
# VITE_BASE_URL = 'http://192.168.0.221:4000'
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
interface PaginationProps {
|
||||||
|
currentPage: number;
|
||||||
|
totalPages: number;
|
||||||
|
onPageChange: (page: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Pagination: React.FC<PaginationProps> = ({
|
||||||
|
currentPage,
|
||||||
|
totalPages,
|
||||||
|
onPageChange,
|
||||||
|
}) => {
|
||||||
|
const getPageNumbers = () => {
|
||||||
|
const pageNumbers: (number | string)[] = [];
|
||||||
|
const maxVisiblePages = 5; // تعداد حداکثری صفحات قابل مشاهده
|
||||||
|
|
||||||
|
if (totalPages <= maxVisiblePages) {
|
||||||
|
for (let i = 1; i <= totalPages; i++) {
|
||||||
|
pageNumbers.push(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (currentPage > 3) {
|
||||||
|
pageNumbers.push(1);
|
||||||
|
if (currentPage > 4) {
|
||||||
|
pageNumbers.push("...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const start = Math.max(2, currentPage - 1);
|
||||||
|
const end = Math.min(totalPages - 1, currentPage + 1);
|
||||||
|
|
||||||
|
for (let i = start; i <= end; i++) {
|
||||||
|
pageNumbers.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPage < totalPages - 2) {
|
||||||
|
if (currentPage < totalPages - 3) {
|
||||||
|
pageNumbers.push("...");
|
||||||
|
}
|
||||||
|
pageNumbers.push(totalPages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pageNumbers;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pageNumbers = getPageNumbers();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex gap-2 text-xs justify-center items-center space-x-2 mt-4">
|
||||||
|
{/* دکمه قبلی */}
|
||||||
|
{/* <button
|
||||||
|
className={`px-3 py-1 rounded-md ${currentPage === 1
|
||||||
|
? "text-gray-400 cursor-not-allowed"
|
||||||
|
: "text-blue-600 hover:bg-gray-100"
|
||||||
|
}`}
|
||||||
|
onClick={() => currentPage > 1 && onPageChange(currentPage - 1)}
|
||||||
|
disabled={currentPage === 1}
|
||||||
|
>
|
||||||
|
قبلی
|
||||||
|
</button> */}
|
||||||
|
|
||||||
|
{/* شماره صفحات */}
|
||||||
|
{pageNumbers.map((page, index) =>
|
||||||
|
typeof page === "number" ? (
|
||||||
|
<button
|
||||||
|
key={index}
|
||||||
|
className={`size-8 rounded-md ${currentPage === page
|
||||||
|
? "bg-primary text-white"
|
||||||
|
: "text-primary bg-[#EAECF5] hover:bg-gray-100"
|
||||||
|
}`}
|
||||||
|
onClick={() => onPageChange(page)}
|
||||||
|
>
|
||||||
|
{page}
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<span key={index} className="px-3 py-1 text-gray-500">
|
||||||
|
{page}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* دکمه بعدی */}
|
||||||
|
{/* <button
|
||||||
|
className={`px-3 py-1 rounded-md ${currentPage === totalPages
|
||||||
|
? "text-gray-400 cursor-not-allowed"
|
||||||
|
: "text-blue-600 hover:bg-gray-100"
|
||||||
|
}`}
|
||||||
|
onClick={() => currentPage < totalPages && onPageChange(currentPage + 1)}
|
||||||
|
disabled={currentPage === totalPages}
|
||||||
|
>
|
||||||
|
بعدی
|
||||||
|
</button> */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Pagination;
|
||||||
@@ -2,3 +2,7 @@ export function isEmail(input: string): boolean {
|
|||||||
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
||||||
return emailRegex.test(input);
|
return emailRegex.test(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function NumberFormat(number: number): string {
|
||||||
|
return Intl.NumberFormat("fa-IR").format(number);
|
||||||
|
}
|
||||||
|
|||||||
+4
-1
@@ -214,8 +214,11 @@
|
|||||||
"description_transaction": "شرح تراکنش",
|
"description_transaction": "شرح تراکنش",
|
||||||
"amount": "مبلغ",
|
"amount": "مبلغ",
|
||||||
"date": "تاریخ تراکنش",
|
"date": "تاریخ تراکنش",
|
||||||
"order_number": "شماره سفارش"
|
"order_number": "شماره سفارش",
|
||||||
|
"transaction_type": "نوع تراکنش",
|
||||||
|
"description": "توضیحات"
|
||||||
},
|
},
|
||||||
|
"toman": "تومان",
|
||||||
"announcement": {
|
"announcement": {
|
||||||
"announcements": "اطلاعیه ها",
|
"announcements": "اطلاعیه ها",
|
||||||
"search": "جستجو در اطلاعیه ها",
|
"search": "جستجو در اطلاعیه ها",
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
import { ArrowRight, MoneyRecive, MoneySend } from 'iconsax-react'
|
import { ArrowRight, MoneyRecive, MoneySend } from 'iconsax-react'
|
||||||
import { FC } from 'react'
|
import { FC, Fragment, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Td from '../../components/Td'
|
import Td from '../../components/Td'
|
||||||
import Detail from './components/Detail'
|
import Detail from './components/Detail'
|
||||||
|
import { useGetTransactions } from './hooks/useTransactionData'
|
||||||
|
import PageLoading from '../../components/PageLoading'
|
||||||
|
import { TransactionItemType } from './types/TransactionTypes'
|
||||||
|
import moment from 'moment-jalaali'
|
||||||
|
import { NumberFormat } from '../../config/func'
|
||||||
|
import Pagination from '../../components/Pagination'
|
||||||
|
|
||||||
const TransactionList: FC = () => {
|
const TransactionList: FC = () => {
|
||||||
|
|
||||||
|
const [page, setPage] = useState<number>(1)
|
||||||
const { t } = useTranslation('global')
|
const { t } = useTranslation('global')
|
||||||
|
const getTransactions = useGetTransactions(page)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='mt-4'>
|
<div className='mt-4'>
|
||||||
@@ -14,6 +22,11 @@ const TransactionList: FC = () => {
|
|||||||
{t('transaction.transaction')}
|
{t('transaction.transaction')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{
|
||||||
|
getTransactions.isPending ?
|
||||||
|
<PageLoading />
|
||||||
|
:
|
||||||
|
<Fragment>
|
||||||
<div className='mt-6 flex xl:gap-6 gap-1 justify-center'>
|
<div className='mt-6 flex xl:gap-6 gap-1 justify-center'>
|
||||||
<div className='bg-white flex-1 rounded-2xl xl:p-6 py-2 px-4 xl:max-w-[253px]'>
|
<div className='bg-white flex-1 rounded-2xl xl:p-6 py-2 px-4 xl:max-w-[253px]'>
|
||||||
<div className='flex xl:flex-row flex-col gap-2 items-center'>
|
<div className='flex xl:flex-row flex-col gap-2 items-center'>
|
||||||
@@ -26,7 +39,7 @@ const TransactionList: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className='mt-2 flex xl:flex-row flex-col gap-2 items-center'>
|
<div className='mt-2 flex xl:flex-row flex-col gap-2 items-center'>
|
||||||
<div className='text-[#101828] xl:text-xs text-[10px]'>
|
<div className='text-[#101828] xl:text-xs text-[10px]'>
|
||||||
۱۴۰,۰۰۰,۰۰۰ ریال
|
{NumberFormat(getTransactions.data?.data?.totalDeposits)} {t('toman')}
|
||||||
</div>
|
</div>
|
||||||
<div className='flex gap gap-0.5 px-2 py-1 bg-green-100 rounded-lg text-[10px] text-success'>
|
<div className='flex gap gap-0.5 px-2 py-1 bg-green-100 rounded-lg text-[10px] text-success'>
|
||||||
<ArrowRight size={12} color='#00BA4B' className='-rotate-45' />
|
<ArrowRight size={12} color='#00BA4B' className='-rotate-45' />
|
||||||
@@ -45,7 +58,7 @@ const TransactionList: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className='mt-2 flex xl:flex-row flex-col gap-2 items-center'>
|
<div className='mt-2 flex xl:flex-row flex-col gap-2 items-center'>
|
||||||
<div className='text-[#101828] xl:text-xs text-[10px]'>
|
<div className='text-[#101828] xl:text-xs text-[10px]'>
|
||||||
۱۴۰,۰۰۰,۰۰۰ ریال
|
{NumberFormat(getTransactions.data?.data?.totalWithdrawals)} {t('toman')}
|
||||||
</div>
|
</div>
|
||||||
<div className='flex gap gap-0.5 px-2 py-1 bg-green-100 rounded-lg text-[10px] text-success'>
|
<div className='flex gap gap-0.5 px-2 py-1 bg-green-100 rounded-lg text-[10px] text-success'>
|
||||||
<ArrowRight size={12} color='#00BA4B' className='-rotate-45' />
|
<ArrowRight size={12} color='#00BA4B' className='-rotate-45' />
|
||||||
@@ -64,7 +77,7 @@ const TransactionList: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className='mt-2 flex xl:flex-row flex-col gap-2 items-center'>
|
<div className='mt-2 flex xl:flex-row flex-col gap-2 items-center'>
|
||||||
<div className='text-[#101828] xl:text-xs text-[10px]'>
|
<div className='text-[#101828] xl:text-xs text-[10px]'>
|
||||||
۱۴۰,۰۰۰,۰۰۰ ریال
|
{NumberFormat(getTransactions.data?.data?.balance)} {t('toman')}
|
||||||
</div>
|
</div>
|
||||||
<div className='flex gap gap-0.5 px-2 py-1 text-red-400 rounded-lg text-[10px] bg-red-100'>
|
<div className='flex gap gap-0.5 px-2 py-1 text-red-400 rounded-lg text-[10px] bg-red-100'>
|
||||||
<ArrowRight size={12} color='red' className='rotate-45' />
|
<ArrowRight size={12} color='red' className='rotate-45' />
|
||||||
@@ -79,43 +92,42 @@ const TransactionList: FC = () => {
|
|||||||
<thead className='thead'>
|
<thead className='thead'>
|
||||||
<tr>
|
<tr>
|
||||||
<Td text={t('ticket.number')} />
|
<Td text={t('ticket.number')} />
|
||||||
<Td text={t('ticket.title')} />
|
<Td text={t('transaction.description')} />
|
||||||
<Td text={t('ticket.team')} />
|
<Td text={t('transaction.amount')} />
|
||||||
<Td text={t('ticket.date')} />
|
<Td text={t('ticket.date')} />
|
||||||
<Td text={t('ticket.status')} />
|
|
||||||
<Td text={t('ticket.priority')} />
|
|
||||||
<Td text={t('ticket.detail')} />
|
<Td text={t('ticket.detail')} />
|
||||||
<Td text={''} />
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr className='tr'>
|
{
|
||||||
<Td text={t('ticket.number')} />
|
getTransactions.data?.data?.transactions?.map((item: TransactionItemType) => {
|
||||||
<Td text={t('ticket.title')} />
|
return (
|
||||||
<Td text={t('ticket.team')} />
|
<tr key={item.id}>
|
||||||
<Td text={t('ticket.date')} />
|
<Td text={item.numericId + ''} />
|
||||||
<Td text={t('ticket.status')} />
|
<Td text={item.description} />
|
||||||
<Td text={t('ticket.priority')} />
|
<Td text={item.amount} />
|
||||||
<Td text={t('ticket.detail')} />
|
<Td text={moment(item.createdAt).format('jYYYY-jMM-jDD')} />
|
||||||
<Td text={''}>
|
<Td text={''}>
|
||||||
<Detail
|
<Detail />
|
||||||
/>
|
|
||||||
</Td>
|
</Td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr className='tr'>
|
)
|
||||||
<Td text={t('ticket.number')} />
|
})
|
||||||
<Td text={t('ticket.title')} />
|
}
|
||||||
<Td text={t('ticket.team')} />
|
|
||||||
<Td text={t('ticket.date')} />
|
|
||||||
<Td text={t('ticket.status')} />
|
|
||||||
<Td text={t('ticket.priority')} />
|
|
||||||
<Td text={t('ticket.detail')} />
|
|
||||||
<Td text={''} />
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className='flex justify-end'>
|
||||||
|
<Pagination
|
||||||
|
currentPage={page}
|
||||||
|
totalPages={getTransactions.data?.data?.pager?.totalPages}
|
||||||
|
onPageChange={setPage}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
</div >
|
</div >
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import * as api from "../service/TransactionService";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
export const useGetTransactions = (page: number) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["transactions", page],
|
||||||
|
queryFn: () => api.getTransactions(page),
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import axios from "../../../config/axios";
|
||||||
|
|
||||||
|
export const getTransactions = async (page: number) => {
|
||||||
|
const { data } = await axios.get(`/wallets/transactions?page=${page}`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export type TransactionItemType = {
|
||||||
|
amount: string;
|
||||||
|
description: string;
|
||||||
|
numericId: number;
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user