Compare commits

..

No commits in common. "fd143285629882a667ffa0a24c9d0c4eba01e77c" and "528d3b756ce46dbddba1f463acde7a7a680c80bb" have entirely different histories.

5 changed files with 153 additions and 227 deletions

View File

@ -21,13 +21,12 @@ 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:
@ -47,13 +46,12 @@ 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,
@ -63,6 +61,7 @@ const Documents = ({ Document_Entity, Entity }) => {
isOpen: false,
});
const { setOffcanvasContent, setShowTrigger } = useFab();
const methods = useForm({
@ -96,16 +95,17 @@ const Documents = ({ Document_Entity, Entity }) => {
viewDoc,
setViewDoc,
setOpenDocument,
OpenDocument,
};
OpenDocument
}
useEffect(()=>{
if(Document_Entity){
setDocumentEntity(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">
@ -138,32 +138,15 @@ 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({
onClick={() => setManageDoc({
document: null,
isOpen: true,
})
}
})}
>
<i className="bx bx-plus fs-4 text-white"></i>
</button>
@ -176,7 +159,6 @@ const Documents = ({ Document_Entity, Entity }) => {
searchText={searchText}
setIsRefetching={setIsRefetching}
setRefetchFn={setRefetchFn}
isActive={isActive}
/>
</div>
@ -204,30 +186,23 @@ const Documents = ({ Document_Entity, Entity }) => {
)}
{viewDoc.isOpen && (
<GlobalModel
size="lg"
isOpen={viewDoc.isOpen}
closeModal={() =>
setViewDoc({
<GlobalModel size="lg" isOpen={viewDoc.isOpen} closeModal={()=>setViewDoc({
document:null,
isOpen: false,
})
}
>
isOpen:false
})}>
<ViewDocument />
</GlobalModel>
)}
{OpenDocument && (
<GlobalModel
isOpen={OpenDocument}
closeModal={() => setOpenDocument(false)}
>
<GlobalModel isOpen={OpenDocument} closeModal={()=>setOpenDocument(false)}>
<DocumentViewerModal/>
</GlobalModel>
)}
</div>
</DocumentContext.Provider>
);
};

View File

@ -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,14 +20,11 @@ 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,
@ -35,21 +32,21 @@ const DocumentsList = ({
ITEMS_PER_PAGE,
currentPage,
filters,
debouncedSearch,
isActive
debouncedSearch
);
// 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);
@ -69,8 +66,9 @@ const DocumentsList = ({
if (isFilterEmpty) return <div>No documents match your filter.</div>;
const handleDelete = () => {
debugger;
ActiveInActive(
{ documentId: deletingId, isActive: !isActive },
{ documentId: deletingId, isActive: false },
{
onSettled: () => {
setDeletingId(null);
@ -79,21 +77,6 @@ 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",
@ -111,6 +94,10 @@ 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
@ -119,31 +106,27 @@ const DocumentsList = ({
firstName={e.uploadedBy?.firstName}
lastName={e.uploadedBy?.lastName}
/>
<span className="text-truncate ms-1">
<span className="text-truncate ">
{`${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),
align: "text-center",
getValue: (e) => formatUTCToLocalTime(e?.uploadedAt),
isAlwaysVisible: true,
align: "text-center",
},
{
key: "Status",
label: "Status",
label: "status",
getValue: (e) => getDocuementsStatus(e.isVerified),
align: "text-center",
isAlwaysVisible: true,
align: "text-center",
},
];
@ -151,10 +134,13 @@ 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
@ -163,7 +149,7 @@ const DocumentsList = ({
message="Are you sure you want delete?"
onSubmit={handleDelete}
onClose={() => setIsDeleteModalOpen(false)}
loading={!!isPending}
loading={isPending}
paramData={deletingId}
/>
</div>
@ -184,10 +170,7 @@ const DocumentsList = ({
</tr>
</thead>
<tbody className="text-start">
{data?.data?.map((doc) => {
const isRestoring = restoringIds.includes(doc.id);
return (
{data?.data?.map((doc) => (
<tr key={doc.id}>
{DocumentColumns.map((col) => (
<td key={col.key} className={`sorting ${col.align}`}>
@ -197,19 +180,18 @@ const DocumentsList = ({
</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 })
setViewDoc({ document: doc?.id, isOpen: true })
}
></i>
<i
className="bx bx-edit text-secondary cursor-pointer"
onClick={() =>
setManageDoc({ document: doc.id, isOpen: true })
setManageDoc({ document: doc?.id, isOpen: true })
}
></i>
@ -217,33 +199,19 @@ const DocumentsList = ({
className="bx bx-trash text-danger cursor-pointer"
onClick={() => {
setIsDeleteModalOpen(true);
setDeletingId(doc.id);
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>
</tr>
);
})}
))}
</tbody>
</table>
{data?.data?.length > 0 && (
<Pagination
currentPage={currentPage}
totalPages={data.totalPages}
totalPages={data?.totalPages}
onPageChange={paginate}
/>
)}

View File

@ -87,30 +87,16 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
}
);
const onSubmit = (data) => {
const normalizeAttachment = (attachment) => {
if (!attachment) return null;
return {
...attachment,
fileSize: Math.ceil(attachment.fileSize / 1024),
};
};
const payload = {
...data,
attachment: normalizeAttachment(data.attachment),
};
if (ManageDoc?.document) {
const DocumentPayload = {
...payload,
...data,
id: DocData.id,
tags: MergedTagsWithExistenStatus(data?.tags, DocData?.tags),
};
UpdateDocument({ documentId: DocData?.id, DocumentPayload });
} else {
const DocumentPayload = { ...payload, entityId: Entity };
const DocumentPayload = { ...data, entityId: Entity };
UploadDocument(DocumentPayload);
}
};

View File

@ -31,8 +31,7 @@ export const useDocumentListByEntityId = (
pageSize,
pageNumber,
filter,
searchString = "",
isActive
searchString = ""
) => {
return useQuery({
queryKey: [
@ -43,7 +42,6 @@ export const useDocumentListByEntityId = (
pageNumber,
filter,
searchString,
isActive
],
queryFn: async () => {
const cleanedFilter = cleanFilter(filter);
@ -53,8 +51,7 @@ export const useDocumentListByEntityId = (
pageSize,
pageNumber,
cleanedFilter,
searchString,
isActive
searchString
);
return resp.data

View File

@ -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,isActive)=>{
getDocumentList:(entityTypeId,entityId,pageSize, pageNumber, filter,searchString)=>{
const payloadJsonString = JSON.stringify(filter);
return api.get(`/api/Document/list/${entityTypeId}/entity/${entityId}/?pageSize=${pageSize}&pageNumber=${pageNumber}&filter=${payloadJsonString}&searchString=${searchString}&isActive=${isActive}`)
return api.get(`/api/Document/list/${entityTypeId}/entity/${entityId}/?pageSize=${pageSize}&pageNumber=${pageNumber}&filter=${payloadJsonString}&searchString=${searchString}`)
},
getDocumentById:(id)=>api.get(`/api/Document/get/details/${id}`),