import React, { useState } from "react"; import { useDeleteExpense, useExpenseList } from "../../hooks/useExpense"; import Avatar from "../common/Avatar"; import { useExpenseContext } from "../../pages/Expense/ExpensePage"; import { formatDate, formatUTCToLocalTime } from "../../utils/dateUtils"; import Pagination from "../common/Pagination"; import { APPROVE_EXPENSE, EXPENSE_DRAFT, EXPENSE_REJECTEDBY } from "../../utils/constants"; import { getColorNameFromHex, useDebounce } from "../../utils/appUtils"; import { ExpenseTableSkeleton } from "./ExpenseSkeleton"; import ConfirmModal from "../common/ConfirmModal"; import { useHasUserPermission } from "../../hooks/useHasUserPermission"; import { useSelector } from "react-redux"; const ExpenseList = ({ filters, groupBy = "transactionDate",searchText }) => { const [deletingId, setDeletingId] = useState(null); const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const { setViewExpense, setManageExpenseModal } = useExpenseContext(); const IsExpenseEditable = useHasUserPermission(); const IsExpesneApprpve = useHasUserPermission(APPROVE_EXPENSE); const [currentPage, setCurrentPage] = useState(1); const pageSize = 20; const debouncedSearch = useDebounce(searchText, 500); const { mutate: DeleteExpense, isPending } = useDeleteExpense(); const { data, isLoading, isError, isInitialLoading, error } = useExpenseList( pageSize, currentPage, filters, debouncedSearch ); const SelfId = useSelector( (store) => store?.globalVariables?.loginUser?.employeeInfo?.id ); const handleDelete = (id) => { setDeletingId(id); DeleteExpense( { id }, { onSettled: () => { setDeletingId(null); setIsDeleteModalOpen(false); }, } ); }; const paginate = (page) => { if (page >= 1 && page <= (data?.totalPages ?? 1)) { setCurrentPage(page); } }; const groupByField = (items, field) => { return items.reduce((acc, item) => { let key; switch (field) { case "transactionDate": key = item.transactionDate?.split("T")[0]; break; case "status": key = item.status?.displayName || "Unknown"; break; case "paidBy": key = `${item.paidBy?.firstName ?? ""} ${ item.paidBy?.lastName ?? "" }`.trim(); break; case "project": key = item.project?.name || "Unknown Project"; break; case "paymentMode": key = item.paymentMode?.name || "Unknown Mode"; break; case "expensesType": key = item.expensesType?.name || "Unknown Type"; break; case "createdAt": key = item.createdAt?.split("T")[0] || "Unknown Type"; break; default: key = "Others"; } if (!acc[key]) acc[key] = []; acc[key].push(item); return acc; }, {}); }; const expenseColumns = [ { key: "expensesType", label: "Expense Type", getValue: (e) => e.expensesType?.name || "N/A", align: "text-start", }, { key: "paymentMode", label: "Payment Mode", getValue: (e) => e.paymentMode?.name || "N/A", align: "text-start", }, { key: "paidBy", label: "Paid By", align: "text-start", getValue: (e) => `${e.paidBy?.firstName ?? ""} ${e.paidBy?.lastName ?? ""}`.trim() || "N/A", customRender: (e) => (
{`${e.paidBy?.firstName ?? ""} ${ e.paidBy?.lastName ?? "" }`.trim() || "N/A"}
), }, { key: "submitted", label: "Submitted", getValue: (e) => formatUTCToLocalTime(e?.createdAt), isAlwaysVisible: true, }, { key: "amount", label: "Amount", getValue: (e) => ( <> {e?.amount} ), isAlwaysVisible: true, align: "text-end", }, { key: "status", label: "Status", align: "text-center", getValue: (e) => ( {e.status?.name || "Unknown"} ), }, ]; if (isInitialLoading) return ; if (isError) return
{error}
; const grouped = groupBy ? groupByField(data?.data ?? [], groupBy) : { All: data?.data ?? [] }; const IsGroupedByDate = ["transactionDate", "createdAt"].includes(groupBy); const canEditExpense = (expense) => { return ( (expense.status.id === EXPENSE_DRAFT || EXPENSE_REJECTEDBY.includes(expense.status.id)) && expense.createdBy?.id === SelfId ); }; const canDetetExpense = (expense)=>{ return (expense.status.id === EXPENSE_DRAFT && expense.createdBy.id === SelfId ) } return ( <> {IsDeleteModalOpen && (
setIsDeleteModalOpen(false)} loading={isPending} paramData={deletingId} />
)}
{expenseColumns.map( (col) => (col.isAlwaysVisible || groupBy !== col.key) && ( ) )} {Object.keys(grouped).length > 0 ? ( Object.entries(grouped).map(([group, expenses]) => ( {expenses.map((expense) => ( {expenseColumns.map( (col) => (col.isAlwaysVisible || groupBy !== col.key) && ( ) )} ))} )) ) : ( )}
{col.label}
Action
{IsGroupedByDate ? formatUTCToLocalTime(group) : group}
{col.customRender ? col.customRender(expense) : col.getValue(expense)}
setViewExpense({ expenseId: expense.id, view: true, }) } > {canEditExpense(expense) && ( setManageExpenseModal({ IsOpen: true, expenseId: expense.id, }) } > )} {canDetetExpense(expense) && ( { setIsDeleteModalOpen(true); setDeletingId(expense.id); }} > )}
No Expense Found
{data?.data?.length > 0 && ( )}
); }; export default ExpenseList;