import React, { useState, useEffect } from 'react'; import { FaArrowLeft, FaCheck, FaExternalLinkAlt, FaEye, FaEyeSlash, FaRedo, FaImage, FaUsers, FaFileAlt, FaEnvelope, FaCog, FaShieldAlt, FaBell, FaDownload, FaShare, FaEdit, FaSave, FaClock, FaLock } from 'react-icons/fa'; import { RootState } from '../../../store/store'; import api from '../../../config/api'; import { fetchRecipients } from "../../../store/slices/selectedRecipientsSlice"; import { fetchDocuments } from "../../../store/slices/documentSlice"; import { useDispatch, useSelector } from "react-redux"; import { Link, useLocation, useNavigate, useParams } from "react-router-dom"; import Loader from "../../dashboard/Loader"; import confetti from 'canvas-confetti' import { IoClose } from "react-icons/io5"; import { IoMdClose, IoMdHome } from "react-icons/io"; import { Bounce, toast } from "react-toastify"; type Signer = { id: number; name: string; email: string; routingOrder: number; completed: boolean; }; // Signers List Component const SignersList: React.FC<{ signers: Signer[] }> = ({ signers }) => { return ( //

Signature Status

{signers.filter(s => s.completed).length} of {signers.length} signed
{signers.map((signer) => (
{signer.name.length > 2 ? signer.name.split(" ").map(n => n[0].toUpperCase()).join("") : signer.email.split("").map(n => n[0].toUpperCase()).join("")}
{signer.name}
{signer.email}
Order: {signer.routingOrder}
{signer.completed ? (
Signed
) : (
Pending
)}
))}
//
); }; // Fixed Signing Order Diagram Component const SigningOrderDiagram: React.FC<{ signers: Signer[] }> = ({ signers }) => { const groupByRoutingOrder = (data: Signer[]) => { const grouped: Record = {}; data.forEach((signer) => { if (!grouped[signer.routingOrder]) { grouped[signer.routingOrder] = []; } grouped[signer.routingOrder].push(signer); }); return grouped; }; const getInitials = (name: string) => { return name .split(" ") .map((n) => n[0].toUpperCase()) .join(""); }; const grouped = groupByRoutingOrder(signers); const sortedOrders = Object.keys(grouped) .map(Number) .sort((a, b) => a - b); const currentProcessingOrder = sortedOrders.find((order) => grouped[order].some((signer) => !signer.completed) ) || -1; return ( //

Signing Flow

{/* Mail icon */}

Sent

