diff --git a/apps/console/src/pages/DocumentSigningRequestsPage.tsx b/apps/console/src/pages/DocumentSigningRequestsPage.tsx deleted file mode 100644 index 7d279f05a..000000000 --- a/apps/console/src/pages/DocumentSigningRequestsPage.tsx +++ /dev/null @@ -1,462 +0,0 @@ -import { sprintf } from "@probo/helpers"; -import { useTranslate } from "@probo/i18n"; -import { - Button, - Card, - IconCircleCheck, - IconCircleProgress, - Logo, - Spinner, -} from "@probo/ui"; -import { clsx } from "clsx"; -import { useEffect, useState } from "react"; -import { useSearchParams } from "react-router"; -import { useWindowSize } from "usehooks-ts"; - -import { PDFPreview } from "../components/documents/PDFPreview"; - -type Document = { - document_version_id: string; - title: string; - signed?: boolean; - organization_name: string; -}; - -type DocumentSigningResponse = { - documents: Document[]; - organizationName: string; -}; - -export default function DocumentSigningRequestsPage() { - const { __ } = useTranslate(); - const [searchParams] = useSearchParams(); - const token = searchParams.get("token"); - - const [loading, setLoading] = useState(true); - const [signing, setSigning] = useState(false); - const [error, setError] = useState(null); - const [signingData, setSigningData] - = useState(null); - const [currentDocIndex, setCurrentDocIndex] = useState(0); - const [showAllDocuments, setShowAllDocuments] = useState(false); - - const { width } = useWindowSize(); - const isMobile = width < 1100; - const isDesktop = !isMobile; - - useEffect(() => { - document.body.style.setProperty("overflow", "hidden"); - return () => { - document.body.style.removeProperty("overflow"); - }; - }, []); - - useEffect(() => { - if (!token) { - setError( - __("Missing signing token. Please check your URL and try again."), - ); - setLoading(false); - return; - } - - async function fetchDocuments() { - try { - const response = await fetch( - "/api/console/v1/documents/signing-requests", - { - method: "GET", - headers: { - "Authorization": `Bearer ${token}`, - "Content-Type": "application/json", - }, - }, - ); - - if (!response.ok) { - throw new Error(__("Failed to fetch signing documents")); - } - - const documents = (await response.json()) as Document[]; - - const enhancedDocuments = documents.map(doc => ({ - ...doc, - signed: false, - })); - - // Extract organization name from the first document - const organizationName - = documents.length > 0 - ? documents[0].organization_name || "Organization" - : "Organization"; - - setSigningData({ - documents: enhancedDocuments, - organizationName, - }); - } catch (err) { - setError( - err instanceof Error ? err.message : __("An unknown error occurred"), - ); - } finally { - setLoading(false); - } - } - - void fetchDocuments(); - }, [token, __]); - - const handleSignDocument = async () => { - if (!signingData || !token) return; - - const docToSign = signingData.documents[currentDocIndex]; - - setSigning(true); - try { - const response = await fetch( - `/api/console/v1/documents/signing-requests/${docToSign.document_version_id}/sign`, - { - method: "POST", - headers: { - "Authorization": `Bearer ${token}`, - "Content-Type": "application/json", - }, - }, - ); - - if (!response.ok) { - throw new Error(__("Failed to sign document")); - } - - const updatedDocs = [...signingData.documents]; - updatedDocs[currentDocIndex] = { - ...updatedDocs[currentDocIndex], - signed: true, - }; - - setSigningData({ - ...signingData, - documents: updatedDocs, - }); - - // Collapse the document list when signing - setShowAllDocuments(false); - - if (currentDocIndex < updatedDocs.length - 1) { - setCurrentDocIndex(currentDocIndex + 1); - } - } catch (err) { - setError( - err instanceof Error ? err.message : __("Failed to sign document"), - ); - } finally { - setSigning(false); - } - }; - - const handleNextDocument = () => { - if (signingData && currentDocIndex < signingData.documents.length - 1) { - setCurrentDocIndex(currentDocIndex + 1); - } - }; - - const getSignedCount = () => { - if (!signingData) return 0; - return signingData.documents.filter(doc => doc.signed).length; - }; - - if (loading) { - return ( - <> - {__("Loading Signing Requests")} -
- -
- -
-

- {__("Loading Signing Requests")} -

-

- {__("Please wait while we fetch your documents...")} -

-
-
-
-
- - ); - } - - if (error) { - return ( - <> - {__("Error")} -
- -

- {__("Error")} -

-

{error}

- -
-
- - ); - } - - if (!signingData || signingData.documents.length === 0) { - return ( - <> - {__("No Documents to Sign")} -
- -

- {__("No Documents to Sign")} -

-

- {__( - "There are no documents requiring your signature at this time.", - )} -

-
-
- - ); - } - - const currentDoc = signingData.documents[currentDocIndex]; - const isLastDocument = currentDocIndex === signingData.documents.length - 1; - const allSigned = getSignedCount() === signingData.documents.length; - - // Build PDF URL with watermark - const pdfUrl = token - ? `${`/api/console/v1/documents/signing-requests/${currentDoc.document_version_id}/pdf`}?token=${encodeURIComponent(token)}` - : null; - - return ( - <> - {__("Document Signing")} -
-
- -
-
-
-

- {sprintf( - __("%s requests your signature"), - signingData.organizationName, - )} -

- {allSigned - ? ( -

- {__("You have successfully signed all documents. You can now close this page.")} -

- ) - : ( - <> -

- {__("Please review and sign the following documents:")} -

- -
- {(() => { - const renderDocumentItem = ( - doc: Document, - index: number, - ) => ( -
-
- {doc.signed - ? ( - - ) - : ( - - {index + 1} - - )} -
-
-

- {doc.title} -

-
-
- - {doc.signed - ? __("Signed") - : index === currentDocIndex - ? __("In review") - : __("Waiting signature")} - -
-
- ); - - const totalDocs = signingData.documents.length; - - if (totalDocs <= 4) { - return signingData.documents.map((doc, index) => - renderDocumentItem(doc, index), - ); - } - - if (showAllDocuments) { - return ( - <> - {signingData.documents.map((doc, index) => - renderDocumentItem(doc, index), - )} - - - ); - } - - // Always show current document in collapsed view with two "show more" buttons - const firstDoc = signingData.documents[0]; - const currentIsFirst = currentDocIndex === 0; - const currentIsLast = currentDocIndex === totalDocs - 1; - - // Calculate hidden docs before and after current - const hiddenBeforeCurrent = currentIsFirst - ? 0 - : currentDocIndex - 1; - const hiddenAfterCurrent = currentIsLast - ? 0 - : totalDocs - currentDocIndex - 2; - - return ( - <> - {/* First document */} - {renderDocumentItem(firstDoc, 0)} - - {/* Show more button for documents BEFORE current (signed documents) */} - {hiddenBeforeCurrent > 0 && ( - - )} - - {/* Current document (if not first) */} - {!currentIsFirst - && renderDocumentItem(currentDoc, currentDocIndex)} - - {/* Show more button for documents AFTER current (upcoming documents) */} - {hiddenAfterCurrent > 0 && ( - - )} - - ); - })()} -
-
-

- {__("Please review the document carefully before signing.")} -

- - )} - {isMobile && pdfUrl && ( - - )} - {!currentDoc.signed && !allSigned && ( - <> - -

- {__( - "By clicking 'I acknowledge and agree', your digital signature will be recorded.", - )} -

- - )} - {currentDoc.signed && !isLastDocument && ( - - )} - - Powered by - {" "} - - -
- {isDesktop && ( -
- {pdfUrl && } -
- )} -
-
- - ); -} diff --git a/apps/console/src/routes.tsx b/apps/console/src/routes.tsx index c44d39b6b..fa8d271cd 100644 --- a/apps/console/src/routes.tsx +++ b/apps/console/src/routes.tsx @@ -119,13 +119,6 @@ const routes = [ }, ], }, - { - path: "documents/signing-requests", - ErrorBoundary: RootErrorBoundary, - Component: lazy( - () => import("./pages/DocumentSigningRequestsPage"), - ), - }, { path: "/organizations/:organizationId", children: [