Compare commits
No commits in common. "280715d62f5a6bdd0aaed31e93de21d31361be0d" and "dbdb7a1299437828628610406f4e06c7d40cac46" have entirely different histories.
280715d62f
...
dbdb7a1299
@ -254,11 +254,6 @@ const CreateExpense = ({closeModal}) => {
|
|||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</select>
|
</select>
|
||||||
{errors.paidById && (
|
|
||||||
<small className="danger-text">
|
|
||||||
{errors.paidById.message}
|
|
||||||
</small>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -20,9 +20,8 @@ const ExpenseList = () => {
|
|||||||
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;
|
||||||
@ -38,13 +37,12 @@ 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"
|
||||||
id="horizontal-example"
|
style={{ width: "100%" }}
|
||||||
>
|
>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -133,7 +131,7 @@ const ExpenseList = () => {
|
|||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isInitialLoading && items.length === 0 && (
|
{!isLoading && 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.
|
||||||
@ -141,12 +139,12 @@ const ExpenseList = () => {
|
|||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isInitialLoading &&
|
{!isLoading &&
|
||||||
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.transactionDate)}</span>
|
<span>{formatUTCToLocalTime(expense.createdAt)}</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">
|
||||||
@ -170,7 +168,7 @@ 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"><i className='bx bx-rupee b-xs'></i>{expense.amount}</td>
|
||||||
<td>
|
<td>
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
@ -185,37 +183,22 @@ const ExpenseList = () => {
|
|||||||
{expense.status?.name || "Unknown"}
|
{expense.status?.name || "Unknown"}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td >
|
<td>
|
||||||
<div className="d-flex justify-content-center align-items-center gap-2">
|
<span
|
||||||
<span
|
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setViewExpense({ expenseId: expense, view: true })
|
setViewExpense({ expenseId: expense, view: true })
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<i className="bx bx-show text-primary "></i>
|
<i className="bx bx-show "></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>
|
||||||
{!isInitialLoading && items.length > 0 && (
|
{!isLoading && items.length > 0 && (
|
||||||
<Pagination
|
<Pagination
|
||||||
currentPage={currentPage}
|
currentPage={currentPage}
|
||||||
totalPages={totalPages}
|
totalPages={totalPages}
|
||||||
|
|||||||
@ -67,8 +67,3 @@ export const ExpenseSchema = (expenseTypes) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ActionSchema = z.object({
|
|
||||||
comment : z.string().min(1,{message:"Please leave comment"}),
|
|
||||||
selectedStatus: z.string().min(1, { message: "Please select a status" }),
|
|
||||||
})
|
|
||||||
@ -1,89 +1,68 @@
|
|||||||
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(
|
await ExpenseRepository.GetExpenseList( pageSize, pageNumber, filter ).then((res) => res.data),
|
||||||
(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) => {
|
|
||||||
showToast("Expense Created Successfully", "success");
|
|
||||||
queryClient.invalidateQueries({ queryKey: ["expenses"] });
|
|
||||||
if (onSuccessCallBack) onSuccessCallBack();
|
|
||||||
},
|
|
||||||
onError: (error) => {
|
|
||||||
showToast(
|
|
||||||
error.message || "Something went wrong please try again !",
|
|
||||||
"error"
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useActionOnExpense = (onSuccessCallBack) => {
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
return useMutation({
|
|
||||||
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,
|
|
||||||
},
|
},
|
||||||
(oldData) => {
|
onSuccess:(_,variables)=>{
|
||||||
if (!oldData) return oldData;
|
showToast("Expense Created Successfully","success")
|
||||||
return {
|
queryClient.invalidateQueries({queryKey:["expenses"]})
|
||||||
...oldData,
|
if (onSuccessCallBack) onSuccessCallBack();
|
||||||
data: oldData.data.map((item) =>
|
},
|
||||||
item.id === updatedExpense.id
|
onError:(error)=>{
|
||||||
? {
|
showToast(error.message || "Something went wrong please try again !","success")
|
||||||
...item,
|
|
||||||
nextStatus: updatedExpense.nextStatus,
|
|
||||||
status: updatedExpense.status,
|
|
||||||
}
|
|
||||||
: item
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
);
|
})
|
||||||
|
}
|
||||||
if (onSuccessCallBack) onSuccessCallBack();
|
const demoExpense = {
|
||||||
|
projectId: "proj_123",
|
||||||
|
expensesTypeId: "1", // corresponds to Travel
|
||||||
|
paymentModeId: "pm_456",
|
||||||
|
paidById: "emp_789",
|
||||||
|
transactionDate: "2025-07-21",
|
||||||
|
transactionId: "TXN-001234",
|
||||||
|
description: "Taxi fare from airport to hotel",
|
||||||
|
location: "New York",
|
||||||
|
supplerName: "City Taxi Service",
|
||||||
|
amount: 45.50,
|
||||||
|
noOfPersons: 2,
|
||||||
|
billAttachments: [
|
||||||
|
{
|
||||||
|
fileName: "receipt.pdf",
|
||||||
|
base64Data: "JVBERi0xLjQKJcfs...", // truncated base64 example string
|
||||||
|
contentType: "application/pdf",
|
||||||
|
fileSize: 450000, // less than 5MB
|
||||||
|
description: "Taxi receipt",
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
],
|
||||||
showToast(
|
|
||||||
error.message || "Something went wrong, please try again!",
|
|
||||||
"error"
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user