adding api for get list for payment request.
This commit is contained in:
parent
e0c0a14777
commit
f3cfb3cf24
@ -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 (
|
||||
<div className="container p-3">
|
||||
<h5 className="m-0">
|
||||
|
||||
@ -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");
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -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"
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -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 (
|
||||
<div className="card page-min-h table-responsive px-sm-4">
|
||||
<div className="card-datatable " id="payment-request-table">
|
||||
<table className="table border-top dataTable text-nowrap">
|
||||
<thead>
|
||||
<tr>
|
||||
{paymentRequestColumns.map((col) => (
|
||||
<th key={col.key} className="sorting text-start">
|
||||
{col.label}
|
||||
</th>
|
||||
))}
|
||||
<th className="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{/* Data rows will be added here later */}
|
||||
<tr>
|
||||
<td colSpan={paymentRequestColumns.length + 1} className="text-center py-4">
|
||||
No Payment Request Found
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
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 (
|
||||
<div className="text-center text-danger py-5">
|
||||
<p>Failed to load payment requests.</p>
|
||||
<small>{error?.message || "Something went wrong."}</small>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="card page-min-h table-responsive px-sm-4">
|
||||
<div className="card-datatable" id="payment-request-table">
|
||||
<table className="table border-top dataTable text-nowrap align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
{paymentRequestColumns.map((col) => (
|
||||
<th key={col.key} className={`sorting ${col.align}`}>
|
||||
{col.label}
|
||||
</th>
|
||||
))}
|
||||
<th className="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{isLoading || isFetching ? (
|
||||
<tr>
|
||||
<td
|
||||
colSpan={paymentRequestColumns.length + 1}
|
||||
className="text-center py-4"
|
||||
>
|
||||
Loading Payment Requests...
|
||||
</td>
|
||||
</tr>
|
||||
) : paymentRequestData.length > 0 ? (
|
||||
paymentRequestData.map((row) => (
|
||||
<tr key={row.id}>
|
||||
<td>{row.paymentRequestUID}</td>
|
||||
<td>{row.title}</td>
|
||||
<td>{row.payee}</td>
|
||||
<td>{formatDate(row.createdAt)}</td>
|
||||
<td>
|
||||
{row.currency?.symbol}
|
||||
{row.amount}
|
||||
</td>
|
||||
<td>
|
||||
<span
|
||||
className="badge"
|
||||
style={{
|
||||
backgroundColor: row.expenseStatus?.color || "#6c757d",
|
||||
}}
|
||||
>
|
||||
{row.expenseStatus?.displayName || "Unknown"}
|
||||
</span>
|
||||
</td>
|
||||
<td className="text-center">
|
||||
<div className="d-flex justify-content-center gap-2">
|
||||
<i
|
||||
className="bx bx-show text-primary cursor-pointer"
|
||||
title="View"
|
||||
onClick={() =>
|
||||
console.log("View clicked for:", row.paymentRequestUID)
|
||||
}
|
||||
></i>
|
||||
|
||||
<i
|
||||
className="bx bx-edit text-secondary cursor-pointer"
|
||||
title="Edit"
|
||||
onClick={() =>
|
||||
setManagePaymentRequestModal({
|
||||
IsOpen: true,
|
||||
expenseId: row.id, // Pass ID for editing
|
||||
})
|
||||
}
|
||||
></i>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
) : (
|
||||
<tr>
|
||||
<td
|
||||
colSpan={paymentRequestColumns.length + 1}
|
||||
className="text-center py-4"
|
||||
>
|
||||
No Payment Requests Found
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{/* Pagination */}
|
||||
{totalPages > 1 && (
|
||||
<div className="d-flex justify-content-end py-3 pe-3">
|
||||
<nav>
|
||||
<ul className="pagination mb-0">
|
||||
{[...Array(totalPages)].map((_, index) => (
|
||||
<li
|
||||
key={index}
|
||||
className={`page-item ${currentPage === index + 1 ? "active" : ""}`}
|
||||
>
|
||||
<button
|
||||
className="page-link"
|
||||
onClick={() => setCurrentPage(index + 1)}
|
||||
>
|
||||
{index + 1}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PaymentRequestList;
|
||||
|
||||
@ -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 (
|
||||
<div className="container-fluid">
|
||||
{/* Breadcrumb */}
|
||||
<Breadcrumb data={[{ label: "Home", link: "/" }, { label: "Finance", link: "/Payment Request" }, { label: "Payment Request" }]} />
|
||||
<Breadcrumb
|
||||
data={[
|
||||
{ label: "Home", link: "/" },
|
||||
{ label: "Finance", link: "/Payment Request" },
|
||||
{ label: "Payment Request" },
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* Top Bar */}
|
||||
<div className="card my-3 px-sm-4 px-0">
|
||||
@ -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)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -38,13 +49,16 @@ const PaymentRequestPage = () => {
|
||||
}
|
||||
>
|
||||
<i className="bx bx-plus-circle me-2"></i>
|
||||
<span className="d-none d-md-inline-block">Add Payment Request</span>
|
||||
<span className="d-none d-md-inline-block">
|
||||
Add Payment Request
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Add/Edit Modal */}
|
||||
{ManagePaymentRequestModal.IsOpen && (
|
||||
<GlobalModel
|
||||
isOpen
|
||||
@ -63,15 +77,13 @@ const PaymentRequestPage = () => {
|
||||
</GlobalModel>
|
||||
)}
|
||||
|
||||
{/* Expense List Placeholder */}
|
||||
{/* Payment Request List */}
|
||||
<div className="card">
|
||||
{/* <div className="card-body text-center text-muted py-5">
|
||||
<p>No Expense Data found</p>
|
||||
</div> */}
|
||||
<PaymentRequestList/>
|
||||
<PaymentRequestList
|
||||
search={search}
|
||||
setManagePaymentRequestModal={setManagePaymentRequestModal}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -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),
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
import { api } from "../utils/axiosClient";
|
||||
|
||||
|
||||
const PaymentRequestRepository = {
|
||||
|
||||
|
||||
CreatePaymentRequest:(data)=>api.post("/api/expense/payment-request/create",data),
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default PaymentRequestRepository;
|
||||
Loading…
x
Reference in New Issue
Block a user