157 lines
6.0 KiB
JavaScript
157 lines
6.0 KiB
JavaScript
import React, { useEffect, useState } from "react";
|
|
import { useExpense } from "../../hooks/useExpense";
|
|
import { useExpenseStatus } from "../../hooks/useDashboard_Data";
|
|
import { useSelectedProject } from "../../slices/apiDataManager";
|
|
import { useProjectName } from "../../hooks/useProjects";
|
|
import { countDigit, formatCurrency } from "../../utils/appUtils";
|
|
import { EXPENSE_MANAGE, EXPENSE_STATUS } from "../../utils/constants";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
|
|
|
const ExpenseStatus = () => {
|
|
const [projectName, setProjectName] = useState("All Project");
|
|
const selectedProject = useSelectedProject();
|
|
const { projectNames, loading } = useProjectName();
|
|
const { data, isPending, error } = useExpenseStatus(selectedProject);
|
|
const navigate = useNavigate();
|
|
const isManageExpense = useHasUserPermission(EXPENSE_MANAGE)
|
|
|
|
useEffect(() => {
|
|
if (selectedProject && projectNames?.length) {
|
|
const project = projectNames.find((p) => p.id === selectedProject);
|
|
setProjectName(project?.name || "All Project");
|
|
} else {
|
|
setProjectName("All Project");
|
|
}
|
|
}, [projectNames, selectedProject]);
|
|
|
|
const handleNavigate = (status) => {
|
|
if (selectedProject) {
|
|
navigate(`/expenses/${status}/${selectedProject}`);
|
|
} else {
|
|
navigate(`/expenses/${status}`);
|
|
}
|
|
};
|
|
return (
|
|
<>
|
|
<div className="card-header d-flex justify-content-between text-start ">
|
|
<div className="m-0">
|
|
<h5 className="card-title mb-1">Expense - By Status</h5>
|
|
<p className="card-subtitle m-0 ">{projectName}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="card-body ">
|
|
|
|
<div className="report-list text-start">
|
|
{[
|
|
{
|
|
title: "Pending Payment",
|
|
count: data?.processPending?.count || 0,
|
|
amount: data?.processPending?.totalAmount || 0,
|
|
icon: "bx bx-rupee",
|
|
iconColor: "text-primary",
|
|
status: EXPENSE_STATUS.payment_pending,
|
|
},
|
|
{
|
|
title: "Pending Approve",
|
|
count: data?.approvePending?.count || 0,
|
|
amount: data?.approvePending?.totalAmount || 0,
|
|
icon: "fa-solid fa-check",
|
|
iconColor: "text-warning",
|
|
status: EXPENSE_STATUS.approve_pending,
|
|
},
|
|
{
|
|
title: "Pending Review",
|
|
count: data?.reviewPending?.count || 0,
|
|
amount: data?.reviewPending?.totalAmount || 0,
|
|
icon: "bx bx-search-alt-2",
|
|
iconColor: "text-secondary",
|
|
status: EXPENSE_STATUS.review_pending,
|
|
},
|
|
{
|
|
title: "Draft",
|
|
count: data?.draft?.count || 0,
|
|
amount: data?.draft?.totalAmount || 0,
|
|
icon: "bx bx-file-blank",
|
|
iconColor: "text-info",
|
|
status: EXPENSE_STATUS.daft,
|
|
},
|
|
].map((item, idx) => (
|
|
<div
|
|
key={idx}
|
|
className="report-list-item rounded-2 mb-4 bg-lighter px-2 py-1 cursor-pointer"
|
|
onClick={() => handleNavigate(item?.status)}
|
|
>
|
|
<div className="d-flex align-items-center">
|
|
<div className="report-list-icon shadow-xs me-2">
|
|
<span className="d-inline-flex align-items-center justify-content-center rounded-circle border p-2">
|
|
<i className={`${item?.icon} ${item?.iconColor} bx-lg`}></i>
|
|
</span>
|
|
</div>
|
|
<div className="d-flex justify-content-between align-items-center w-100 flex-wrap gap-2">
|
|
<div className="d-flex flex-column gap-2">
|
|
<span className="fw-bold">{item?.title}</span>
|
|
{item?.amount ? (
|
|
<small className="mb-0 text-primary">
|
|
{formatCurrency(item?.amount)}
|
|
</small>
|
|
) : (
|
|
<small className="mb-0 text-primary">{formatCurrency(0)}</small>
|
|
)}
|
|
</div>
|
|
<div>
|
|
<small
|
|
className={`text-royalblue ${countDigit(item?.count || 0) >= 3 ? "text-xl" : "text-2xl"
|
|
} text-gray-500`}
|
|
>
|
|
{item?.count || 0}
|
|
</small>
|
|
<small className="text-muted fs-semibold text-royalblue text-md">
|
|
<i className="bx bx-chevron-right"></i>
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<div className=" py-0 text-start mb-2">
|
|
{isManageExpense && (
|
|
<div
|
|
className="d-flex justify-content-between align-items-center cursor-pointer"
|
|
onClick={() => handleNavigate(EXPENSE_STATUS.process_pending)}
|
|
>
|
|
<div className="d-block">
|
|
<span
|
|
className={`fs-semibold d-block ${countDigit(data?.totalAmount || 0) > 3 ? "text-base" : "text-lg"
|
|
}`}
|
|
>
|
|
Project Spendings:
|
|
</span>{" "}
|
|
<small className="d-block text-xxs text-gary-80">
|
|
(All Processed Payments)
|
|
</small>
|
|
</div>
|
|
<div className="d-flex align-items-center gap-2">
|
|
<span
|
|
className={`text-end text-royalblue ${countDigit(data?.totalAmount || 0) > 3 ? "text-" : "text-3xl"
|
|
} text-md`}
|
|
>
|
|
{formatCurrency(data?.totalAmount || 0)}
|
|
</span>
|
|
<small className="text-muted fs-semibold text-royalblue text-md">
|
|
<i className="bx bx-chevron-right"></i>
|
|
</small>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default ExpenseStatus;
|