From c11c331fb9373e029dd8dc058df1e623fb901f68 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sat, 11 Oct 2025 15:13:39 +0330 Subject: [PATCH] withdraw request --- src/config/Pages.ts | 1 + src/pages/seller/WithdrawalRequest.tsx | 104 ++++++++++ .../components/WithdrawalRequestModal.tsx | 183 ++++++++++++++++++ .../components/WithdrawalRequestTableRow.tsx | 79 ++++++++ src/pages/seller/hooks/useSellerData.ts | 7 + src/pages/seller/service/SellerService.ts | 10 + src/pages/seller/types/Types.ts | 37 ++++ src/router/Main.tsx | 2 + src/shared/SideBar.tsx | 6 +- 9 files changed, 426 insertions(+), 3 deletions(-) create mode 100644 src/pages/seller/WithdrawalRequest.tsx create mode 100644 src/pages/seller/components/WithdrawalRequestModal.tsx create mode 100644 src/pages/seller/components/WithdrawalRequestTableRow.tsx diff --git a/src/config/Pages.ts b/src/config/Pages.ts index 4140c82..5c34bc4 100644 --- a/src/config/Pages.ts +++ b/src/config/Pages.ts @@ -197,5 +197,6 @@ export const Pages = { sellers: { list: "/sellers/list", wholesaleRequests: "/sellers/wholesale-requests", + withdrawalRequests: "/sellers/withdrawal-requests", }, }; diff --git a/src/pages/seller/WithdrawalRequest.tsx b/src/pages/seller/WithdrawalRequest.tsx new file mode 100644 index 0000000..69760ed --- /dev/null +++ b/src/pages/seller/WithdrawalRequest.tsx @@ -0,0 +1,104 @@ +import { type FC, useState } from 'react' +import { useGetWithdrawalRequests } from './hooks/useSellerData' +import PageLoading from '../../components/PageLoading' +import Error from '../../components/Error' +import PaginationUi from '../../components/PaginationUi' +import Td from '../../components/Td' +import WithdrawalRequestTableRow from './components/WithdrawalRequestTableRow' +import WithdrawalRequestModal from './components/WithdrawalRequestModal' + +interface WithdrawalRequestData { + wallet: { + _id: string; + seller: { + fullName: string; + email?: string; + phoneNumber: string; + }; + balance: number; + }; + withdrawals: unknown[]; + lastPaidAmount: number | null; + lastPaidDate: string | null; +} + +const WithdrawalRequest: FC = () => { + + const [currentPage, setCurrentPage] = useState(1); + const [selectedRequest, setSelectedRequest] = useState(null); + const [isModalOpen, setIsModalOpen] = useState(false); + const { data: withdrawalData, isLoading, error } = useGetWithdrawalRequests(currentPage); + + if (isLoading) { + return ( +
+ +
+ ); + } + + if (error) { + return ( +
+ +
+ ); + } + + const withdrawalRequests = withdrawalData?.results?.walletData || []; + + const handleViewDetails = (request: WithdrawalRequestData) => { + setSelectedRequest(request); + setIsModalOpen(true); + }; + + return ( +
+
+ + + + + + + {withdrawalRequests.length === 0 ? ( + + + + ) : ( + withdrawalRequests.map((request: WithdrawalRequestData) => ( + + )) + )} + +
+ + + + +
+ هیچ درخواست برداشتی یافت نشد +
+
+ + { + setCurrentPage(page); + }} + /> + + setIsModalOpen(false)} + request={selectedRequest} + /> +
+ ) +} + +export default WithdrawalRequest \ No newline at end of file diff --git a/src/pages/seller/components/WithdrawalRequestModal.tsx b/src/pages/seller/components/WithdrawalRequestModal.tsx new file mode 100644 index 0000000..977a0fb --- /dev/null +++ b/src/pages/seller/components/WithdrawalRequestModal.tsx @@ -0,0 +1,183 @@ +import { type FC } from 'react' +import DefaulModal from '../../../components/DefaulModal' +import { Calendar, Call, Card, User as UserIcon, Shop, Money } from 'iconsax-react' +import type { WithdrawalRequestData } from '../WithdrawalRequest' + +interface Props { + open: boolean + close: () => void + request: WithdrawalRequestData | null +} + +const WithdrawalRequestModal: FC = ({ open, close, request }) => { + + const formatCurrency = (amount: number) => { + return new Intl.NumberFormat('fa-IR', { + style: 'currency', + currency: 'IRR', + minimumFractionDigits: 0, + }).format(amount); + }; + + const formatDate = (dateString: string) => { + return new Date(dateString).toLocaleDateString('fa-IR'); + }; + + const getStatusText = (status: string) => { + switch (status) { + case 'Approved': return 'تایید شده'; + case 'Pending': return 'در انتظار'; + default: return status; + } + }; + + const getStatusColor = (status: string) => { + switch (status) { + case 'Approved': return 'text-green-600'; + case 'Pending': return 'text-yellow-600'; + default: return 'text-gray-600'; + } + }; + + if (!request) return null; + + return ( + +
+ {/* Seller Information */} +
+

+ + اطلاعات فروشنده +

+
+
+ +
+ نام و نام خانوادگی: +

{request.wallet?.seller?.fullName || '-'}

+
+
+ +
+ +
+ ایمیل: +

{request.wallet?.seller?.email || '-'}

+
+
+ +
+ +
+ شماره تلفن: +

{request.wallet?.seller?.phoneNumber}

+
+
+ +
+ +
+ تاریخ تولد: +

+ {request.wallet?.seller?.dateOfBirth ? formatDate(request.wallet.seller.dateOfBirth) : '-'} +

+
+
+ +
+ +
+ نوع کسب‌وکار: +

{request.wallet?.seller?.businessType || '-'}

+
+
+ +
+
+
+ وضعیت حساب: +

+ {getStatusText(request.wallet?.seller?.accountStatus || '')} +

+
+
+
+
+ + {/* Wallet Information */} +
+

+ + اطلاعات کیف پول +

+
+
+ +
+ موجودی: +

{formatCurrency(request.wallet?.balance || 0)}

+
+
+ +
+ +
+ تاریخ ایجاد کیف پول: +

{formatDate(request.wallet?.createdAt || '')}

+
+
+ +
+ +
+ آخرین بروزرسانی: +

{formatDate(request.wallet?.updatedAt || '')}

+
+
+
+
+ + {/* Additional Information */} +
+

اطلاعات تکمیلی

+
+
+ تاریخ عضویت: +

+ {request.wallet?.seller?.createdAt ? formatDate(request.wallet.seller.createdAt) : '-'} +

+
+ +
+ وضعیت تکمیل ثبت‌نام: +

+ {request.wallet?.seller?.isRegisterCompleted ? 'تکمیل شده' : 'ناتمام'} +

+
+ +
+ فروشنده عمده: +

+ {request.wallet?.seller?.isWholesaler ? 'بله' : 'خیر'} +

+
+ +
+ تعداد درخواست‌های برداشت: +

{request.withdrawals?.length || 0}

+
+
+
+
+
+ ) +} + +export default WithdrawalRequestModal diff --git a/src/pages/seller/components/WithdrawalRequestTableRow.tsx b/src/pages/seller/components/WithdrawalRequestTableRow.tsx new file mode 100644 index 0000000..742e818 --- /dev/null +++ b/src/pages/seller/components/WithdrawalRequestTableRow.tsx @@ -0,0 +1,79 @@ +import { type FC } from 'react' +import Td from '../../../components/Td' +import { Call, Card, User as UserIcon, Money, Eye } from 'iconsax-react' + +interface WithdrawalRequestData { + wallet: { + _id: string; + seller: { + fullName: string; + email?: string; + phoneNumber: string; + }; + balance: number; + }; + withdrawals: unknown[]; + lastPaidAmount: number | null; + lastPaidDate: string | null; +} + +interface Props { + request: WithdrawalRequestData + onViewDetails: (request: WithdrawalRequestData) => void +} + +const WithdrawalRequestTableRow: FC = ({ request, onViewDetails }) => { + + const handleViewDetails = () => { + onViewDetails(request); + }; + + const formatCurrency = (amount: number | null) => { + if (amount === null) return '-'; + return new Intl.NumberFormat('fa-IR', { + style: 'currency', + currency: 'IRR', + minimumFractionDigits: 0, + }).format(amount); + }; + + return ( + + +
+ + {request.wallet?.seller?.fullName || '-'} +
+ + +
+ + {request.wallet?.seller?.email || '-'} +
+ + +
+ + {request.wallet?.seller?.phoneNumber} +
+ + +
+ + {formatCurrency(request.wallet?.balance || 0)} +
+ + + + + + ) +} + +export default WithdrawalRequestTableRow diff --git a/src/pages/seller/hooks/useSellerData.ts b/src/pages/seller/hooks/useSellerData.ts index 7592103..92d95be 100644 --- a/src/pages/seller/hooks/useSellerData.ts +++ b/src/pages/seller/hooks/useSellerData.ts @@ -32,3 +32,10 @@ export const useApproveWholesaleRequest = () => { mutationFn: api.approveWholesaleRequest, }); }; + +export const useGetWithdrawalRequests = (page: number = 1) => { + return useQuery({ + queryKey: ["withdrawal-requests", page], + queryFn: () => api.getWithdrawalRequests(page), + }); +}; diff --git a/src/pages/seller/service/SellerService.ts b/src/pages/seller/service/SellerService.ts index f432f4e..3547485 100644 --- a/src/pages/seller/service/SellerService.ts +++ b/src/pages/seller/service/SellerService.ts @@ -2,6 +2,7 @@ import axios from "@/config/axios"; import type { SellersResponse, WholesaleRequestsResponse, + WithdrawalRequestsResponse, } from "../types/Types"; export const getSellers = async ( @@ -38,3 +39,12 @@ export const approveWholesaleRequest = async (id: string) => { const { data } = await axios.patch(`/admin/sellers/wholesale-requests/${id}`); return data; }; + +export const getWithdrawalRequests = async ( + page: number = 1 +): Promise => { + const { data } = await axios.get( + `/admin/financial/withdrawal/requests?page=${page}` + ); + return data; +}; diff --git a/src/pages/seller/types/Types.ts b/src/pages/seller/types/Types.ts index 67cc299..347f2b8 100644 --- a/src/pages/seller/types/Types.ts +++ b/src/pages/seller/types/Types.ts @@ -122,3 +122,40 @@ export interface WholesaleRequestsResponse { }; }; } + +export interface WalletSeller { + _id: string; + fullName: string; + dateOfBirth: string | null; + phoneNumber: string; + accountStatus: "Pending" | "Approved"; + isRegisterCompleted: boolean; + businessType: string | null; + isWholesaler: boolean; + createdAt: string; + updatedAt: string; + email?: string; +} + +export interface Wallet { + _id: string; + seller: WalletSeller; + balance: number; + createdAt: string; + updatedAt: string; +} + +export interface WithdrawalRequest { + wallet: Wallet; + withdrawals: unknown[]; // Empty array in example, can be expanded later + lastPaidAmount: number | null; + lastPaidDate: string | null; +} + +export interface WithdrawalRequestsResponse { + status: number; + success: boolean; + results: { + walletData: WithdrawalRequest[]; + }; +} diff --git a/src/router/Main.tsx b/src/router/Main.tsx index b2eea0d..9464f04 100644 --- a/src/router/Main.tsx +++ b/src/router/Main.tsx @@ -64,6 +64,7 @@ import ContactUsList from '@/pages/contactUs/List' import Dashboard from '@/pages/dashboard/Dashboard' import SellerList from '@/pages/seller/List' import WholeSaleRequest from '@/pages/seller/WholeSaleRequest' +import WithdrawalRequestPage from '@/pages/seller/WithdrawalRequest' const MainRouter: FC = () => { const { hasSubMenu } = useSharedStore() @@ -161,6 +162,7 @@ const MainRouter: FC = () => { } /> } /> + } /> diff --git a/src/shared/SideBar.tsx b/src/shared/SideBar.tsx index a0cfc9e..2c4a4ed 100644 --- a/src/shared/SideBar.tsx +++ b/src/shared/SideBar.tsx @@ -499,17 +499,17 @@ const SellersSubMenu: FC = () => {