hide page if have any permission for Expense
This commit is contained in:
parent
aa14203357
commit
e2d45e54a0
@ -33,7 +33,11 @@ import {
|
||||
SearchSchema,
|
||||
} from "../../components/Expenses/ExpenseSchema";
|
||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||
import { CREATE_EXEPENSE } from "../../utils/constants";
|
||||
import {
|
||||
CREATE_EXEPENSE,
|
||||
VIEW_ALL_EXPNESE,
|
||||
VIEW_SELF_EXPENSE,
|
||||
} from "../../utils/constants";
|
||||
|
||||
const SelectDropdown = ({
|
||||
label,
|
||||
@ -100,12 +104,12 @@ export const useExpenseContext = () => {
|
||||
throw new Error("useExpenseContext must be used within an ExpenseProvider");
|
||||
}
|
||||
return context;
|
||||
}
|
||||
};
|
||||
|
||||
const ExpensePage = () => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [filters,setFilter] = useState()
|
||||
const IsCreatedAble = useHasUserPermission(CREATE_EXEPENSE)
|
||||
const [filters, setFilter] = useState();
|
||||
const IsCreatedAble = useHasUserPermission(CREATE_EXEPENSE);
|
||||
const dropdownRef = useRef(null);
|
||||
const shouldCloseOnOutsideClick = useRef(false);
|
||||
const selectedProjectId = useSelector(
|
||||
@ -123,7 +127,8 @@ const ExpensePage = () => {
|
||||
IsOpen: false,
|
||||
Image: null,
|
||||
});
|
||||
|
||||
const IsViewAll = useHasUserPermission(VIEW_ALL_EXPNESE);
|
||||
const IsViewSelf = useHasUserPermission(VIEW_SELF_EXPENSE);
|
||||
const contextValue = {
|
||||
setViewExpense,
|
||||
setManageExpenseModal,
|
||||
@ -155,26 +160,25 @@ const ExpensePage = () => {
|
||||
);
|
||||
|
||||
const onSubmit = (data) => {
|
||||
setFilter(data)
|
||||
setFilter(data);
|
||||
};
|
||||
const isValidDate = (date) => {
|
||||
return date instanceof Date && !isNaN(date);
|
||||
};
|
||||
const isValidDate = (date) => {
|
||||
return date instanceof Date && !isNaN(date);
|
||||
};
|
||||
|
||||
const setDateRange = ({ startDate, endDate }) => {
|
||||
const parsedStart = new Date(startDate);
|
||||
const parsedEnd = new Date(endDate);
|
||||
|
||||
setValue(
|
||||
"startDate",
|
||||
isValidDate(parsedStart) ? parsedStart.toISOString().split("T")[0] : null
|
||||
);
|
||||
setValue(
|
||||
"endDate",
|
||||
isValidDate(parsedEnd) ? parsedEnd.toISOString().split("T")[0] : null
|
||||
);
|
||||
};
|
||||
const setDateRange = ({ startDate, endDate }) => {
|
||||
const parsedStart = new Date(startDate);
|
||||
const parsedEnd = new Date(endDate);
|
||||
|
||||
setValue(
|
||||
"startDate",
|
||||
isValidDate(parsedStart) ? parsedStart.toISOString().split("T")[0] : null
|
||||
);
|
||||
setValue(
|
||||
"endDate",
|
||||
isValidDate(parsedEnd) ? parsedEnd.toISOString().split("T")[0] : null
|
||||
);
|
||||
};
|
||||
|
||||
const toggleDropdown = () => {
|
||||
setIsOpen((prev) => {
|
||||
@ -199,19 +203,17 @@ const setDateRange = ({ startDate, endDate }) => {
|
||||
document.removeEventListener("mousedown", handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
const clearFilter =()=>{
|
||||
setFilter(
|
||||
{
|
||||
projectIds: [],
|
||||
statusIds: [],
|
||||
createdByIds: [],
|
||||
paidById: [],
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
})
|
||||
reset()
|
||||
|
||||
}
|
||||
const clearFilter = () => {
|
||||
setFilter({
|
||||
projectIds: [],
|
||||
statusIds: [],
|
||||
createdByIds: [],
|
||||
paidById: [],
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
});
|
||||
reset();
|
||||
};
|
||||
|
||||
return (
|
||||
<ExpenseContext.Provider value={contextValue}>
|
||||
@ -222,167 +224,182 @@ const setDateRange = ({ startDate, endDate }) => {
|
||||
{ label: "Expense", link: null },
|
||||
]}
|
||||
/>
|
||||
<div className="card my-1 text-start px-0">
|
||||
<div className="card-body py-1 px-1">
|
||||
<div className="row">
|
||||
<div className="col-5 col-sm-4 d-flex aligin-items-center">
|
||||
<div
|
||||
className="dropdown d-inline-block mt-2 align-items-center"
|
||||
ref={dropdownRef}
|
||||
>
|
||||
<i
|
||||
className="bx bx-slider-alt ms-2"
|
||||
role="button"
|
||||
aria-expanded={isOpen}
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() => setIsOpen((v) => !v)}
|
||||
></i>
|
||||
{isOpen && (
|
||||
{IsViewAll || IsViewSelf ? (
|
||||
<>
|
||||
<div className="card my-1 text-start px-0">
|
||||
<div className="card-body py-1 px-1">
|
||||
<div className="row">
|
||||
<div className="col-5 col-sm-4 d-flex aligin-items-center">
|
||||
<div
|
||||
className="dropdown-menu p-3 overflow-hidden show d-flex align-items-center"
|
||||
style={{ minWidth: "500px" }}
|
||||
className="dropdown d-inline-block mt-2 align-items-center"
|
||||
ref={dropdownRef}
|
||||
>
|
||||
<FormProvider {...methods}>
|
||||
<form
|
||||
className="p-2 p-sm-0"
|
||||
onSubmit={handleSubmit((data) => {
|
||||
onSubmit(data);
|
||||
setIsOpen(false);
|
||||
})}
|
||||
<i
|
||||
className="bx bx-slider-alt ms-2"
|
||||
role="button"
|
||||
aria-expanded={isOpen}
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() => setIsOpen((v) => !v)}
|
||||
></i>
|
||||
{isOpen && (
|
||||
<div
|
||||
className="dropdown-menu p-3 overflow-hidden show d-flex align-items-center"
|
||||
style={{ minWidth: "500px" }}
|
||||
>
|
||||
<div className="w-100">
|
||||
<DateRangePicker
|
||||
onRangeChange={setDateRange}
|
||||
endDateMode="today"
|
||||
DateDifference="6"
|
||||
dateFormat="DD-MM-YYYY"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="row g-2">
|
||||
<div className="col-12 ">
|
||||
<label className="form-label d-block text-secondary">
|
||||
Select Status
|
||||
</label>
|
||||
<div className="d-flex flex-wrap">
|
||||
{ExpenseStatus.map((status) => (
|
||||
<Controller
|
||||
key={status.id}
|
||||
control={control}
|
||||
name="statusIds"
|
||||
render={({
|
||||
field: { value = [], onChange },
|
||||
}) => (
|
||||
<div className="d-flex align-items-center me-4 mb-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="form-check-input form-check-input-sm"
|
||||
value={status.id}
|
||||
checked={value.includes(status.id)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
onChange([...value, status.id]);
|
||||
} else {
|
||||
onChange(
|
||||
value.filter(
|
||||
(v) => v !== status.id
|
||||
)
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<label className="ms-2 mb-0">
|
||||
{status.displayName}
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row g-2">
|
||||
<SelectMultiple
|
||||
name="projectIds"
|
||||
label="Select Projects"
|
||||
options={projectNames}
|
||||
labelKey="name"
|
||||
valueKey="id"
|
||||
IsLoading={projectLoading}
|
||||
/>
|
||||
<SelectMultiple
|
||||
name="createdByIds"
|
||||
label="Select creator"
|
||||
options={employees}
|
||||
labelKey={(item) =>
|
||||
`${item.firstName} ${item.lastName}`
|
||||
}
|
||||
valueKey="id"
|
||||
IsLoading={empLoading}
|
||||
/>
|
||||
<SelectMultiple
|
||||
name="paidById"
|
||||
label="Select Paid by"
|
||||
options={employees}
|
||||
labelKey={(item) =>
|
||||
`${item.firstName} ${item.lastName}`
|
||||
}
|
||||
valueKey="id"
|
||||
IsLoading={empLoading}
|
||||
/>
|
||||
</div>
|
||||
<div className="d-flex justify-content-end py-1 gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary btn-xs"
|
||||
onClick={() => {
|
||||
clearFilter()
|
||||
<FormProvider {...methods}>
|
||||
<form
|
||||
className="p-2 p-sm-0"
|
||||
onSubmit={handleSubmit((data) => {
|
||||
onSubmit(data);
|
||||
setIsOpen(false);
|
||||
}}
|
||||
})}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-xs"
|
||||
>
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</FormProvider>
|
||||
<div className="w-100">
|
||||
<DateRangePicker
|
||||
onRangeChange={setDateRange}
|
||||
endDateMode="today"
|
||||
DateDifference="6"
|
||||
dateFormat="DD-MM-YYYY"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="row g-2">
|
||||
<div className="col-12 ">
|
||||
<label className="form-label d-block text-secondary">
|
||||
Select Status
|
||||
</label>
|
||||
<div className="d-flex flex-wrap">
|
||||
{ExpenseStatus.map((status) => (
|
||||
<Controller
|
||||
key={status.id}
|
||||
control={control}
|
||||
name="statusIds"
|
||||
render={({
|
||||
field: { value = [], onChange },
|
||||
}) => (
|
||||
<div className="d-flex align-items-center me-4 mb-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="form-check-input form-check-input-sm"
|
||||
value={status.id}
|
||||
checked={value.includes(
|
||||
status.id
|
||||
)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
onChange([
|
||||
...value,
|
||||
status.id,
|
||||
]);
|
||||
} else {
|
||||
onChange(
|
||||
value.filter(
|
||||
(v) => v !== status.id
|
||||
)
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<label className="ms-2 mb-0">
|
||||
{status.displayName}
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row g-2">
|
||||
<SelectMultiple
|
||||
name="projectIds"
|
||||
label="Select Projects"
|
||||
options={projectNames}
|
||||
labelKey="name"
|
||||
valueKey="id"
|
||||
IsLoading={projectLoading}
|
||||
/>
|
||||
<SelectMultiple
|
||||
name="createdByIds"
|
||||
label="Select creator"
|
||||
options={employees}
|
||||
labelKey={(item) =>
|
||||
`${item.firstName} ${item.lastName}`
|
||||
}
|
||||
valueKey="id"
|
||||
IsLoading={empLoading}
|
||||
/>
|
||||
<SelectMultiple
|
||||
name="paidById"
|
||||
label="Select Paid by"
|
||||
options={employees}
|
||||
labelKey={(item) =>
|
||||
`${item.firstName} ${item.lastName}`
|
||||
}
|
||||
valueKey="id"
|
||||
IsLoading={empLoading}
|
||||
/>
|
||||
</div>
|
||||
<div className="d-flex justify-content-end py-1 gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary btn-xs"
|
||||
onClick={() => {
|
||||
clearFilter();
|
||||
setIsOpen(false);
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-xs"
|
||||
>
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</FormProvider>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-7 col-sm-8 text-end gap-2">
|
||||
{IsCreatedAble && (
|
||||
<button
|
||||
type="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-offset="0,8"
|
||||
data-bs-placement="top"
|
||||
data-bs-custom-class="tooltip"
|
||||
title="Add New Expense"
|
||||
className={`p-1 me-2 bg-primary rounded-circle `}
|
||||
onClick={() =>
|
||||
setManageExpenseModal({
|
||||
IsOpen: true,
|
||||
expenseId: null,
|
||||
})
|
||||
}
|
||||
>
|
||||
<i className="bx bx-plus fs-4 text-white"></i>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-7 col-sm-8 text-end gap-2">
|
||||
{IsCreatedAble && (
|
||||
<button
|
||||
type="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-offset="0,8"
|
||||
data-bs-placement="top"
|
||||
data-bs-custom-class="tooltip"
|
||||
title="Add New Expense"
|
||||
className={`p-1 me-2 bg-primary rounded-circle `}
|
||||
onClick={() =>
|
||||
setManageExpenseModal({
|
||||
IsOpen: true,
|
||||
expenseId: null,
|
||||
})
|
||||
}
|
||||
>
|
||||
<i className="bx bx-plus fs-4 text-white"></i>
|
||||
</button>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<ExpenseList filters={filters} />
|
||||
</>
|
||||
) : (
|
||||
<div className="card text-center py-1">
|
||||
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
|
||||
<p>
|
||||
Access Denied: You don't have permission to perform this action. !
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<ExpenseList filters={filters} />
|
||||
{ManageExpenseModal.IsOpen && (
|
||||
<GlobalModel
|
||||
isOpen={ManageExpenseModal.IsOpen}
|
||||
|
Loading…
x
Reference in New Issue
Block a user