added api Get Advance Payment
This commit is contained in:
parent
e80223beba
commit
871daf6036
@ -1,6 +1,8 @@
|
||||
import React from "react";
|
||||
import { useExpenseTransactions } from "../../hooks/useExpense";
|
||||
|
||||
const AdvancePaymentList = ({ employeeId }) => {
|
||||
const {data,isError, isLoading,isFetching,error} = useExpenseTransactions(employeeId)
|
||||
const record = {
|
||||
openingBalance: 25000.0,
|
||||
rows: [
|
||||
@ -71,7 +73,6 @@ const AdvancePaymentList = ({ employeeId }) => {
|
||||
{ id: 20, description: "Closing Balance", credit: 0.0, debit: 0.0 },
|
||||
],
|
||||
};
|
||||
|
||||
let currentBalance = record.openingBalance;
|
||||
const rowsWithBalance = record.rows.map((r) => {
|
||||
currentBalance += r.credit - r.debit;
|
||||
@ -134,6 +135,7 @@ const AdvancePaymentList = ({ employeeId }) => {
|
||||
currency: "INR",
|
||||
})
|
||||
: (<div className="d-flex flex-column">
|
||||
<small>{new Date().toISOString()}</small>
|
||||
<small>Projec Name</small>
|
||||
<small>{row[col.key]}</small>
|
||||
</div>)}
|
||||
|
||||
@ -184,8 +184,8 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
if (isInitialLoading && !data) return <ExpenseTableSkeleton />;
|
||||
const headers = ["Expense Type","Payment Mode","Submitted By","Submitted","Amount","Status","Action"]
|
||||
if (isInitialLoading && !data) return <ExpenseTableSkeleton headers={headers} />;
|
||||
if (isError) return <div>{error?.message}</div>;
|
||||
|
||||
const grouped = groupBy
|
||||
|
||||
@ -143,7 +143,7 @@ const SkeletonCell = ({
|
||||
/>
|
||||
);
|
||||
|
||||
export const ExpenseTableSkeleton = ({ groups = 3, rowsPerGroup = 3 }) => {
|
||||
export const ExpenseTableSkeleton = ({ groups = 3, rowsPerGroup = 3, headers }) => {
|
||||
return (
|
||||
<div className="card px-2">
|
||||
<table
|
||||
@ -153,17 +153,12 @@ export const ExpenseTableSkeleton = ({ groups = 3, rowsPerGroup = 3 }) => {
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="d-none d-sm-table-cell">
|
||||
<div className="text-start ms-5">Expense Type</div>
|
||||
{headers.map((header)=>(
|
||||
<th className="d-none d-sm-table-cell">
|
||||
<div className="text-start ms-5">{header}</div>
|
||||
</th>
|
||||
<th className="d-none d-sm-table-cell">
|
||||
<div className="text-start ms-5">Payment Mode</div>
|
||||
</th>
|
||||
<th className="d-none d-sm-table-cell">Submitted By</th>
|
||||
<th className="d-none d-sm-table-cell">Submitted</th>
|
||||
<th className="d-none d-md-table-cell">Amount</th>
|
||||
<th>Status</th>
|
||||
<th>Action</th>
|
||||
))}
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ import { useForm } from 'react-hook-form';
|
||||
import { useExpenseType } from '../../hooks/masterHook/useMaster';
|
||||
import DatePicker from '../common/DatePicker';
|
||||
import { useCreatePaymentRequest, useUpdatePaymentRequest } from '../../hooks/useExpense';
|
||||
import { defaultPaymentRequest, PaymentRequestSchema } from '../../pages/PaymentRequest/PaymentRequestSchema';
|
||||
import { defaultPaymentRequest, PaymentRequestSchema } from './PaymentRequestSchema';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { formatFileSize, localToUtc } from '../../utils/appUtils';
|
||||
|
||||
|
||||
168
src/components/PaymentRequest/PaymentRequestList.jsx
Normal file
168
src/components/PaymentRequest/PaymentRequestList.jsx
Normal file
@ -0,0 +1,168 @@
|
||||
import React, { useState } from "react";
|
||||
import { ITEMS_PER_PAGE } from "../../utils/constants";
|
||||
import { useDebounce } from "../../utils/appUtils";
|
||||
import { formatDate } from "../../utils/dateUtils";
|
||||
import { usePaymentRequestList } from "../../hooks/useExpense";
|
||||
import ExpenseSkeleton, {
|
||||
ExpenseTableSkeleton,
|
||||
} from "../Expenses/ExpenseSkeleton";
|
||||
|
||||
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" },
|
||||
];
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
const header = [
|
||||
"Expense ID",
|
||||
"Expense Category",
|
||||
"Payment Mode",
|
||||
"Sumitted By",
|
||||
"Submitted",
|
||||
"Amount",
|
||||
"Status",
|
||||
"Action",
|
||||
];
|
||||
if (isLoading) return <ExpenseTableSkeleton headers={header} />;
|
||||
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;
|
||||
@ -263,7 +263,8 @@ export const useHasAnyPermission = (permissionIdsInput) => {
|
||||
return permissionIds.some((id) => permissions.includes(id));
|
||||
};
|
||||
|
||||
// ---------------------------Payment Request---------------------------------------------
|
||||
//#region Payment Request
|
||||
// ---------------------------Get Payment Request---------------------------------------------
|
||||
export const usePaymentRequestList = (
|
||||
pageSize,
|
||||
pageNumber,
|
||||
@ -281,10 +282,9 @@ export const usePaymentRequestList = (
|
||||
});
|
||||
};
|
||||
|
||||
// CREATE PAYMENT REQUEST
|
||||
// ---------------------------Put Post Payment Request---------------------------------------
|
||||
export const useCreatePaymentRequest = (onSuccessCallBack) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (payload) => {
|
||||
await ExpenseRepository.CreatePaymentRequest(payload);
|
||||
@ -303,7 +303,6 @@ export const useCreatePaymentRequest = (onSuccessCallBack) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdatePaymentRequest = (onSuccessCallBack) => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
@ -322,4 +321,19 @@ export const useUpdatePaymentRequest = (onSuccessCallBack) => {
|
||||
showToast("Something went wrong.Please try again later.", "error");
|
||||
},
|
||||
});
|
||||
};
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//#region Advance Payment
|
||||
export const useExpenseTransactions = (employeeId)=>{
|
||||
return useQuery({
|
||||
queryKey:["transaction",employeeId],
|
||||
queryFn:async()=> {
|
||||
debugger
|
||||
const resp = await ExpenseRepository.GetTranctionList(employeeId);
|
||||
return resp.data
|
||||
},
|
||||
enabled:!!employeeId
|
||||
})
|
||||
}
|
||||
//#endregion
|
||||
@ -30,14 +30,14 @@ const AdvancePaymentPage = () => {
|
||||
<Label>Search Employee</Label>
|
||||
<EmployeeSearchInput
|
||||
control={control}
|
||||
name="paidById"
|
||||
name="employeeId"
|
||||
projectId={null}
|
||||
forAll={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AdvancePaymentList/>
|
||||
<AdvancePaymentList employeeId={selectedEmployeeId}/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,150 +0,0 @@
|
||||
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 = ({ 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" },
|
||||
];
|
||||
|
||||
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;
|
||||
@ -1,8 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||
import GlobalModel from "../../components/common/GlobalModel";
|
||||
import ManagePaymentRequest from "../../components/PaymentRequest/ManagePaymentRequest";
|
||||
import PaymentRequestList from "./PaymentRequestList";
|
||||
import PaymentRequestList from "../../components/PaymentRequest/PaymentRequestList";
|
||||
|
||||
const PaymentRequestPage = () => {
|
||||
const [ManagePaymentRequestModal, setManagePaymentRequestModal] = useState({
|
||||
@ -33,7 +32,7 @@ const PaymentRequestPage = () => {
|
||||
className="form-control form-control-sm w-auto"
|
||||
placeholder="Search Payment Req.."
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -67,7 +66,7 @@ const PaymentRequestPage = () => {
|
||||
setManagePaymentRequestModal({ IsOpen: null, expenseId: null })
|
||||
}
|
||||
>
|
||||
<ManagePaymentRequest
|
||||
<ManagePaymentRequestModal
|
||||
key={ManagePaymentRequestModal.expenseId ?? "new"}
|
||||
expenseToEdit={ManagePaymentRequestModal.expenseId}
|
||||
closeModal={() =>
|
||||
@ -80,7 +79,7 @@ const PaymentRequestPage = () => {
|
||||
{/* Payment Request List */}
|
||||
<div className="card">
|
||||
<PaymentRequestList
|
||||
search={search}
|
||||
search={search}
|
||||
setManagePaymentRequestModal={setManagePaymentRequestModal}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -2,28 +2,33 @@ import { api } from "../utils/axiosClient";
|
||||
|
||||
|
||||
const ExpenseRepository = {
|
||||
//#region Expense
|
||||
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'),
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Payment Request
|
||||
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),
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region Advance Payment
|
||||
GetTranctionList:()=>api.get(`/get/transactions/${employeeId}`)
|
||||
//#endregion
|
||||
}
|
||||
|
||||
export default ExpenseRepository;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user