enable activating or deactivating existing documents
This commit is contained in:
parent
e8459d3671
commit
fd14328562
@ -21,12 +21,13 @@ export const DocumentContext = createContext();
|
||||
export const useDocumentContext = () => {
|
||||
const context = useContext(DocumentContext);
|
||||
if (!context) {
|
||||
throw new Error("useDocumentContext must be used within an DocumentProvider");
|
||||
throw new Error(
|
||||
"useDocumentContext must be used within an DocumentProvider"
|
||||
);
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
|
||||
export const getDocuementsStatus = (status) => {
|
||||
switch (status) {
|
||||
case true:
|
||||
@ -46,22 +47,22 @@ export const getDocuementsStatus = (status) => {
|
||||
};
|
||||
const Documents = ({ Document_Entity, Entity }) => {
|
||||
const [searchText, setSearchText] = useState("");
|
||||
const [isActive, setIsActive] = useState(true);
|
||||
const [filters, setFilter] = useState();
|
||||
const [isRefetching, setIsRefetching] = useState(false);
|
||||
const [refetchFn, setRefetchFn] = useState(null);
|
||||
const [DocumentEntity,setDocumentEntity] = useState(Document_Entity)
|
||||
const [DocumentEntity, setDocumentEntity] = useState(Document_Entity);
|
||||
const { employeeId } = useParams();
|
||||
const [OpenDocument,setOpenDocument] = useState(false)
|
||||
const [OpenDocument, setOpenDocument] = useState(false);
|
||||
const [ManageDoc, setManageDoc] = useState({
|
||||
document: null,
|
||||
isOpen: false,
|
||||
});
|
||||
const [viewDoc, setViewDoc] = useState({
|
||||
const [viewDoc, setViewDoc] = useState({
|
||||
document: null,
|
||||
isOpen: false,
|
||||
});
|
||||
|
||||
|
||||
const { setOffcanvasContent, setShowTrigger } = useFab();
|
||||
|
||||
const methods = useForm({
|
||||
@ -95,34 +96,33 @@ const Documents = ({ Document_Entity, Entity }) => {
|
||||
viewDoc,
|
||||
setViewDoc,
|
||||
setOpenDocument,
|
||||
OpenDocument
|
||||
}
|
||||
OpenDocument,
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
if(Document_Entity){
|
||||
setDocumentEntity(Document_Entity)
|
||||
useEffect(() => {
|
||||
if (Document_Entity) {
|
||||
setDocumentEntity(Document_Entity);
|
||||
}
|
||||
},[Document_Entity])
|
||||
}, [Document_Entity]);
|
||||
return (
|
||||
<DocumentContext.Provider value={contextValues}>
|
||||
<div className="mt-5">
|
||||
<div className="card d-flex p-2">
|
||||
<div className="row align-items-center">
|
||||
{/* Search */}
|
||||
<div className="col-6 col-md-6 col-lg-3 mb-md-0">
|
||||
<input
|
||||
type="search"
|
||||
value={searchText}
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Search Document"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mt-5">
|
||||
<div className="card d-flex p-2">
|
||||
<div className="row align-items-center">
|
||||
{/* Search */}
|
||||
<div className="col-6 col-md-6 col-lg-3 mb-md-0">
|
||||
<input
|
||||
type="search"
|
||||
value={searchText}
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Search Document"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Actions */}
|
||||
<div className="col-6 col-md-6 col-lg-9 text-end">
|
||||
{/* <span
|
||||
{/* Actions */}
|
||||
<div className="col-6 col-md-6 col-lg-9 text-end">
|
||||
{/* <span
|
||||
className="text-tiny text-muted p-1 border-0 bg-none lead mx-3 cursor-pointer"
|
||||
disabled={isRefetching}
|
||||
onClick={() => {
|
||||
@ -138,71 +138,96 @@ const Documents = ({ Document_Entity, Entity }) => {
|
||||
}`}
|
||||
></i>
|
||||
</span> */}
|
||||
<label className="switch switch-sm">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="switch-input"
|
||||
checked={isActive}
|
||||
onChange={(e) => setIsActive(e.target.checked)}
|
||||
/>
|
||||
<span className="switch-toggle-slider">
|
||||
<span className="switch-on"></span>
|
||||
<span className="switch-off"></span>
|
||||
</span>
|
||||
<span className="switch-label">
|
||||
{isActive ? "Active" : "In-Active"}
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
title="Add New Document"
|
||||
className="p-1 bg-primary rounded-circle cursor-pointer"
|
||||
onClick={() => setManageDoc({
|
||||
document: null,
|
||||
isOpen: true,
|
||||
})}
|
||||
>
|
||||
<i className="bx bx-plus fs-4 text-white"></i>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
title="Add New Document"
|
||||
className="p-1 bg-primary rounded-circle cursor-pointer"
|
||||
onClick={() =>
|
||||
setManageDoc({
|
||||
document: null,
|
||||
isOpen: true,
|
||||
})
|
||||
}
|
||||
>
|
||||
<i className="bx bx-plus fs-4 text-white"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<DocumentsList
|
||||
Document_Entity={DocumentEntity}
|
||||
Entity={Entity}
|
||||
filters={filters}
|
||||
searchText={searchText}
|
||||
setIsRefetching={setIsRefetching}
|
||||
setRefetchFn={setRefetchFn}
|
||||
isActive={isActive}
|
||||
/>
|
||||
</div>
|
||||
<DocumentsList
|
||||
Document_Entity={DocumentEntity}
|
||||
Entity={Entity}
|
||||
filters={filters}
|
||||
searchText={searchText}
|
||||
setIsRefetching={setIsRefetching}
|
||||
setRefetchFn={setRefetchFn}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{ManageDoc.isOpen && (
|
||||
<GlobalModel
|
||||
isOpen={ManageDoc.isOpen}
|
||||
closeModal={() =>
|
||||
setManageDoc({
|
||||
document: null,
|
||||
isOpen: false,
|
||||
})
|
||||
}
|
||||
>
|
||||
<ManageDocument
|
||||
{ManageDoc.isOpen && (
|
||||
<GlobalModel
|
||||
isOpen={ManageDoc.isOpen}
|
||||
closeModal={() =>
|
||||
setManageDoc({
|
||||
document: null,
|
||||
isOpen: false,
|
||||
})
|
||||
}
|
||||
Document_Entity={DocumentEntity}
|
||||
Entity={Entity}
|
||||
/>
|
||||
</GlobalModel>
|
||||
)}
|
||||
>
|
||||
<ManageDocument
|
||||
closeModal={() =>
|
||||
setManageDoc({
|
||||
document: null,
|
||||
isOpen: false,
|
||||
})
|
||||
}
|
||||
Document_Entity={DocumentEntity}
|
||||
Entity={Entity}
|
||||
/>
|
||||
</GlobalModel>
|
||||
)}
|
||||
|
||||
{viewDoc.isOpen && (
|
||||
<GlobalModel size="lg" isOpen={viewDoc.isOpen} closeModal={()=>setViewDoc({
|
||||
document:null,
|
||||
isOpen:false
|
||||
})}>
|
||||
<ViewDocument />
|
||||
</GlobalModel>
|
||||
)}
|
||||
{viewDoc.isOpen && (
|
||||
<GlobalModel
|
||||
size="lg"
|
||||
isOpen={viewDoc.isOpen}
|
||||
closeModal={() =>
|
||||
setViewDoc({
|
||||
document: null,
|
||||
isOpen: false,
|
||||
})
|
||||
}
|
||||
>
|
||||
<ViewDocument />
|
||||
</GlobalModel>
|
||||
)}
|
||||
|
||||
{OpenDocument && (
|
||||
<GlobalModel isOpen={OpenDocument} closeModal={()=>setOpenDocument(false)}>
|
||||
<DocumentViewerModal/>
|
||||
</GlobalModel>
|
||||
)}
|
||||
|
||||
</div>
|
||||
{OpenDocument && (
|
||||
<GlobalModel
|
||||
isOpen={OpenDocument}
|
||||
closeModal={() => setOpenDocument(false)}
|
||||
>
|
||||
<DocumentViewerModal />
|
||||
</GlobalModel>
|
||||
)}
|
||||
</div>
|
||||
</DocumentContext.Provider>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -6,12 +6,12 @@ import {
|
||||
import { ITEMS_PER_PAGE } from "../../utils/constants";
|
||||
import Avatar from "../common/Avatar";
|
||||
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
||||
import Loader from "../common/Loader";
|
||||
import { useDebounce } from "../../utils/appUtils";
|
||||
import { DocumentTableSkeleton } from "./DocumentSkeleton";
|
||||
import { getDocuementsStatus, useDocumentContext } from "./Documents";
|
||||
import Pagination from "../common/Pagination";
|
||||
import ConfirmModal from "../common/ConfirmModal";
|
||||
import { isPending } from "@reduxjs/toolkit";
|
||||
|
||||
const DocumentsList = ({
|
||||
Document_Entity,
|
||||
@ -20,11 +20,14 @@ const DocumentsList = ({
|
||||
searchText,
|
||||
setIsRefetching,
|
||||
setRefetchFn,
|
||||
isActive,
|
||||
}) => {
|
||||
const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||
const [deletingId, setDeletingId] = useState(null);
|
||||
const [restoringIds, setRestoringIds] = useState([]);
|
||||
const debouncedSearch = useDebounce(searchText, 500);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
|
||||
const { data, isError, isLoading, error, refetch, isFetching } =
|
||||
useDocumentListByEntityId(
|
||||
Document_Entity,
|
||||
@ -32,21 +35,21 @@ const DocumentsList = ({
|
||||
ITEMS_PER_PAGE,
|
||||
currentPage,
|
||||
filters,
|
||||
debouncedSearch
|
||||
debouncedSearch,
|
||||
isActive
|
||||
);
|
||||
|
||||
// Pass the refetch function to parent when component mounts
|
||||
useEffect(() => {
|
||||
setRefetchFn(() => refetch);
|
||||
}, [setRefetchFn, refetch]);
|
||||
|
||||
// Sync fetching status with parent
|
||||
useEffect(() => {
|
||||
setIsRefetching(isFetching);
|
||||
}, [isFetching, setIsRefetching]);
|
||||
|
||||
const { setManageDoc, setViewDoc } = useDocumentContext();
|
||||
const { mutate: ActiveInActive, isPending } = useActiveInActiveDocument();
|
||||
|
||||
const paginate = (page) => {
|
||||
if (page >= 1 && page <= (data?.totalPages ?? 1)) {
|
||||
setCurrentPage(page);
|
||||
@ -66,9 +69,8 @@ const DocumentsList = ({
|
||||
if (isFilterEmpty) return <div>No documents match your filter.</div>;
|
||||
|
||||
const handleDelete = () => {
|
||||
debugger;
|
||||
ActiveInActive(
|
||||
{ documentId: deletingId, isActive: false },
|
||||
{ documentId: deletingId, isActive: !isActive },
|
||||
{
|
||||
onSettled: () => {
|
||||
setDeletingId(null);
|
||||
@ -77,6 +79,21 @@ const DocumentsList = ({
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const handleRestore = (docId) => {
|
||||
setRestoringIds((prev) => [...prev, docId]);
|
||||
|
||||
ActiveInActive(
|
||||
{ documentId: docId, isActive: true },
|
||||
{
|
||||
onSettled: () => {
|
||||
setRestoringIds((prev) => prev.filter((id) => id !== docId));
|
||||
refetch();
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const DocumentColumns = [
|
||||
{
|
||||
key: "name",
|
||||
@ -94,10 +111,6 @@ const DocumentsList = ({
|
||||
key: "uploadedBy",
|
||||
label: "Uploaded By",
|
||||
align: "text-start",
|
||||
getValue: (e) =>
|
||||
`${e.uploadedBy?.firstName ?? ""} ${
|
||||
e.uploadedBy?.lastName ?? ""
|
||||
}`.trim() || "N/A",
|
||||
customRender: (e) => (
|
||||
<div className="d-flex align-items-center">
|
||||
<Avatar
|
||||
@ -106,27 +119,31 @@ const DocumentsList = ({
|
||||
firstName={e.uploadedBy?.firstName}
|
||||
lastName={e.uploadedBy?.lastName}
|
||||
/>
|
||||
<span className="text-truncate ">
|
||||
<span className="text-truncate ms-1">
|
||||
{`${e.uploadedBy?.firstName ?? ""} ${
|
||||
e.uploadedBy?.lastName ?? ""
|
||||
}`.trim() || "N/A"}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
getValue: (e) =>
|
||||
`${e.uploadedBy?.firstName ?? ""} ${
|
||||
e.uploadedBy?.lastName ?? ""
|
||||
}`.trim() || "N/A",
|
||||
},
|
||||
{
|
||||
key: "uploadedAt",
|
||||
label: "Uploaded on",
|
||||
getValue: (e) => formatUTCToLocalTime(e?.uploadedAt),
|
||||
isAlwaysVisible: true,
|
||||
getValue: (e) => formatUTCToLocalTime(e.uploadedAt),
|
||||
align: "text-center",
|
||||
isAlwaysVisible: true,
|
||||
},
|
||||
{
|
||||
key: "Status",
|
||||
label: "status",
|
||||
label: "Status",
|
||||
getValue: (e) => getDocuementsStatus(e.isVerified),
|
||||
isAlwaysVisible: true,
|
||||
align: "text-center",
|
||||
isAlwaysVisible: true,
|
||||
},
|
||||
];
|
||||
|
||||
@ -134,13 +151,10 @@ const DocumentsList = ({
|
||||
<>
|
||||
{IsDeleteModalOpen && (
|
||||
<div
|
||||
className={`modal fade show`}
|
||||
className="modal fade show"
|
||||
tabIndex="-1"
|
||||
role="dialog"
|
||||
style={{
|
||||
display: "block",
|
||||
backgroundColor: "rgba(0,0,0,0.5)",
|
||||
}}
|
||||
style={{ display: "block", backgroundColor: "rgba(0,0,0,0.5)" }}
|
||||
aria-hidden="false"
|
||||
>
|
||||
<ConfirmModal
|
||||
@ -149,7 +163,7 @@ const DocumentsList = ({
|
||||
message="Are you sure you want delete?"
|
||||
onSubmit={handleDelete}
|
||||
onClose={() => setIsDeleteModalOpen(false)}
|
||||
loading={isPending}
|
||||
loading={!!isPending}
|
||||
paramData={deletingId}
|
||||
/>
|
||||
</div>
|
||||
@ -170,48 +184,66 @@ const DocumentsList = ({
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="text-start">
|
||||
{data?.data?.map((doc) => (
|
||||
<tr key={doc.id}>
|
||||
{DocumentColumns.map((col) => (
|
||||
<td key={col.key} className={`sorting ${col.align}`}>
|
||||
{col.customRender
|
||||
? col.customRender(doc)
|
||||
: col.getValue(doc)}
|
||||
{data?.data?.map((doc) => {
|
||||
const isRestoring = restoringIds.includes(doc.id);
|
||||
|
||||
return (
|
||||
<tr key={doc.id}>
|
||||
{DocumentColumns.map((col) => (
|
||||
<td key={col.key} className={`sorting ${col.align}`}>
|
||||
{col.customRender
|
||||
? col.customRender(doc)
|
||||
: col.getValue(doc)}
|
||||
</td>
|
||||
))}
|
||||
<td className="text-center">
|
||||
{doc.isActive ? (
|
||||
<div className="d-flex justify-content-center gap-2">
|
||||
<i
|
||||
className="bx bx-show text-primary cursor-pointer"
|
||||
onClick={() =>
|
||||
setViewDoc({ document: doc.id, isOpen: true })
|
||||
}
|
||||
></i>
|
||||
|
||||
<i
|
||||
className="bx bx-edit text-secondary cursor-pointer"
|
||||
onClick={() =>
|
||||
setManageDoc({ document: doc.id, isOpen: true })
|
||||
}
|
||||
></i>
|
||||
|
||||
<i
|
||||
className="bx bx-trash text-danger cursor-pointer"
|
||||
onClick={() => {
|
||||
setIsDeleteModalOpen(true);
|
||||
setDeletingId(doc.id);
|
||||
}}
|
||||
></i>
|
||||
</div>
|
||||
) : isRestoring ? (
|
||||
<div
|
||||
className="spinner-border spinner-border-sm text-primary"
|
||||
role="status"
|
||||
>
|
||||
<span className="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
) : (
|
||||
<i
|
||||
className="bx bx-recycle me-1 text-primary cursor-pointer"
|
||||
onClick={() => handleRestore(doc.id)}
|
||||
></i>
|
||||
)}
|
||||
</td>
|
||||
))}
|
||||
<td className="text-center">
|
||||
<div className="d-flex justify-content-center gap-2">
|
||||
<i
|
||||
className="bx bx-show text-primary cursor-pointer"
|
||||
onClick={() =>
|
||||
setViewDoc({ document: doc?.id, isOpen: true })
|
||||
}
|
||||
></i>
|
||||
|
||||
<i
|
||||
className="bx bx-edit text-secondary cursor-pointer"
|
||||
onClick={() =>
|
||||
setManageDoc({ document: doc?.id, isOpen: true })
|
||||
}
|
||||
></i>
|
||||
|
||||
<i
|
||||
className="bx bx-trash text-danger cursor-pointer"
|
||||
onClick={() => {
|
||||
setIsDeleteModalOpen(true);
|
||||
setDeletingId(doc?.id);
|
||||
}}
|
||||
></i>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
{data?.data?.length > 0 && (
|
||||
<Pagination
|
||||
currentPage={currentPage}
|
||||
totalPages={data?.totalPages}
|
||||
totalPages={data.totalPages}
|
||||
onPageChange={paginate}
|
||||
/>
|
||||
)}
|
||||
|
@ -31,7 +31,8 @@ export const useDocumentListByEntityId = (
|
||||
pageSize,
|
||||
pageNumber,
|
||||
filter,
|
||||
searchString = ""
|
||||
searchString = "",
|
||||
isActive
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: [
|
||||
@ -42,6 +43,7 @@ export const useDocumentListByEntityId = (
|
||||
pageNumber,
|
||||
filter,
|
||||
searchString,
|
||||
isActive
|
||||
],
|
||||
queryFn: async () => {
|
||||
const cleanedFilter = cleanFilter(filter);
|
||||
@ -51,7 +53,8 @@ export const useDocumentListByEntityId = (
|
||||
pageSize,
|
||||
pageNumber,
|
||||
cleanedFilter,
|
||||
searchString
|
||||
searchString,
|
||||
isActive
|
||||
);
|
||||
return resp.data
|
||||
|
||||
|
@ -2,9 +2,9 @@ import { api } from "../utils/axiosClient";
|
||||
|
||||
export const DocumentRepository = {
|
||||
uploadDocument:(data)=> api.post(`/api/Document/upload`,data),
|
||||
getDocumentList:(entityTypeId,entityId,pageSize, pageNumber, filter,searchString)=>{
|
||||
getDocumentList:(entityTypeId,entityId,pageSize, pageNumber, filter,searchString,isActive)=>{
|
||||
const payloadJsonString = JSON.stringify(filter);
|
||||
return api.get(`/api/Document/list/${entityTypeId}/entity/${entityId}/?pageSize=${pageSize}&pageNumber=${pageNumber}&filter=${payloadJsonString}&searchString=${searchString}`)
|
||||
return api.get(`/api/Document/list/${entityTypeId}/entity/${entityId}/?pageSize=${pageSize}&pageNumber=${pageNumber}&filter=${payloadJsonString}&searchString=${searchString}&isActive=${isActive}`)
|
||||
},
|
||||
getDocumentById:(id)=>api.get(`/api/Document/get/details/${id}`),
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user