From f3cfb3cf24120e63cfb322aa55193d11200e1eed Mon Sep 17 00:00:00 2001 From: Kartik Sharma Date: Mon, 3 Nov 2025 12:50:06 +0530 Subject: [PATCH] adding api for get list for payment request. --- .../PaymentRequest/ManagePaymentRequest.jsx | 9 +- src/hooks/useExpense.js | 61 ++++++ src/hooks/usePaymentRequest.js | 25 --- .../PaymentRequest/PaymentRequestList.jsx | 181 ++++++++++++++---- .../PaymentRequest/PaymentRequestPage.jsx | 30 ++- src/repositories/ExpsenseRepository.jsx | 29 +-- src/repositories/PaymentRequestRepository.jsx | 12 -- 7 files changed, 250 insertions(+), 97 deletions(-) delete mode 100644 src/hooks/usePaymentRequest.js delete mode 100644 src/repositories/PaymentRequestRepository.jsx diff --git a/src/components/PaymentRequest/ManagePaymentRequest.jsx b/src/components/PaymentRequest/ManagePaymentRequest.jsx index c5fd2f2d..1eba646d 100644 --- a/src/components/PaymentRequest/ManagePaymentRequest.jsx +++ b/src/components/PaymentRequest/ManagePaymentRequest.jsx @@ -4,7 +4,7 @@ import Label from '../common/Label'; import { useForm } from 'react-hook-form'; import { useExpenseType } from '../../hooks/masterHook/useMaster'; import DatePicker from '../common/DatePicker'; -import { useCreatePaymentRequest } from '../../hooks/usePaymentRequest'; +import { useCreatePaymentRequest, useUpdatePaymentRequest } from '../../hooks/useExpense'; import { defaultPaymentRequest, PaymentRequestSchema } from '../../pages/PaymentRequest/PaymentRequestSchema'; import { zodResolver } from '@hookform/resolvers/zod'; import { formatFileSize, localToUtc } from '../../utils/appUtils'; @@ -103,6 +103,9 @@ function ManagePaymentRequest({ closeModal, expenseToEdit = null }) { handleClose(); } ); + const { mutate: PaymentRequestUpdate, isPending } = useUpdatePaymentRequest(() => + handleClose() + ); useEffect(() => { if (expenseToEdit && data) { @@ -140,13 +143,13 @@ function ManagePaymentRequest({ closeModal, expenseToEdit = null }) { }; if (expenseToEdit) { const editPayload = { ...payload, id: data.id }; - ExpenseUpdate({ id: data.id, payload: editPayload }); + PaymentRequestUpdate({ id: data.id, payload: editPayload }); } else { CreatePaymentRequest(payload); } }; - + return (
diff --git a/src/hooks/useExpense.js b/src/hooks/useExpense.js index 0d4b3c77..164724a4 100644 --- a/src/hooks/useExpense.js +++ b/src/hooks/useExpense.js @@ -262,3 +262,64 @@ export const useHasAnyPermission = (permissionIdsInput) => { return permissionIds.some((id) => permissions.includes(id)); }; + +// ---------------------------Payment Request--------------------------------------------- +export const usePaymentRequestList = ( + pageSize, + pageNumber, + filter, + isActive, + searchString = "", +) => { + return useQuery({ + queryKey: ["PaymentRequest",pageSize,pageNumber,filter,isActive,searchString], + queryFn: async()=>{ + const resp = await ExpenseRepository.GetPaymentRequestList(pageSize,pageNumber,filter,isActive,searchString); + return resp.data; + }, + keepPreviousData: true, + }); +}; + +// CREATE PAYMENT REQUEST +export const useCreatePaymentRequest = (onSuccessCallBack) => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async (payload) => { + await ExpenseRepository.CreatePaymentRequest(payload); + }, + + onSuccess: (_, variables) => { + queryClient.invalidateQueries({ queryKey: ["PaymentRequest"] }); + showToast("Payment Created Successfully", "success"); + if (onSuccessCallBack) onSuccessCallBack(); + }, + onError: (error) => { + showToast( + error.message || "Something went wrong please try again !", + "error" + ); + }, + }); +}; + +export const useUpdatePaymentRequest = (onSuccessCallBack) => { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: async ({ id, payload }) => { + const response = await ExpenseRepository.UpdatePaymentRequest(id, payload); + return response.data; + }, + onSuccess: (updatedExpense, variables) => { + queryClient.removeQueries({ queryKey: ["PaymentRequest", variables.id] }); + queryClient.invalidateQueries({ queryKey: ["PaymentRequest"] }); + showToast("PaymentRequest updated Successfully", "success"); + + if (onSuccessCallBack) onSuccessCallBack(); + }, + onError: (error) => { + showToast("Something went wrong.Please try again later.", "error"); + }, + }); +}; \ No newline at end of file diff --git a/src/hooks/usePaymentRequest.js b/src/hooks/usePaymentRequest.js deleted file mode 100644 index 033ebafc..00000000 --- a/src/hooks/usePaymentRequest.js +++ /dev/null @@ -1,25 +0,0 @@ -import { useMutation, useQueryClient } from "@tanstack/react-query"; -import PaymentRequestRepository from "../repositories/PaymentRequestRepository"; -import showToast from "../services/toastService"; - -export const useCreatePaymentRequest = (onSuccessCallBack) => { - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: async (payload) => { - await PaymentRequestRepository.CreatePaymentRequest(payload); - }, - - onSuccess: (_, variables) => { - queryClient.invalidateQueries({ queryKey: ["PaymentRequest"] }); - showToast("Payment Created Successfully", "success"); - if (onSuccessCallBack) onSuccessCallBack(); - }, - onError: (error) => { - showToast( - error.message || "Something went wrong please try again !", - "error" - ); - }, - }); -}; \ No newline at end of file diff --git a/src/pages/PaymentRequest/PaymentRequestList.jsx b/src/pages/PaymentRequest/PaymentRequestList.jsx index c4a03e8b..528086db 100644 --- a/src/pages/PaymentRequest/PaymentRequestList.jsx +++ b/src/pages/PaymentRequest/PaymentRequestList.jsx @@ -1,41 +1,150 @@ -import React from "react"; +import React, { useState } from "react"; +import { ITEMS_PER_PAGE } from "../../utils/constants"; +import { useDebounce } from "../../utils/appUtils"; +import { usePaymentRequestList } from "../../hooks/useExpense"; +import { formatDate } from "../../utils/dateUtils"; -const PaymentRequestList = () => { - const paymentRequestColumns = [ - { key: "requestId", label: "Request Id" }, - { key: "RequestType", label: "Request Type" }, - { key: "submittedBy", label: "Submitted By" }, - { key: "submittedOn", label: "Submitted On" }, - { key: "amount", label: "Amount" }, - { key: "status", label: "Status" }, - ]; +const PaymentRequestList = ({ setManagePaymentRequestModal, search }) => { + const paymentRequestColumns = [ + { key: "paymentRequestUID", label: "Request ID", align: "text-start mx-2" }, + { key: "title", label: "Request Title", align: "text-start" }, + { key: "payee", label: "Payee", align: "text-start" }, + { key: "createdAt", label: "Submitted On", align: "text-start" }, + { key: "amount", label: "Amount", align: "text-start" }, + { key: "expenseStatus", label: "Status", align: "text-start" }, + ]; - return ( -
-
- - - - {paymentRequestColumns.map((col) => ( - - ))} - - - - - {/* Data rows will be added here later */} - - - - -
- {col.label} - Action
- No Payment Request Found -
-
-
- ); + const [currentPage, setCurrentPage] = useState(1); + const debouncedSearch = useDebounce(search, 500); + + const { data, isLoading, isError, error, isFetching } = usePaymentRequestList( + ITEMS_PER_PAGE, + currentPage, + {}, + true, + debouncedSearch + ); + + const paymentRequestData = data?.data || []; + const totalPages = data?.data?.totalPages || 1; + + if (isError) { + return ( +
+

Failed to load payment requests.

+ {error?.message || "Something went wrong."} +
+ ); + } + + return ( +
+
+ + + + {paymentRequestColumns.map((col) => ( + + ))} + + + + + + {isLoading || isFetching ? ( + + + + ) : paymentRequestData.length > 0 ? ( + paymentRequestData.map((row) => ( + + + + + + + + + + )) + ) : ( + + + + )} + +
+ {col.label} + Action
+ Loading Payment Requests... +
{row.paymentRequestUID}{row.title}{row.payee}{formatDate(row.createdAt)} + {row.currency?.symbol} + {row.amount} + + + {row.expenseStatus?.displayName || "Unknown"} + + +
+ + console.log("View clicked for:", row.paymentRequestUID) + } + > + + + setManagePaymentRequestModal({ + IsOpen: true, + expenseId: row.id, // Pass ID for editing + }) + } + > +
+
+ No Payment Requests Found +
+
+ + {/* Pagination */} + {totalPages > 1 && ( +
+ +
+ )} +
+ ); }; export default PaymentRequestList; diff --git a/src/pages/PaymentRequest/PaymentRequestPage.jsx b/src/pages/PaymentRequest/PaymentRequestPage.jsx index 9e707326..92dc36bd 100644 --- a/src/pages/PaymentRequest/PaymentRequestPage.jsx +++ b/src/pages/PaymentRequest/PaymentRequestPage.jsx @@ -3,16 +3,25 @@ import Breadcrumb from "../../components/common/Breadcrumb"; import GlobalModel from "../../components/common/GlobalModel"; import ManagePaymentRequest from "../../components/PaymentRequest/ManagePaymentRequest"; import PaymentRequestList from "./PaymentRequestList"; + const PaymentRequestPage = () => { const [ManagePaymentRequestModal, setManagePaymentRequestModal] = useState({ IsOpen: null, expenseId: null, }); + const [search, setSearch] = useState(""); + return (
{/* Breadcrumb */} - + {/* Top Bar */}
@@ -23,6 +32,8 @@ const PaymentRequestPage = () => { type="search" className="form-control form-control-sm w-auto" placeholder="Search Payment Req.." + value={search} + onChange={(e) => setSearch(e.target.value)} />
@@ -38,13 +49,16 @@ const PaymentRequestPage = () => { } > - Add Payment Request + + Add Payment Request +
+ {/* Add/Edit Modal */} {ManagePaymentRequestModal.IsOpen && ( { )} - {/* Expense List Placeholder */} + {/* Payment Request List */}
- {/*
-

No Expense Data found

-
*/} - +
- - ); }; diff --git a/src/repositories/ExpsenseRepository.jsx b/src/repositories/ExpsenseRepository.jsx index ef15940a..91c52c13 100644 --- a/src/repositories/ExpsenseRepository.jsx +++ b/src/repositories/ExpsenseRepository.jsx @@ -2,22 +2,27 @@ import { api } from "../utils/axiosClient"; const ExpenseRepository = { - GetExpenseList: ( pageSize, pageNumber, filter,searchString ) => { + GetExpenseList: (pageSize, pageNumber, filter, searchString) => { const payloadJsonString = JSON.stringify(filter); - - - return api.get(`/api/expense/list?pageSize=${pageSize}&pageNumber=${pageNumber}&filter=${payloadJsonString}&searchString=${searchString}`); }, - - GetExpenseDetails:(id)=>api.get(`/api/Expense/details/${id}`), - CreateExpense:(data)=>api.post("/api/Expense/create",data), - UpdateExpense:(id,data)=>api.put(`/api/Expense/edit/${id}`,data), - DeleteExpense:(id)=>api.delete(`/api/Expense/delete/${id}`), - ActionOnExpense:(data)=>api.post('/api/expense/action',data), - - GetExpenseFilter:()=>api.get('/api/Expense/filter') + GetExpenseDetails: (id) => api.get(`/api/Expense/details/${id}`), + CreateExpense: (data) => api.post("/api/Expense/create", data), + UpdateExpense: (id, data) => api.put(`/api/Expense/edit/${id}`, data), + DeleteExpense: (id) => api.delete(`/api/Expense/delete/${id}`), + + ActionOnExpense: (data) => api.post('/api/expense/action', data), + + GetExpenseFilter: () => api.get('/api/Expense/filter'), + + GetPaymentRequestList: (pageSize, pageNumber, filter, isActive, searchString) => { + const payloadJsonString = JSON.stringify(filter); + return api.get(`/api/Expense/get/payment-requests/list?isActive=${isActive}&pageSize=${pageSize}&pageNumber=${pageNumber}&filter=${payloadJsonString}&searchString=${searchString}`); + }, + + CreatePaymentRequest: (data) => api.post("/api/expense/payment-request/create", data), + UpdatePaymentRequest: (id, data) => api.put(`/api/Expense/payment-request/edit/${id}`, data), } diff --git a/src/repositories/PaymentRequestRepository.jsx b/src/repositories/PaymentRequestRepository.jsx deleted file mode 100644 index a3e861ec..00000000 --- a/src/repositories/PaymentRequestRepository.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import { api } from "../utils/axiosClient"; - - -const PaymentRequestRepository = { - - - CreatePaymentRequest:(data)=>api.post("/api/expense/payment-request/create",data), - - -} - -export default PaymentRequestRepository;