Compare commits

...

4 Commits

5 changed files with 90 additions and 60 deletions

View File

@ -18,7 +18,7 @@ import { ExpenseFilterSkeleton } from "./ExpenseSkeleton";
const ExpenseFilterPanel = ({ onApply, handleGroupBy }) => {
const selectedProjectId = useSelector((store) => store.localVariables.projectId);
const { data, isLoading } = useExpenseFilter();
const { data, isLoading,isError,error,isFetching , isFetched} = useExpenseFilter();
const groupByList = useMemo(() => [
{ id: "transactionDate", name: "Transaction Date" },
@ -69,8 +69,8 @@ const ExpenseFilterPanel = ({ onApply, handleGroupBy }) => {
closePanel();
};
if (isLoading) return <ExpenseFilterSkeleton />;
if (isLoading || isFetching) return <ExpenseFilterSkeleton />;
if(isError && isFetched) return <div>Something went wrong Here- {error.message} </div>
return (
<>

View File

@ -4,7 +4,7 @@ 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 } from "../../utils/constants";
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";
@ -164,7 +164,19 @@ const ExpenseList = ({ filters, groupBy = "transactionDate",searchText }) => {
? 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 && (
@ -255,29 +267,28 @@ const ExpenseList = ({ filters, groupBy = "transactionDate",searchText }) => {
})
}
></i>
{(expense.status.name === "Draft" ||
expense.status.name === "Rejected") &&
expense.createdBy.id === SelfId && (
<i
className="bx bx-edit text-secondary cursor-pointer"
onClick={() =>
setManageExpenseModal({
IsOpen: true,
expenseId: expense.id,
})
}
></i>
)}
{expense.status.name === "Draft" &&
expense.createdBy.id === SelfId && (
<i
{canEditExpense(expense) && (
<i
className="bx bx-edit text-secondary cursor-pointer"
onClick={() =>
setManageExpenseModal({
IsOpen: true,
expenseId: expense.id,
})
}
></i>
)}
{canDetetExpense(expense) && (
<i
className="bx bx-trash text-danger cursor-pointer"
onClick={() => {
setIsDeleteModalOpen(true);
setDeletingId(expense.id);
}}
></i>
)}
)}
</div>
</td>
</tr>

View File

@ -12,7 +12,7 @@ import { useExpenseContext } from "../../pages/Expense/ExpensePage";
import { getColorNameFromHex } from "../../utils/appUtils";
import { ExpenseDetailsSkeleton } from "./ExpenseSkeleton";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { PROCESS_EXPENSE, REVIEW_EXPENSE } from "../../utils/constants";
import { EXPENSE_REJECTEDBY, PROCESS_EXPENSE, REVIEW_EXPENSE } from "../../utils/constants";
import { useProfile } from "../../hooks/useProfile";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
@ -49,6 +49,9 @@ const ViewExpense = ({ ExpenseId }) => {
const userPermissions = useSelector(
(state) => state?.globalVariables?.loginUser?.featurePermissions || []
);
const CurrentUser = useSelector(
(state) => state?.globalVariables?.loginUser?.employeeInfo
);
const nextStatusWithPermission = useMemo(() => {
if (!Array.isArray(data?.nextStatus)) return [];
@ -66,6 +69,14 @@ const ViewExpense = ({ ExpenseId }) => {
});
}, [data, userPermissions]);
const IsRejectedExpense = useMemo(()=>{
return EXPENSE_REJECTEDBY.includes(data?.status?.id)
},[data])
const isCreatedBy = useMemo(() => {
return data?.createdBy.id === CurrentUser?.id;
}, [data, CurrentUser]);
const { mutate: MakeAction,isPending } = useActionOnExpense(() => {
setClickedStatusId(null);
reset()});
@ -184,7 +195,7 @@ const ViewExpense = ({ ExpenseId }) => {
getColorNameFromHex(data?.status?.color) || "secondary"
}`}
>
{data?.status?.displayName}
{data?.status?.name}
</span>
</div>
</div>
@ -466,43 +477,49 @@ const ViewExpense = ({ ExpenseId }) => {
</div>
</div>
)}
<div className="col-12 mb-3 text-start">
{nextStatusWithPermission.length > 0 && (
<>
<label className="form-label me-2 mb-0 ">Comment:</label>
<textarea
className="form-control form-control-sm"
{...register("comment")}
rows="2"
/>
{errors.comment && (
<small className="danger-text">
{errors.comment.message}
</small>
)}
</>
)}
<div className="col-12 mb-3 text-start">
{(
(nextStatusWithPermission.length > 0 && !IsRejectedExpense) ||
(IsRejectedExpense && isCreatedBy)
) && (
<>
<label className="form-label me-2 mb-0">Comment:</label>
<textarea
className="form-control form-control-sm"
{...register("comment")}
rows="2"
/>
{errors.comment && (
<small className="danger-text">
{errors.comment.message}
</small>
)}
</>
)}
{(nextStatusWithPermission?.length > 0 && (!IsRejectedExpense || isCreatedBy)) && (
<div className="text-center flex-wrap gap-2 my-2">
{nextStatusWithPermission.map((status, index) => (
<button
key={status.id || index}
type="button"
onClick={() => {
setClickedStatusId(status.id);
setValue("statusId", status.id);
handleSubmit(onSubmit)();
}}
disabled={isPending}
className="btn btn-primary btn-sm cursor-pointer mx-2 border-0"
>
{isPending && clickedStatusId === status.id
? "Please Wait..."
: status.displayName || status.name}
</button>
))}
</div>
)}
</div>
{nextStatusWithPermission?.length > 0 && (
<div className="text-center flex-wrap gap-2 my-2">
{nextStatusWithPermission?.map((status, index) => (
<button
key={status.id || index}
type="button"
onClick={() => {
setClickedStatusId(status.id);
setValue("statusId", status.id);
handleSubmit(onSubmit)();
}}
disabled={isPending}
className="btn btn-primary btn-sm cursor-pointer mx-2 border-0"
>
{(isPending && clickedStatusId === status.id) ? "Please Wait..." : (status.displayName || status.name)}
</button>
))}
</div>
)}
</div>
</>
)}
</form>

View File

@ -114,7 +114,7 @@ const ExpensePage = () => {
<div className="row align-items-center">
<div className="col-sm-6 col-md-4">
<div className="d-flex align-items-center">
<span className="form-label me-2" id="search-label">Search</span>
<input
type="search"
className="form-control form-control-sm w-auto"

View File

@ -56,7 +56,9 @@ export const PROCESS_EXPENSE = "ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"
export const EXPENSE_MANAGE = "ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"
export const EXPENSE_REJECTEDBY = ["d1ee5eec-24b6-4364-8673-a8f859c60729","965eda62-7907-4963-b4a1-657fb0b2724b"]
export const EXPENSE_DRAFT = "297e0d8f-f668-41b5-bfea-e03b354251c"
// -------------------Application Role------------------------------
// 1 - Expense Manage