document can inside open in browser

This commit is contained in:
pramod mahajan 2025-09-02 19:34:42 +05:30
parent 809f2ef726
commit ef00f83c44
6 changed files with 92 additions and 32 deletions

View File

@ -0,0 +1,27 @@
import React, { useEffect } from "react";
import { useDocumentVersion } from "../../hooks/useDocument";
import { useDocumentContext } from "./Documents";
import { error } from "pdf-lib";
const DocumentViewerModal = () => {
const { viewDoc,setOpenDocument } = useDocumentContext();
const { data, isLoading, isError,error } = useDocumentVersion(viewDoc.document);
useEffect(() => {
if (data?.data) {
const fileUrl = data.data;
window.open(fileUrl, "_blank");
setOpenDocument(false)
}
}, [data]);
if (isLoading) return <p>Loading document...</p>;
if (isError) return <div>
<p className="danger-text">{error.message}</p>
</div>;
// Nothing to render inside modal since we redirect
return null;
};
export default DocumentViewerModal;

View File

@ -14,6 +14,7 @@ import {
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import ManageDocument from "./ManageDocument"; import ManageDocument from "./ManageDocument";
import ViewDocument from "./ViewDocument"; import ViewDocument from "./ViewDocument";
import DocumentViewerModal from "./DocumentViewerModal";
// Context // Context
export const DocumentContext = createContext(); export const DocumentContext = createContext();
@ -50,6 +51,7 @@ const Documents = ({ Document_Entity, Entity }) => {
const [refetchFn, setRefetchFn] = useState(null); const [refetchFn, setRefetchFn] = useState(null);
const [DocumentEntity,setDocumentEntity] = useState(Document_Entity) const [DocumentEntity,setDocumentEntity] = useState(Document_Entity)
const { employeeId } = useParams(); const { employeeId } = useParams();
const [OpenDocument,setOpenDocument] = useState(false)
const [ManageDoc, setManageDoc] = useState({ const [ManageDoc, setManageDoc] = useState({
document: null, document: null,
isOpen: false, isOpen: false,
@ -91,7 +93,9 @@ const Documents = ({ Document_Entity, Entity }) => {
ManageDoc, ManageDoc,
setManageDoc, setManageDoc,
viewDoc, viewDoc,
setViewDoc setViewDoc,
setOpenDocument,
OpenDocument
} }
useEffect(()=>{ useEffect(()=>{
@ -189,6 +193,13 @@ const Documents = ({ Document_Entity, Entity }) => {
<ViewDocument /> <ViewDocument />
</GlobalModel> </GlobalModel>
)} )}
{OpenDocument && (
<GlobalModel isOpen={OpenDocument} closeModal={()=>setOpenDocument(false)}>
<DocumentViewerModal/>
</GlobalModel>
)}
</div> </div>
</DocumentContext.Provider> </DocumentContext.Provider>

View File

@ -9,7 +9,6 @@ import { DocumentTableSkeleton } from "./DocumentSkeleton";
import { getDocuementsStatus, useDocumentContext } from "./Documents"; import { getDocuementsStatus, useDocumentContext } from "./Documents";
import Pagination from "../common/Pagination"; import Pagination from "../common/Pagination";
const DocumentsList = ({ const DocumentsList = ({
Document_Entity, Document_Entity,
Entity, Entity,
@ -19,7 +18,7 @@ const DocumentsList = ({
setRefetchFn, setRefetchFn,
}) => { }) => {
const debouncedSearch = useDebounce(searchText, 500); const debouncedSearch = useDebounce(searchText, 500);
const [currentPage,setCurrentPage] = useState(1) const [currentPage, setCurrentPage] = useState(1);
const { data, isError, isLoading, error, refetch, isFetching } = const { data, isError, isLoading, error, refetch, isFetching } =
useDocumentListByEntityId( useDocumentListByEntityId(
Document_Entity, Document_Entity,
@ -40,19 +39,20 @@ const DocumentsList = ({
setIsRefetching(isFetching); setIsRefetching(isFetching);
}, [isFetching, setIsRefetching]); }, [isFetching, setIsRefetching]);
const {setManageDoc,setViewDoc} = useDocumentContext() const { setManageDoc, setViewDoc } = useDocumentContext();
// check no data scenarios const paginate = (page) => {
const noData = !isLoading && !isError && data?.data.length === 0;
const isSearchEmpty = noData && !!debouncedSearch;
const isFilterEmpty = noData && false;
const isInitialEmpty = noData && !debouncedSearch;
const paginate = (page) => {
if (page >= 1 && page <= (data?.totalPages ?? 1)) { if (page >= 1 && page <= (data?.totalPages ?? 1)) {
setCurrentPage(page); setCurrentPage(page);
} }
}; };
if (isLoading || isFetching) return <DocumentTableSkeleton />
const noData = !isLoading && !isError && data?.data.length === 0;
const isSearchEmpty = noData && !!debouncedSearch;
const isFilterEmpty = noData && !!filters && Object.keys(filters).length > 0;
const isInitialEmpty = noData && !debouncedSearch && !isFilterEmpty;
if (isLoading || isFetching) return <DocumentTableSkeleton />;
if (isError) if (isError)
return <div>Error: {error?.message || "Something went wrong"}</div>; return <div>Error: {error?.message || "Something went wrong"}</div>;
if (isInitialEmpty) return <div>No documents found yet.</div>; if (isInitialEmpty) return <div>No documents found yet.</div>;
@ -137,9 +137,19 @@ const DocumentsList = ({
))} ))}
<td className="text-center"> <td className="text-center">
<div className="d-flex justify-content-center gap-2"> <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-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-edit text-secondary cursor-pointer"
onClick={() =>
setManageDoc({ document: doc?.id, isOpen: true })
}
></i>
<i className="bx bx-trash text-danger cursor-pointer"></i> <i className="bx bx-trash text-danger cursor-pointer"></i>
</div> </div>
@ -149,12 +159,12 @@ const DocumentsList = ({
</tbody> </tbody>
</table> </table>
{data?.data?.length > 0 && ( {data?.data?.length > 0 && (
<Pagination <Pagination
currentPage={currentPage} currentPage={currentPage}
totalPages={data?.totalPages} totalPages={data?.totalPages}
onPageChange={paginate} onPageChange={paginate}
/> />
)} )}
</div> </div>
); );
}; };

View File

@ -12,7 +12,7 @@ import VersionListSkeleton from "./VersionListSkeleton";
import DocumentDetailsSkeleton from "./DocumentDetailsSkeleton "; import DocumentDetailsSkeleton from "./DocumentDetailsSkeleton ";
const ViewDocument = () => { const ViewDocument = () => {
const { viewDoc, setViewDoc } = useDocumentContext(); const { viewDoc, setViewDoc,setOpenDocument } = useDocumentContext();
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const { data, isLoading, isError, error } = useDocumentDetails( const { data, isLoading, isError, error } = useDocumentDetails(
viewDoc?.document viewDoc?.document
@ -39,8 +39,7 @@ const ViewDocument = () => {
<div className="p-1"> <div className="p-1">
<p className="fw-bold fs-6">Document Details</p> <p className="fw-bold fs-6">Document Details</p>
{/* Row 1 */}
{/* Row 1 */}
<div className="row mb-2"> <div className="row mb-2">
<div className="col-12 col-md-6"> <div className="col-12 col-md-6">
<div className="d-flex text-start"> <div className="d-flex text-start">
@ -184,8 +183,9 @@ const ViewDocument = () => {
<small>{getDocuementsStatus(document.isVerified)}</small> <small>{getDocuementsStatus(document.isVerified)}</small>
</div> </div>
</div> </div>
<div className="d-flex align-items-center text-secondary"> <div className="d-flex align-items-center justify-content-between text-secondary">
Upload By <div className="d-flex align-items-center">
Upload By
<Avatar <Avatar
size="xs" size="xs"
classAvatar="m-0" classAvatar="m-0"
@ -197,14 +197,18 @@ const ViewDocument = () => {
document.uploadedBy?.lastName ?? "" document.uploadedBy?.lastName ?? ""
}`.trim() || "N/A"} }`.trim() || "N/A"}
</span> </span>
</div>
<div className="d-flex text-primary align-items-center cursor-pointer"onClick={()=>setOpenDocument(true)} >
<small >view</small> <i className='bx bx-sm bx-link-external'></i>
</div>
</div> </div>
<div className="d-flex gap-2"> {/* <div className="d-flex gap-2">
{document?.updatedAt && ( {document?.updatedAt && (
<span className="small text-secondary"> <span className="small text-secondary">
Updated At : {formatUTCToLocalTime(document.updatedAt)} Updated At : {formatUTCToLocalTime(document.updatedAt)}
</span> </span>
)} )}
</div> </div> */}
</a> </a>
))} ))}
</div>)} </div>)}

View File

@ -91,6 +91,14 @@ export const useDocumentVersionList = (parentAttachmentId,pageSize,pageNumber) =
}); });
}; };
export const useDocumentVersion = (id)=>{
return useQuery({
queryKey:["DocumentVersion",id],
queryFn:async()=> await DocumentRepository.getDocumentVersion(id),
enabled:!!id
})
}
//----------------------- MUTATION ------------------------- //----------------------- MUTATION -------------------------
export const useUploadDocument = (onSuccessCallBack) => { export const useUploadDocument = (onSuccessCallBack) => {

View File

@ -86,12 +86,12 @@ const LoginPage = () => {
} }
}, [IsLoginWithOTP]); }, [IsLoginWithOTP]);
useEffect(() => { // useEffect(() => {
const token = localStorage.getItem("jwtToken"); // const token = localStorage.getItem("jwtToken");
if (token) { // if (token) {
navigate("/dashboard"); // navigate("/dashboard");
} // }
}, [navigate]); // }, [navigate]);
return ( return (
<AuthWrapper> <AuthWrapper>