Refactor_Expenses #321

Merged
pramod.mahajan merged 249 commits from Refactor_Expenses into hotfix/MasterActivity 2025-08-01 13:14:59 +00:00
3 changed files with 109 additions and 59 deletions
Showing only changes of commit 9df4b20ff0 - Show all commits

View File

@ -254,6 +254,11 @@ const CreateExpense = ({closeModal}) => {
)) ))
)} )}
</select> </select>
{errors.paidById && (
<small className="danger-text">
{errors.paidById.message}
</small>
)}
</div> </div>
</div> </div>

View File

@ -19,9 +19,10 @@ const ExpenseList = () => {
startDate: null, startDate: null,
endDate: null, endDate: null,
}; };
const { data, isLoading, isError } = useExpenseList(ITEMS_PER_PAGE, currentPage, filter); const { data, isLoading, isError,isInitialLoading } = useExpenseList(2, currentPage, filter);
if (isLoading) return <div>Loading...</div>; if (isInitialLoading) return <div>Loading...</div>;
const items = data.data ?? []; const items = data.data ?? [];
const totalPages = data?.totalPages ?? 1; const totalPages = data?.totalPages ?? 1;
const hasMore = currentPage < totalPages; const hasMore = currentPage < totalPages;
@ -37,12 +38,13 @@ const ExpenseList = () => {
<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"
id="DataTables_Table_0"
aria-describedby="DataTables_Table_0_info" aria-describedby="DataTables_Table_0_info"
style={{ width: "100%" }} id="horizontal-example"
> >
<thead> <thead>
<tr> <tr>
@ -131,7 +133,7 @@ const ExpenseList = () => {
</tr> </tr>
)} )}
{!isLoading && items.length === 0 && ( {!isInitialLoading && items.length === 0 && (
<tr> <tr>
<td colSpan={7} className="text-center py-3"> <td colSpan={7} className="text-center py-3">
No expenses found. No expenses found.
@ -139,12 +141,12 @@ const ExpenseList = () => {
</tr> </tr>
)} )}
{!isLoading && {!isInitialLoading &&
items.map((expense) => ( items.map((expense) => (
<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.createdAt)}</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">
@ -183,22 +185,37 @@ const ExpenseList = () => {
{expense.status?.name || "Unknown"} {expense.status?.name || "Unknown"}
</span> </span>
</td> </td>
<td> <td >
<span <div className="d-flex justify-content-center align-items-center gap-2">
<span
className="cursor-pointer" className="cursor-pointer"
onClick={() => onClick={() =>
setViewExpense({ expenseId: expense, view: true }) setViewExpense({ expenseId: expense, view: true })
} }
> >
<i className="bx bx-show "></i> <i className="bx bx-show text-primary "></i>
</span> </span>
<span
className="cursor-pointer"
>
<i className='bx bx-edit bx-sm text-secondary'></i>
</span>
<span
className="cursor-pointer"
>
<i className='bx bx-trash bx-sm text-danger' ></i>
</span>
</div>
</td> </td>
</tr> </tr>
))} ))}
</tbody> </tbody>
</table> </table>
</div> </div>
{!isLoading && items.length > 0 && ( {!isInitialLoading && items.length > 0 && (
<Pagination <Pagination
currentPage={currentPage} currentPage={currentPage}
totalPages={totalPages} totalPages={totalPages}

View File

@ -1,61 +1,89 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query" import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import ExpenseRepository from "../repositories/ExpsenseRepository" import ExpenseRepository from "../repositories/ExpsenseRepository";
import showToast from "../services/toastService" import showToast from "../services/toastService";
import { queryClient } from "../layouts/AuthLayout"; import { queryClient } from "../layouts/AuthLayout";
// -------------------Query------------------------------------------------------ // -------------------Query------------------------------------------------------
export const useExpenseList=( pageSize, pageNumber, filter ) =>{ export const useExpenseList = (pageSize, pageNumber, filter) => {
return useQuery({
return useQuery({
queryKey: ["expenses", pageNumber, pageSize, filter], queryKey: ["expenses", pageNumber, pageSize, filter],
queryFn: async() => queryFn: async () =>
await ExpenseRepository.GetExpenseList( pageSize, pageNumber, filter ).then((res) => res.data), await ExpenseRepository.GetExpenseList(pageSize, pageNumber, filter).then(
(res) => res.data
),
keepPreviousData: true, keepPreviousData: true,
}); });
} };
export const useExpense =(ExpenseId)=>{
return useQuery({
queryKey:["Expense",ExpenseId],
queryFn:async()=>await ExpenseRepository.GetExpenseDetails(ExpenseId)
})
}
export const useExpense = (ExpenseId) => {
return useQuery({
queryKey: ["Expense", ExpenseId],
queryFn: async () => await ExpenseRepository.GetExpenseDetails(ExpenseId),
});
};
// ---------------------------Mutation--------------------------------------------- // ---------------------------Mutation---------------------------------------------
export const useCreateExpnse =(onSuccessCallBack)=>{ export const useCreateExpnse = (onSuccessCallBack) => {
const queryClient = useQueryClient() const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async(payload)=>{ mutationFn: async (payload) => {
await ExpenseRepository.CreateExpense(payload) await ExpenseRepository.CreateExpense(payload);
}, },
onSuccess:(_,variables)=>{ onSuccess: (_, variables) => {
showToast("Expense Created Successfully","success") showToast("Expense Created Successfully", "success");
queryClient.invalidateQueries({queryKey:["expenses"]}) queryClient.invalidateQueries({ queryKey: ["expenses"] });
if (onSuccessCallBack) onSuccessCallBack(); if (onSuccessCallBack) onSuccessCallBack();
}, },
onError:(error)=>{ onError: (error) => {
showToast(error.message || "Something went wrong please try again !","error") showToast(
} error.message || "Something went wrong please try again !",
}) "error"
} );
},
});
};
export const useActionOnExpense=(onSuccessCallBack)=>{ export const useActionOnExpense = (onSuccessCallBack) => {
const queryClient = useQueryClient() const queryClient = useQueryClient();
return useMutation({
mutationFn: async(payload)=>{ return useMutation({
await ExpenseRepository.ActionOnExpense(payload) mutationFn: async (payload) => {
const response = await ExpenseRepository.ActionOnExpense(payload);
return response.data;
},
onSuccess: (updatedExpense, variables) => {
showToast("Expense updated successfully", "success");
queryClient.setQueriesData(
{
queryKey: ["expenses"],
exact: false,
}, },
onSuccess:(data,variables)=>{ (oldData) => {
console.log(data) if (!oldData) return oldData;
showToast("Expense Created Successfully","success") return {
if (onSuccessCallBack) onSuccessCallBack(); ...oldData,
}, data: oldData.data.map((item) =>
onError:(error)=>{ item.id === updatedExpense.id
showToast(error.message || "Something went wrong please try again !","error") ? {
...item,
nextStatus: updatedExpense.nextStatus,
status: updatedExpense.status,
}
: item
),
};
} }
}) );
}
if (onSuccessCallBack) onSuccessCallBack();
},
onError: (error) => {
showToast(
error.message || "Something went wrong, please try again!",
"error"
);
},
});
};