Refactor_Expenses #321
@ -1,5 +1,5 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useExpenseList } from "../../hooks/useExpense";
|
import { useDeleteExpense, useExpenseList } from "../../hooks/useExpense";
|
||||||
import Avatar from "../common/Avatar";
|
import Avatar from "../common/Avatar";
|
||||||
import { useExpenseContext } from "../../pages/Expense/ExpensePage";
|
import { useExpenseContext } from "../../pages/Expense/ExpensePage";
|
||||||
import { formatDate, formatUTCToLocalTime } from "../../utils/dateUtils";
|
import { formatDate, formatUTCToLocalTime } from "../../utils/dateUtils";
|
||||||
@ -7,12 +7,17 @@ import Pagination from "../common/Pagination";
|
|||||||
import { ITEMS_PER_PAGE } from "../../utils/constants";
|
import { ITEMS_PER_PAGE } from "../../utils/constants";
|
||||||
import { AppColorconfig, getColorNameFromHex } from "../../utils/appUtils";
|
import { AppColorconfig, getColorNameFromHex } from "../../utils/appUtils";
|
||||||
import { ExpenseTableSkeleton } from "./ExpenseSkeleton";
|
import { ExpenseTableSkeleton } from "./ExpenseSkeleton";
|
||||||
|
import ConfirmModal from "../common/ConfirmModal";
|
||||||
|
import { useProfile } from "../../hooks/useProfile";
|
||||||
|
|
||||||
const ExpenseList = () => {
|
const ExpenseList = () => {
|
||||||
const { setViewExpense,setManageExpenseModal } = useExpenseContext();
|
const [deletingId, setDeletingId] = useState(null);
|
||||||
|
const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||||
|
const { setViewExpense, setManageExpenseModal } = useExpenseContext();
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const pageSize = 10;
|
const pageSize = 10;
|
||||||
|
const {profile} = useProfile()
|
||||||
|
console.log(profile)
|
||||||
const filter = {
|
const filter = {
|
||||||
projectIds: [],
|
projectIds: [],
|
||||||
statusIds: [],
|
statusIds: [],
|
||||||
@ -21,10 +26,25 @@ const ExpenseList = () => {
|
|||||||
startDate: null,
|
startDate: null,
|
||||||
endDate: null,
|
endDate: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const { data, isLoading, isError,isInitialLoading,error,isFetching } = useExpenseList(10, currentPage, filter);
|
const { mutate: DeleteExpense, isPending } = useDeleteExpense();
|
||||||
if (isInitialLoading ) return <ExpenseTableSkeleton/>;
|
const { data, isLoading, isError, isInitialLoading, error, isFetching } =
|
||||||
|
useExpenseList(10, currentPage, filter);
|
||||||
|
|
||||||
|
const handleDelete = (id) => {
|
||||||
|
setDeletingId(id);
|
||||||
|
DeleteExpense(
|
||||||
|
{ id },
|
||||||
|
{
|
||||||
|
onSettled: () => {
|
||||||
|
setDeletingId(null);
|
||||||
|
setIsDeleteModalOpen(false)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isInitialLoading) return <ExpenseTableSkeleton />;
|
||||||
if (isError) return <div>{error}</div>;
|
if (isError) return <div>{error}</div>;
|
||||||
const items = data?.data ?? [];
|
const items = data?.data ?? [];
|
||||||
const totalPages = data?.totalPages ?? 1;
|
const totalPages = data?.totalPages ?? 1;
|
||||||
@ -36,16 +56,41 @@ const ExpenseList = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
{IsDeleteModalOpen && (
|
||||||
|
<div
|
||||||
|
className={`modal fade ${IsDeleteModalOpen ? "show" : ""}`}
|
||||||
|
tabIndex="-1"
|
||||||
|
role="dialog"
|
||||||
|
style={{
|
||||||
|
display: IsDeleteModalOpen ? "block" : "none",
|
||||||
|
backgroundColor: IsDeleteModalOpen
|
||||||
|
? "rgba(0,0,0,0.5)"
|
||||||
|
: "transparent",
|
||||||
|
}}
|
||||||
|
aria-hidden="false"
|
||||||
|
>
|
||||||
|
|
||||||
|
<ConfirmModal
|
||||||
|
type={"delete"}
|
||||||
|
header={"Delete Expense"}
|
||||||
|
message={"Are you sure you want delete?"}
|
||||||
|
onSubmit={handleDelete}
|
||||||
|
onClose={() => setIsDeleteModalOpen(false)}
|
||||||
|
loading={isPending}
|
||||||
|
paramData={deletingId}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="card ">
|
<div className="card ">
|
||||||
<div className="card-datatable table-responsive">
|
<div className="card-datatable table-responsive">
|
||||||
<div
|
<div
|
||||||
id="DataTables_Table_0_wrapper"
|
id="DataTables_Table_0_wrapper"
|
||||||
className="dataTables_wrapper no-footer"
|
className="dataTables_wrapper no-footer"
|
||||||
|
|
||||||
>
|
>
|
||||||
<table
|
<table
|
||||||
className="datatables-users table border-top dataTable no-footer dtr-column text-nowrap"
|
className="datatables-users table border-top dataTable no-footer dtr-column text-nowrap"
|
||||||
|
|
||||||
aria-describedby="DataTables_Table_0_info"
|
aria-describedby="DataTables_Table_0_info"
|
||||||
id="horizontal-example"
|
id="horizontal-example"
|
||||||
>
|
>
|
||||||
@ -149,7 +194,9 @@ const ExpenseList = () => {
|
|||||||
<tr key={expense.id} className="odd">
|
<tr key={expense.id} className="odd">
|
||||||
<td className="sorting_1" colSpan={2}>
|
<td className="sorting_1" colSpan={2}>
|
||||||
<div className="d-flex justify-content-start align-items-center user-name ms-6">
|
<div className="d-flex justify-content-start align-items-center user-name ms-6">
|
||||||
<span>{formatUTCToLocalTime(expense.transactionDate)}</span>
|
<span>
|
||||||
|
{formatUTCToLocalTime(expense.transactionDate)}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="text-start d-none d-sm-table-cell ms-5">
|
<td className="text-start d-none d-sm-table-cell ms-5">
|
||||||
@ -173,36 +220,68 @@ const ExpenseList = () => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="d-none d-md-table-cell text-end"><i className='bx bx-rupee b-xs'></i>{expense?.amount}</td>
|
<td className="d-none d-md-table-cell text-end">
|
||||||
|
<i className="bx bx-rupee b-xs"></i>
|
||||||
|
{expense?.amount}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span
|
<span
|
||||||
className={`badge bg-label-${getColorNameFromHex(expense?.status?.color) || 'secondary'}`}
|
className={`badge bg-label-${
|
||||||
|
getColorNameFromHex(expense?.status?.color) ||
|
||||||
|
"secondary"
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
|
{expense.status?.displayName || "Unknown"}
|
||||||
{expense.status?.displayName || "Unknown"}
|
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td >
|
<td>
|
||||||
<div className="d-flex justify-content-center align-items-center gap-2">
|
<div className="d-flex justify-content-strat align-items-center gap-2">
|
||||||
<span
|
<span
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setViewExpense({ expenseId:expense.id, view: true })
|
setViewExpense({
|
||||||
}
|
expenseId: expense.id,
|
||||||
>
|
view: true,
|
||||||
<i className="bx bx-show text-primary "></i>
|
})
|
||||||
</span>
|
}
|
||||||
<span
|
>
|
||||||
className="cursor-pointer"
|
<i className="bx bx-show text-primary "></i>
|
||||||
onClick={()=>setManageExpenseModal({IsOpen:true,expenseId:expense.id})}
|
</span>
|
||||||
>
|
{(expense.status.name === 'Draft' || expense.status.name === 'Rejected') && (expense.createdBy.id === profile.employeeInfo.id ) &&(
|
||||||
<i className='bx bx-edit bx-sm text-secondary'></i>
|
<span
|
||||||
</span>
|
className="cursor-pointer"
|
||||||
<span
|
onClick={() =>
|
||||||
className="cursor-pointer"
|
setManageExpenseModal({
|
||||||
>
|
IsOpen: true,
|
||||||
<i className='bx bx-trash bx-sm text-danger' ></i>
|
expenseId: expense.id,
|
||||||
</span>
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<i className="bx bx-edit bx-sm text-secondary"></i>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{expense.status.name == "Draft" && (
|
||||||
|
<span
|
||||||
|
className="cursor-pointer"
|
||||||
|
onClick={() => {
|
||||||
|
setIsDeleteModalOpen(true)
|
||||||
|
setDeletingId(expense.id)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* {deletingId === expense.id ? (
|
||||||
|
<div
|
||||||
|
className="spinner-border spinner-border-sm text-secondary"
|
||||||
|
role="status"
|
||||||
|
>
|
||||||
|
<span className="visually-hidden">
|
||||||
|
Loading...
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
) : ( */}
|
||||||
|
<i className="bx bx-trash bx-sm text-danger"></i>
|
||||||
|
{/* )} */}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -211,15 +290,15 @@ const ExpenseList = () => {
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{!isInitialLoading && items.length > 0 && (
|
{!isInitialLoading && items.length > 0 && (
|
||||||
<Pagination
|
<Pagination
|
||||||
currentPage={currentPage}
|
currentPage={currentPage}
|
||||||
totalPages={totalPages}
|
totalPages={totalPages}
|
||||||
onPageChange={paginate}
|
onPageChange={paginate}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -163,3 +163,33 @@ export const useActionOnExpense = (onSuccessCallBack) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useDeleteExpense = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async ({ id }) => {
|
||||||
|
const response = await ExpenseRepository.DeleteExpense(id);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
onSuccess: (data, variables) => {
|
||||||
|
queryClient.setQueryData(["Expenses"], (oldData) => {
|
||||||
|
if (!oldData || !oldData.data) return queryClient.invalidateQueries({queryKey:["Expenses"]});
|
||||||
|
|
||||||
|
const updatedList = oldData.data.filter(
|
||||||
|
(expense) => expense.id !== variables.id
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...oldData,
|
||||||
|
data: updatedList,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
showToast(data.message || "Expense deleted successfully", "success");
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
showToast("Failed to delete expense", "error");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -13,7 +13,7 @@ const ExpenseRepository = {
|
|||||||
GetExpenseDetails:(id)=>api.get(`/api/Expense/details/${id}`),
|
GetExpenseDetails:(id)=>api.get(`/api/Expense/details/${id}`),
|
||||||
CreateExpense:(data)=>api.post("/api/Expense/create",data),
|
CreateExpense:(data)=>api.post("/api/Expense/create",data),
|
||||||
UpdateExpense:(id,data)=>api.put(`/api/Expense/edit/${id}`,data),
|
UpdateExpense:(id,data)=>api.put(`/api/Expense/edit/${id}`,data),
|
||||||
DeleteExpense:(id)=>api.delete(`/api/Expense/edit/${id}`),
|
DeleteExpense:(id)=>api.delete(`/api/Expense/delete/${id}`),
|
||||||
|
|
||||||
ActionOnExpense:(data)=>api.post('/api/expense/action',data),
|
ActionOnExpense:(data)=>api.post('/api/expense/action',data),
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user