{/* Dotted line */}
{/* Signers by routing order */}
{sortedOrders.map((order, index) => (
Step {order}
{grouped[order].map((signer) => { let bgColor = ""; let icon = null; if (signer.completed) { bgColor = "bg-[var(--primary)]"; icon = ; } else if (order === currentProcessingOrder) { bgColor = "bg-yellow-500"; icon = ; } else { bgColor = "bg-gray-400"; icon = ; } return (
{getInitials(signer.name)} {icon}

{signer.name.split(" ")[0] || signer.firstName.split(0, 1)}

); })}
{index < sortedOrders.length - 1 && (
)}
))}
//
); }; const DocumentSubmissionOptions = () => { const location = useLocation(); const [status, setStatus] = useState(null); console.log("location.pathname", location.pathname, status) const { accountId, transactionId } = useParams<{ accountId: string, transactionId: string }>(); const [showConfetti, setShowConfetti] = React.useState(true) if (!accountId || !transactionId) { window.location.href = "/"; return null; } // const transactionId = useSelector((state: RootState) => state.transaction.transactionId) const navigate = useNavigate(); const dispatch = useDispatch(); const selectedRecipients = useSelector((state: RootState) => state.selectedRecipients.recipients); // const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments) const selectedDocuments = useSelector((state: RootState) => state.documents.documents) console.log('Line 218', selectedDocuments) const [transactionData, setTransactionData] = useState({}) useEffect(() => { selectedRecipients.length === 0 && dispatch(fetchRecipients({ accountId, transactionId })); selectedDocuments.length === 0 && dispatch(fetchDocuments({ accountId, transactionId })); }, []) useEffect(() => { // toast.dismiss(); // toast.success("Your document has been successfully sent for signature.", { // position: "top-center", // autoClose: 1500, // hideProgressBar: false, // closeOnClick: false, // pauseOnHover: true, // draggable: true, // progress: undefined, // theme: "light", // transition: Bounce, // }); if (showConfetti) { const duration = 3000; const end = Date.now() + duration; const interval = setInterval(() => { if (Date.now() > end) { clearInterval(interval); return; } confetti({ particleCount: 5, // fewer particles per burst for smoothness angle: 90, // falling straight down spread: 30, // slight spread startVelocity: 8, // gentle falling speed origin: { x: Math.random(), // random horizontal position across the top y: 0, }, scalar: 1, zIndex: 9999, }); }, 50); // fire every 50ms for continuous effect return () => clearInterval(interval); } }, [showConfetti]); console.log("History length:", window.history.length); // Step 1: Fetch transaction status useEffect(() => { const fetchTransaction = async () => { // /api/accounts/{accountId}/transactions/{trxId} try { const res = await api.get(`/api/accounts/${accountId}/transactions/${transactionId}`); if (res?.data) { setStatus(res?.data?.status); setTransactionData(res?.data) } } catch (error) { console.error("Failed to fetch transaction:", error); } }; if (accountId && transactionId) { fetchTransaction(); } }, [accountId, transactionId]); // Step 2: Prevent browser back when status === 'SENT' useEffect(() => { if (status === "SENT") { const currentPath = window.location.pathname; const handlePopState = (event) => { // Show warning alert("Back navigation is blocked on this screen."); // Push the current URL back to prevent navigating away window.history.pushState(null, "", currentPath); }; // Push extra states to build history buffer for (let i = 0; i < 50; i++) { window.history.pushState(null, "", currentPath); } // Add popstate listener window.addEventListener("popstate", handlePopState); // Cleanup on unmount return () => { window.removeEventListener("popstate", handlePopState); }; } }, [status]); // useEffect(() => { // if (status === 'SENT') { // // Step 1: Push a dummy state to trap the user // window.history.pushState(null, '', window.location.href); // // Step 2: Intercept back button // const handlePopState = (event) => { // // Push the same dummy state again to block back // window.history.pushState(null, '', window.location.href); // }; // window.addEventListener('popstate', handlePopState); // return () => { // window.removeEventListener('popstate', handlePopState); // }; // } // }, [status]); const [selectedOption, setSelectedOption] = useState('success'); const [isVisible, setIsVisible] = useState(false); const [previewData, setPreviewData] = useState({ documentName: "Contract Agreement.pdf", submissionCount: 1, signerName: "Sumit Kumar", signerEmail: "sumit.kumar@hicglobalsolutions.com", submissionTime: new Date().toLocaleString() }); useEffect(() => { setIsVisible(true); }, []); const options = [ { id: 'success', icon: FaCheck, title: 'Success screen', description: 'Display confirmation message after successful document submission', color: 'bg-green-50 border-green-200 hover:bg-green-100', iconColor: 'text-green-600', isPremium: false }, { id: 'redirect', icon: FaExternalLinkAlt, title: 'Signing Flow', description: 'Navigate user to view their transaction details', color: 'bg-blue-50 border-blue-200 hover:bg-blue-100', iconColor: 'text-blue-600', isPremium: true }, { id: 'public', icon: FaEye, title: 'Signature status', description: 'Show transaction status on public dashboard', color: 'bg-purple-50 border-purple-200 hover:bg-purple-100', iconColor: 'text-purple-600', isPremium: true }, ]; const getPreviewContent = () => { switch (selectedOption) { case 'success': return (

Document Send Successfully!

{selectedDocuments?.map((docs) => (

Your document "{docs.name}" has been sent for signature.

))}
createdBy: {transactionData?.createdBy?.name}
Email: {transactionData?.createdBy?.email}
createdAt: {transactionData.createdAt}
); case 'redirect': return ( <> ); case 'public': return ( <> ); default: return null; } }; return (

🎉 Awesome! The document’s been sent for signature. 🎉

{/* Header */} {/*

Choose an action after a signer completes the document.

{options.map((option) => { const Icon = option.icon; const isSelected = selectedOption === option.id; return (
setSelectedOption(option.id)} className={` relative cursor-pointer p-4 rounded-xl border-2 transition-all duration-200 group ${isSelected ? 'border-[var(--primary)] bg-blue-50 shadow-md scale-[1.02]' : option.color + ' border-2' } hover:shadow-md hover:scale-[1.01] transform `} >

{option.title}

{option.isPremium && ( ★ )}

{option.description}

{isSelected && (
)}
); })}

Live Preview

See how your users will experience the completion

{getPreviewContent()}
*/}

Document Send Successfully!

); }; export default DocumentSubmissionOptions;