added properly permissions
This commit is contained in:
parent
4c059afb72
commit
cb7e044b27
@ -10,7 +10,21 @@
|
|||||||
.table_header_border {
|
.table_header_border {
|
||||||
border-bottom:2px solid var(--bs-table-border-color) ;
|
border-bottom:2px solid var(--bs-table-border-color) ;
|
||||||
}
|
}
|
||||||
|
.text-gary-80 {
|
||||||
|
color:var(--bs-gray-500)
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-royalblue{
|
||||||
|
color: #1796e3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-md {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-md-b {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
.text-xxs { font-size: 0.55rem; } /* 8px */
|
.text-xxs { font-size: 0.55rem; } /* 8px */
|
||||||
.text-xs { font-size: 0.75rem; } /* 12px */
|
.text-xs { font-size: 0.75rem; } /* 12px */
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
|
||||||
const PreviewDocument = ({ imageUrl }) => {
|
const PreviewDocument = ({ imageUrl }) => {
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [rotation, setRotation] = useState(0); // Rotation angle
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="d-flex justify-content-center align-items-center" style={{ minHeight: "50vh" }}>
|
<div className="d-flex flex-column justify-content-center align-items-center" style={{ minHeight: "50vh" }}>
|
||||||
{loading && (
|
{loading && (
|
||||||
<div className="text-secondary text-center mb-2">
|
<div className="text-secondary text-center mb-2">
|
||||||
Loading...
|
Loading...
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<img
|
<img
|
||||||
src={imageUrl}
|
src={imageUrl}
|
||||||
alt="Full View"
|
alt="Full View"
|
||||||
@ -18,11 +21,22 @@ const PreviewDocument = ({ imageUrl }) => {
|
|||||||
maxHeight: "100vh",
|
maxHeight: "100vh",
|
||||||
objectFit: "contain",
|
objectFit: "contain",
|
||||||
display: loading ? "none" : "block",
|
display: loading ? "none" : "block",
|
||||||
|
transform: `rotate(${rotation}deg)`,
|
||||||
|
transition: "transform 0.3s ease",
|
||||||
}}
|
}}
|
||||||
onLoad={() => setLoading(false)}
|
onLoad={() => setLoading(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Rotate Button */}
|
||||||
|
<button
|
||||||
|
className="btn btn-secondary mt-3"
|
||||||
|
onClick={() => setRotation((prev) => prev + 90)}
|
||||||
|
>
|
||||||
|
Rotate
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PreviewDocument;
|
export default PreviewDocument;
|
||||||
|
|
||||||
|
@ -138,7 +138,6 @@ const ManageCollection = ({ collectionId, onClose }) => {
|
|||||||
taxAmount: data?.taxAmount,
|
taxAmount: data?.taxAmount,
|
||||||
basicAmount: data?.basicAmount,
|
basicAmount: data?.basicAmount,
|
||||||
description: data?.description,
|
description: data?.description,
|
||||||
attachments: data?.attachments,
|
|
||||||
attachments: data.attachments
|
attachments: data.attachments
|
||||||
? data.attachments.map((doc) => ({
|
? data.attachments.map((doc) => ({
|
||||||
fileName: doc.fileName,
|
fileName: doc.fileName,
|
||||||
|
22
src/components/common/AccessDenied.jsx
Normal file
22
src/components/common/AccessDenied.jsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Breadcrumb from "./Breadcrumb";
|
||||||
|
|
||||||
|
const AccessDenied = ({data}) => {
|
||||||
|
return (
|
||||||
|
<div className="container-fluid">
|
||||||
|
<Breadcrumb
|
||||||
|
data={data}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="card text-center py-1">
|
||||||
|
<i className="fa-solid fa-triangle-exclamation fs-5" />
|
||||||
|
<p>
|
||||||
|
Access Denied: You don't have permission to perform this action !
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AccessDenied;
|
@ -23,6 +23,7 @@ import {
|
|||||||
EDIT_COLLECTION,
|
EDIT_COLLECTION,
|
||||||
VIEW_COLLECTION,
|
VIEW_COLLECTION,
|
||||||
} from "../../utils/constants";
|
} from "../../utils/constants";
|
||||||
|
import AccessDenied from "../../components/common/AccessDenied";
|
||||||
|
|
||||||
const CollectionContext = createContext();
|
const CollectionContext = createContext();
|
||||||
export const useCollectionContext = () => {
|
export const useCollectionContext = () => {
|
||||||
@ -81,155 +82,140 @@ const CollectionPage = () => {
|
|||||||
const handleMarkedPayment = (payload) => {
|
const handleMarkedPayment = (payload) => {
|
||||||
MarkedReceived(payload);
|
MarkedReceived(payload);
|
||||||
};
|
};
|
||||||
|
if (isAdmin === undefined ||
|
||||||
|
canAddPayment === undefined ||
|
||||||
|
canEditCollection === undefined ||
|
||||||
|
canViewCollection === undefined ||
|
||||||
|
canCreate === undefined
|
||||||
|
) {
|
||||||
|
return <div className="text-center py-5">Checking access...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isAdmin && !canAddPayment && !canEditCollection && !canViewCollection && !canCreate) {
|
||||||
|
return <AccessDenied data={[{ label: "Home", link: "/" }, { label: "Collection" }]} />;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<CollectionContext.Provider value={contextMassager}>
|
<CollectionContext.Provider value={contextMassager}>
|
||||||
{isAdmin ||
|
<div className="container-fluid">
|
||||||
canAddPayment ||
|
<Breadcrumb
|
||||||
canEditCollection ||
|
data={[{ label: "Home", link: "/" }, { label: "Collection" }]}
|
||||||
canViewCollection ||
|
/>
|
||||||
canCreate ? (
|
|
||||||
<div className="container-fluid">
|
|
||||||
<Breadcrumb
|
|
||||||
data={[{ label: "Home", link: "/" }, { label: "Collection" }]}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="card my-3 py-2 px-sm-4 px-0">
|
<div className="card my-3 py-2 px-sm-4 px-0">
|
||||||
<div className="row px-3">
|
<div className="row px-3">
|
||||||
<div className="col-12 col-md-3 mb-1">
|
<div className="col-12 col-md-3 mb-1">
|
||||||
<FormProvider {...methods}>
|
<FormProvider {...methods}>
|
||||||
<DateRangePicker1 howManyDay={180} />
|
<DateRangePicker1 howManyDay={180} />
|
||||||
</FormProvider>
|
</FormProvider>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 col-md-3 d-flex align-items-center gap-2 ">
|
<div className="col-12 col-md-3 d-flex align-items-center gap-2 ">
|
||||||
<div className="form-check form-switch text-start align-items-center">
|
<div className="form-check form-switch text-start align-items-center">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
className="form-check-input"
|
className="form-check-input"
|
||||||
role="switch"
|
role="switch"
|
||||||
id="inactiveEmployeesCheckbox"
|
id="inactiveEmployeesCheckbox"
|
||||||
checked={showPending}
|
checked={showPending}
|
||||||
onChange={(e) => setShowPending(e.target.checked)}
|
onChange={(e) => setShowPending(e.target.checked)}
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
className="form-check-label ms-0"
|
className="form-check-label ms-0"
|
||||||
htmlFor="inactiveEmployeesCheckbox"
|
htmlFor="inactiveEmployeesCheckbox"
|
||||||
>
|
>
|
||||||
Show Pending
|
Show Pending
|
||||||
</label>
|
</label>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="col-12 col-md-6 d-flex justify-content-end gap-4">
|
|
||||||
<div className=" w-md-auto">
|
|
||||||
{" "}
|
|
||||||
<input
|
|
||||||
type="search"
|
|
||||||
value={searchText}
|
|
||||||
onChange={(e) => setSearchText(e.target.value)}
|
|
||||||
placeholder="search Collection"
|
|
||||||
className="form-control form-control-sm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{isAdmin ||
|
|
||||||
(isCanCreate && (
|
|
||||||
<button
|
|
||||||
className="btn btn-sm btn-primary"
|
|
||||||
type="button"
|
|
||||||
onClick={() =>
|
|
||||||
setCollection({ isOpen: true, invoiceId: null })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
|
||||||
<span className="d-none d-md-inline-block">
|
|
||||||
Add New Collection
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<CollectionList
|
<div className="col-12 col-md-6 d-flex justify-content-end gap-4">
|
||||||
fromDate={fromDate}
|
<div className=" w-md-auto">
|
||||||
toDate={toDate}
|
{" "}
|
||||||
isPending={showPending}
|
<input
|
||||||
searchString={searchText}
|
type="search"
|
||||||
/>
|
value={searchText}
|
||||||
|
onChange={(e) => setSearchText(e.target.value)}
|
||||||
|
placeholder="search Collection"
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{ (canCreate || isAdmin) && (
|
||||||
|
<button
|
||||||
|
className="btn btn-sm btn-primary"
|
||||||
|
type="button"
|
||||||
|
onClick={() => setCollection({ isOpen: true, invoiceId: null })}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
<span className="d-none d-md-inline-block">Add New Collection</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
{makeCollection.isOpen && (
|
</div>
|
||||||
<GlobalModel
|
|
||||||
isOpen={makeCollection.isOpen}
|
|
||||||
size="lg"
|
|
||||||
closeModal={() =>
|
|
||||||
setCollection({ isOpen: false, invoiceId: null })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<ManageCollection
|
|
||||||
collectionId={makeCollection?.invoiceId ?? null}
|
|
||||||
onClose={() =>
|
|
||||||
setCollection({ isOpen: false, invoiceId: null })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</GlobalModel>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{addPayment.isOpen && (
|
|
||||||
<GlobalModel
|
|
||||||
size="lg"
|
|
||||||
isOpen={addPayment.isOpen}
|
|
||||||
closeModal={() =>
|
|
||||||
setAddPayment({ isOpen: false, invoiceId: null })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<AddPayment
|
|
||||||
onClose={() =>
|
|
||||||
setAddPayment({ isOpen: false, invoiceId: null })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</GlobalModel>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{viewCollection && (
|
|
||||||
<GlobalModel
|
|
||||||
size="lg"
|
|
||||||
isOpen={viewCollection}
|
|
||||||
closeModal={() => setViewCollection(null)}
|
|
||||||
>
|
|
||||||
<ViewCollection onClose={() => setViewCollection(null)} />
|
|
||||||
</GlobalModel>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{ViewDocument.IsOpen && (
|
|
||||||
<GlobalModel
|
|
||||||
isOpen
|
|
||||||
size="md"
|
|
||||||
key={ViewDocument.Image ?? "doc"}
|
|
||||||
closeModal={() => setDocumentView({ IsOpen: false, Image: null })}
|
|
||||||
>
|
|
||||||
<PreviewDocument imageUrl={ViewDocument.Image} />
|
|
||||||
</GlobalModel>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<ConfirmModal
|
|
||||||
type="success"
|
|
||||||
header="Payment Successful Received"
|
|
||||||
message="Payment has been recored successfully."
|
|
||||||
isOpen={processedPayment?.isOpen}
|
|
||||||
loading={isPending}
|
|
||||||
onSubmit={() => handleMarkedPayment(processedPayment?.invoiceId)}
|
|
||||||
onClose={() => setProcessedPayment(null)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="container-fluid">
|
|
||||||
<div className="card text-center py-1">
|
|
||||||
<i className="fa-solid fa-triangle-exclamation fs-5" />
|
|
||||||
<p>
|
|
||||||
Access Denied: You don't have permission to perform this action !
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
<CollectionList
|
||||||
|
fromDate={fromDate}
|
||||||
|
toDate={toDate}
|
||||||
|
isPending={showPending}
|
||||||
|
searchString={searchText}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{makeCollection.isOpen && (
|
||||||
|
<GlobalModel
|
||||||
|
isOpen={makeCollection.isOpen}
|
||||||
|
size="lg"
|
||||||
|
closeModal={() => setCollection({ isOpen: false, invoiceId: null })}
|
||||||
|
>
|
||||||
|
<ManageCollection
|
||||||
|
collectionId={makeCollection?.invoiceId ?? null}
|
||||||
|
onClose={() => setCollection({ isOpen: false, invoiceId: null })}
|
||||||
|
/>
|
||||||
|
</GlobalModel>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{addPayment.isOpen && (
|
||||||
|
<GlobalModel
|
||||||
|
size="lg"
|
||||||
|
isOpen={addPayment.isOpen}
|
||||||
|
closeModal={() => setAddPayment({ isOpen: false, invoiceId: null })}
|
||||||
|
>
|
||||||
|
<AddPayment
|
||||||
|
onClose={() => setAddPayment({ isOpen: false, invoiceId: null })}
|
||||||
|
/>
|
||||||
|
</GlobalModel>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{viewCollection && (
|
||||||
|
<GlobalModel
|
||||||
|
size="lg"
|
||||||
|
isOpen={viewCollection}
|
||||||
|
closeModal={() => setViewCollection(null)}
|
||||||
|
>
|
||||||
|
<ViewCollection onClose={() => setViewCollection(null)} />
|
||||||
|
</GlobalModel>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{ViewDocument.IsOpen && (
|
||||||
|
<GlobalModel
|
||||||
|
isOpen
|
||||||
|
size="md"
|
||||||
|
key={ViewDocument.Image ?? "doc"}
|
||||||
|
closeModal={() => setDocumentView({ IsOpen: false, Image: null })}
|
||||||
|
>
|
||||||
|
<PreviewDocument imageUrl={ViewDocument.Image} />
|
||||||
|
</GlobalModel>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<ConfirmModal
|
||||||
|
type="success"
|
||||||
|
header="Payment Successful Received"
|
||||||
|
message="Payment has been recored successfully."
|
||||||
|
isOpen={processedPayment?.isOpen}
|
||||||
|
loading={isPending}
|
||||||
|
onSubmit={() => handleMarkedPayment(processedPayment?.invoiceId)}
|
||||||
|
onClose={() => setProcessedPayment(null)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</CollectionContext.Provider>
|
</CollectionContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user