Compare commits

..

No commits in common. "a87d3fb20aedb335f55f5aebe46ea889c9443936" and "0c8c954b9cb3e4d0a477474eaadcdf9c84e4bde0" have entirely different histories.

4 changed files with 250 additions and 174 deletions

View File

@ -23,11 +23,11 @@ const ExpenseFilterPanel = ({ onApply, handleGroupBy }) => {
const groupByList = useMemo(() => [ const groupByList = useMemo(() => [
{ id: "transactionDate", name: "Transaction Date" }, { id: "transactionDate", name: "Transaction Date" },
{ id: "status", name: "Status" }, { id: "status", name: "Status" },
{ id: "submittedBy", name: "Submitted By" }, { id: "paidBy", name: "Paid By" },
{ id: "project", name: "Project" }, { id: "project", name: "Project" },
{ id: "paymentMode", name: "Payment Mode" }, { id: "paymentMode", name: "Payment Mode" },
{ id: "expensesType", name: "Expense Type" }, { id: "expensesType", name: "Expense Type" },
{id: "createdAt",name:"Submitted Date"} {id: "createdAt",name:"Submitted"}
], []); ], []);
const [selectedGroup, setSelectedGroup] = useState(groupByList[0]); const [selectedGroup, setSelectedGroup] = useState(groupByList[0]);

View File

@ -4,18 +4,14 @@ 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";
import Pagination from "../common/Pagination"; import Pagination from "../common/Pagination";
import { import { APPROVE_EXPENSE, EXPENSE_DRAFT, EXPENSE_REJECTEDBY } from "../../utils/constants";
APPROVE_EXPENSE,
EXPENSE_DRAFT,
EXPENSE_REJECTEDBY,
} from "../../utils/constants";
import { getColorNameFromHex, useDebounce } from "../../utils/appUtils"; import { getColorNameFromHex, useDebounce } from "../../utils/appUtils";
import { ExpenseTableSkeleton } from "./ExpenseSkeleton"; import { ExpenseTableSkeleton } from "./ExpenseSkeleton";
import ConfirmModal from "../common/ConfirmModal"; import ConfirmModal from "../common/ConfirmModal";
import { useHasUserPermission } from "../../hooks/useHasUserPermission"; import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => { const ExpenseList = ({ filters, groupBy = "transactionDate",searchText }) => {
const [deletingId, setDeletingId] = useState(null); const [deletingId, setDeletingId] = useState(null);
const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const { setViewExpense, setManageExpenseModal } = useExpenseContext(); const { setViewExpense, setManageExpenseModal } = useExpenseContext();
@ -66,9 +62,9 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
case "status": case "status":
key = item.status?.displayName || "Unknown"; key = item.status?.displayName || "Unknown";
break; break;
case "submittedBy": case "paidBy":
key = `${item.createdBy?.firstName ?? ""} ${ key = `${item.paidBy?.firstName ?? ""} ${
item.createdBy?.lastName ?? "" item.paidBy?.lastName ?? ""
}`.trim(); }`.trim();
break; break;
case "project": case "project":
@ -80,7 +76,7 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
case "expensesType": case "expensesType":
key = item.expensesType?.name || "Unknown Type"; key = item.expensesType?.name || "Unknown Type";
break; break;
case "createdAt": case "createdAt":
key = item.createdAt?.split("T")[0] || "Unknown Type"; key = item.createdAt?.split("T")[0] || "Unknown Type";
break; break;
default: default:
@ -106,23 +102,23 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
align: "text-start", align: "text-start",
}, },
{ {
key: "Submitted By", key: "paidBy",
label: "Submitted By", label: "Paid By",
align: "text-start", align: "text-start",
getValue: (e) => getValue: (e) =>
`${e.createdBy?.firstName ?? ""} ${e.createdBy?.lastName ?? ""}`.trim() || `${e.paidBy?.firstName ?? ""} ${e.paidBy?.lastName ?? ""}`.trim() ||
"N/A", "N/A",
customRender: (e) => ( customRender: (e) => (
<div className="d-flex align-items-center"> <div className="d-flex align-items-center">
<Avatar <Avatar
size="xs" size="xs"
classAvatar="m-0" classAvatar="m-0"
firstName={e.createdBy?.firstName} firstName={e.paidBy?.firstName}
lastName={e.createdBy?.lastName} lastName={e.paidBy?.lastName}
/> />
<span> <span>
{`${e.createdBy?.firstName ?? ""} ${ {`${e.paidBy?.firstName ?? ""} ${
e.createdBy?.lastName ?? "" e.paidBy?.lastName ?? ""
}`.trim() || "N/A"} }`.trim() || "N/A"}
</span> </span>
</div> </div>
@ -168,20 +164,19 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
? groupByField(data?.data ?? [], groupBy) ? groupByField(data?.data ?? [], groupBy)
: { All: data?.data ?? [] }; : { All: data?.data ?? [] };
const IsGroupedByDate = ["transactionDate", "createdAt"].includes(groupBy); const IsGroupedByDate = ["transactionDate", "createdAt"].includes(groupBy);
const canEditExpense = (expense) => { const canEditExpense = (expense) => {
return ( return (
(expense.status.id === EXPENSE_DRAFT || (expense.status.id === EXPENSE_DRAFT ||
EXPENSE_REJECTEDBY.includes(expense.status.id)) && EXPENSE_REJECTEDBY.includes(expense.status.id)) &&
expense.createdBy?.id === SelfId expense.createdBy?.id === SelfId
); );
}; };
const canDetetExpense = (expense) => { const canDetetExpense = (expense)=>{
return ( return (expense.status.id === EXPENSE_DRAFT && expense.createdBy.id === SelfId )
expense.status.id === EXPENSE_DRAFT && expense.createdBy.id === SelfId }
);
};
return ( return (
<> <>
{IsDeleteModalOpen && ( {IsDeleteModalOpen && (
@ -272,27 +267,28 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
}) })
} }
></i> ></i>
{canEditExpense(expense) && ( {canEditExpense(expense) && (
<i <i
className="bx bx-edit text-secondary cursor-pointer" className="bx bx-edit text-secondary cursor-pointer"
onClick={() => onClick={() =>
setManageExpenseModal({ setManageExpenseModal({
IsOpen: true, IsOpen: true,
expenseId: expense.id, expenseId: expense.id,
}) })
} }
></i> ></i>
)} )}
{canDetetExpense(expense) && (
<i
className="bx bx-trash text-danger cursor-pointer"
onClick={() => {
setIsDeleteModalOpen(true);
setDeletingId(expense.id);
}}
></i>
)}
{canDetetExpense(expense) && (
<i
className="bx bx-trash text-danger cursor-pointer"
onClick={() => {
setIsDeleteModalOpen(true);
setDeletingId(expense.id);
}}
></i>
)}
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -113,6 +113,9 @@ const ViewExpense = ({ ExpenseId }) => {
<hr /> <hr />
</div> </div>
<div className="text-start mb-2"> <div className="text-start mb-2">
{/* <label className="form-label me-2 mb-0 fw-semibold">
Description :
</label> */}
<div className="text-muted">{data?.description}</div> <div className="text-muted">{data?.description}</div>
</div> </div>
{/* Row 1 */} {/* Row 1 */}
@ -271,9 +274,93 @@ const ViewExpense = ({ ExpenseId }) => {
</div> </div>
</div> </div>
</div> </div>
)} )}
{/* {data.reviewedBy && (
<div className="col-md-6 mb-3 text-start">
<div className="d-flex align-items-center">
<label
className="form-label me-2 mb-0 fw-semibold"
style={{ minWidth: "130px" }}
>
Reviewed By :
</label>
<div className="d-flex align-items-center">
<Avatar
size="xs"
classAvatar="m-0"
firstName={data.reviewedBy?.firstName}
lastName={data.reviewedBy?.lastName}
/>
<span className="text-muted">
{`${data.reviewedBy?.firstName ?? ""} ${
data.reviewedBy?.lastName ?? ""
}`.trim() || "N/A"}
</span>
</div>
</div>
</div>
)}
{data.approvedBy && (
<div className="col-md-6 mb-3 text-start">
<div className="d-flex align-items-center">
<label
className="form-label me-2 mb-0 fw-semibold"
style={{ minWidth: "130px" }}
>
Approved By :{" "}
</label>
<div className="d-flex align-items-center">
<Avatar
size="xs"
classAvatar="m-0"
firstName={data.approvedBy?.firstName}
lastName={data.approvedBy?.lastName}
/>
<span className="text-muted">
{`${data.approvedBy?.firstName ?? ""} ${
data.approvedBy?.lastName ?? ""
}`.trim() || "N/A"}
</span>
</div>
</div>
</div>
)}
{data.processedBy && (
<div className="col-md-6 mb-3 text-start">
<div className="d-flex align-items-center">
<label
className="form-label me-2 mb-0 fw-semibold"
style={{ minWidth: "130px" }}
>
Processed By :{" "}
</label>
<div className="d-flex align-items-center">
<Avatar
size="xs"
classAvatar="m-0"
firstName={data.processedBy?.firstName}
lastName={data.processedBy?.lastName}
/>
<span className="text-muted">
{`${data.processedBy?.firstName ?? ""} ${
data.processedBy?.lastName ?? ""
}`.trim() || "N/A"}
</span>
</div>
</div>
</div>
)} */}
</div> </div>
{/* <div className="text-start">
<label className="form-label me-2 mb-0 fw-semibold">
Description :
</label>
<div className="text-muted">{data?.description}</div>
</div> */}
<div className="col-12 text-start"> <div className="col-12 text-start">
<label className="form-label me-2 mb-0 fw-semibold">Attachment :</label> <label className="form-label me-2 mb-0 fw-semibold">Attachment :</label>

View File

@ -1,125 +1,118 @@
[ [
{ {
"header": "", "header": "",
"items": [ "items": [
{ {
"text": "Dashboard", "text": "Dashboard",
"icon": "bx bx-home", "icon": "bx bx-home",
"available": true, "available": true,
"link": "/dashboard" "link": "/dashboard"
}, },
{ {
"text": "Projects", "text": "Projects",
"icon": "bx bx-building-house", "icon": "bx bx-building-house",
"available": true, "available": true,
"link": "/projects" "link": "/projects"
}, },
{ {
"text": "Employees", "text": "Employees",
"icon": "bx bx-user", "icon": "bx bx-user",
"available": true, "available": true,
"link": "/employees" "link": "/employees"
}, },
{ {
"text": "Activities", "text": "Activities",
"icon": "bx bx-list-ul", "icon": "bx bx-list-ul",
"available": true, "available": true,
"link": "", "link": "",
"submenu": [ "submenu": [
{ {
"text": "Attendance", "text": "Attendance",
"available": true, "available": true,
"link": "/activities/Attendance" "link": "/activities/Attendance"
}, },
{ {
"text": "Daily Task Planning", "text": "Daily Task Planning",
"available": true, "available": true,
"link": "/activities/task" "link": "/activities/task"
}, },
{ {
"text": "Daily Progress Report", "text": "Daily Progress Report",
"available": true, "available": true,
"link": "/activities/records" "link": "/activities/records"
}, },
{ {
"text": "Project Report", "text": "Project Report",
"available": true, "available": true,
"link": "/activities/reports" "link": "/activities/reports"
}, },
{ {
"text": "Daily Expenses", "text": "Daily Expenses",
"available": true, "available": true,
"link": "/activities/reports" "link": "/activities/reports"
} }
]
},
{
"text": "Directory",
"icon": "bx bx-group",
"available": true,
"link": "/directory"
},
{
"text": "Image Gallary",
"icon": "bx bx-images",
"available": true,
"link": "/gallary"
},
{
"text": "Administration",
"icon": "bx bx-box",
"available": true,
"link": "",
"submenu": [
{
"text": "Users",
"available": true,
"link": "/employees/"
},
{
"text": "Masters",
"available": true,
"link": "/masters"
}
]
},
{
"text": "Inventory",
"icon": "bx bx-store",
"available": true,
"link": "/inventory"
}
] ]
}, },
{ {
"text": "Directory", "header": "",
"icon": "bx bx-group", "items": [
"available": true, {
"link": "/directory" "text": "Support",
}, "icon": "bx bx-copy",
{ "available": true,
"text": "Expense", "link": "/help/support"
"icon": "bx bx-receipt", },
"available": true, {
"link": "/expenses" "text": "Documentation",
}, "available": true,
"icon": "bx bx-book-reader",
{ "link": "/help/docs"
"text": "Image Gallary", },
"icon": "bx bx-images", {
"available": true, "text": "Help Desk",
"link": "/gallary" "available": true,
}, "link": "/help/connect",
{ "icon": "bx bx-question-mark"
"text": "Administration", }
"icon": "bx bx-box",
"available": true,
"link": "",
"submenu": [
{
"text": "Users",
"available": true,
"link": "/employees/"
},
{
"text": "Masters",
"available": true,
"link": "/masters"
}
] ]
}, }
{ ]
"text": "Inventory",
"icon": "bx bx-store",
"available": true,
"link": "/inventory"
}
]
},
{
"header": "",
"items": [
{
"text": "Support",
"icon": "bx bx-copy",
"available": true,
"link": "/help/support"
},
{
"text": "Documentation",
"available": true,
"icon": "bx bx-book-reader",
"link": "/help/docs"
},
{
"text": "Help Desk",
"available": true,
"link": "/help/connect",
"icon": "bx bx-question-mark"
}
]
}
]