SME-Web/src/components/process/processStepTwo/NavTwo.tsx

551 lines
25 KiB
TypeScript

import React, { useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { RootState } from '../../../store/store'
import { FaAngleRight, FaCheck, FaChevronRight, FaPaste, FaRegCopy, FaSave, FaSignature } from 'react-icons/fa'
import { IoIosDocument, IoMdArrowRoundBack, IoMdHome } from 'react-icons/io'
import { LuRedo2, LuTableOfContents, LuUndo2 } from 'react-icons/lu'
import { MdKeyboardArrowDown, MdOutlineKeyboardBackspace } from 'react-icons/md'
import { RiResetRightLine } from 'react-icons/ri'
import { fetchRecipients, recipientType, toggleToTemplates, TRANSACTION_TEMPLATE_TOGGLE } from '../../../store/slices/selectedRecipientsSlice'
import { fetchDocuments } from '../../../store/slices/documentSlice'
import { Link, useNavigate, useParams } from 'react-router-dom'
import { Bounce, toast } from 'react-toastify'
import { FiChevronDown } from 'react-icons/fi'
import RecipientsCon from '../processStepOne/RecipientsCon'
import MessageCon from '../processStepOne/MessageCon'
import { IoArrowBackSharp, IoCopy } from 'react-icons/io5'
import { FaRegPaste } from 'react-icons/fa6'
import ConfirmSendModal from './TransactionSendConfirmationModal'
import { RxDividerVertical } from 'react-icons/rx'
import CloseConfirmationModal from './CloseCofirmationModal'
interface NavTwoProps {
transactionSaving?: boolean;
// setTransactionSaving: React.Dispatch<React.SetStateAction<boolean>>
isFields?: boolean;
setIsFields?: React.Dispatch<React.SetStateAction<boolean>>
isPages?: boolean;
setIsPages?: React.Dispatch<React.SetStateAction<boolean>>
isSend?: boolean | null;
setIsSend?: React.Dispatch<React.SetStateAction<boolean | null>>
isPreview?: boolean
aId?: string | null
tId?: string | null
onSendClick?: (isSave?: boolean, navigate?: boolean, navigateTo?: string) => void;
}
interface FIT {
label: string,
value: number | null
}
const fitObj = [
{
label: "Fit",
value: "FIT"
},
{
label: "50%",
value: "50"
},
{
label: "150%",
value: "150"
},
{
label: "200%",
value: "200"
},
]
const NavTwo: React.FC<NavTwoProps> = ({
transactionSaving = false,
isFields,
setIsFields,
isPages,
setIsPages,
isSend,
setIsSend,
isPreview = false,
aId = null,
tId = null,
onSendClick,
}) => {
let transactionTemplateToggle = TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS;
const dispatch = useDispatch();
const [showActionsDropDown, setShowActionsDropDown] = useState<boolean>(false);
const [editRecipientsModal, setEditRecipientsModal] = useState<boolean>(false);
const [messageModal, setMessageModal] = useState<boolean>(false);
const [confirmSendModalOpen, setConfirmSendModalOpen] = useState({
"open": false,
"confirm": false,
"loading": false
});
console.log(editRecipientsModal)
const params = useParams<{ accountId?: string; transactionId?: string; templateId?: string }>();
let accountId = params.accountId;
let transactionId = params.transactionId
if (!transactionId) {
transactionTemplateToggle = TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES;
transactionId = params.templateId;
dispatch(toggleToTemplates());
}
if (!accountId || !transactionId) {
window.location.href = "/";
return null;
}
// If is preview is enable
if (isPreview && aId != null && tId != null) {
accountId = aId;
transactionId = tId;
}
// const [transactionSaving, setTransactionSaving] = useState<boolean>(false);
const [dotCount, setDotCount] = useState(0);
const [closePage, setClosePage] = useState(false);
const [isFitDd, setIsFitDd] = useState<boolean>(false)
const [selFitIndx, setSelFitIndx] = useState<number>(0);
const [selfUserSign, setSelfUserSign] = useState({ sign: false, recipientId: 0 });
const navigate = useNavigate()
const selectedRecipients = useSelector((state: RootState) => state.selectedRecipients.recipients)
const selectedDocuments = useSelector((state: RootState) => state.documents.documents)
const userDetails = useSelector((state: RootState) => state.user);
useEffect(() => {
if (selectedRecipients.length || selectedDocuments.length) return;
(async () => {
selectedRecipients.length == 0 && await dispatch(fetchRecipients({ accountId, transactionId }));
selectedDocuments.length == 0 && await dispatch(fetchDocuments({ accountId, transactionId }));
})()
}, [])
useEffect(() => {
if (selectedRecipients.length > 0) {
let minRoutingOrder: number = Infinity;
let userEmailPresent = {
present: false,
routingOrder: 0,
recipientId: 0,
type: recipientType.CC
};
// Getting Minimum RoutingOrder
for (let i = 0; i < selectedRecipients.length; i++) {
const recipient = selectedRecipients[i]
if (recipient.routingOrder < minRoutingOrder) {
minRoutingOrder = recipient.routingOrder;
}
if (recipient.email == userDetails.email) {
userEmailPresent.present = true;
userEmailPresent.routingOrder = recipient.routingOrder;
userEmailPresent.recipientId = recipient.id;
userEmailPresent.type = recipient.type;
}
}
if (userEmailPresent.present && userEmailPresent.routingOrder == minRoutingOrder && userEmailPresent.type != recipientType.CC && userEmailPresent.type != recipientType.INPERSONSIGNER) {
setSelfUserSign({ sign: true, recipientId: userEmailPresent.recipientId })
}
}
}, [selectedRecipients])
const [nav2RecToggle, setNav2RecToggle] = useState<boolean>(false);
const [nav2DocToggle, setNav2DocToggle] = useState<boolean>(false);
const transactionSendValidation = () => {
const transactionSendValidationObj = {
oneSignerIsRequiredError: true
}
// One Signer is required - Validation
for (const recipient of selectedRecipients) {
if (recipient.type == recipientType.SIGNER || recipient.type == recipientType.INPERSONSIGNER) {
transactionSendValidationObj.oneSignerIsRequiredError = false; break
};
}
if (!transactionSendValidationObj.oneSignerIsRequiredError) return false;
return transactionSendValidationObj;
}
function handleSend(isSignSend: boolean = false) {
// dispatch(showLoader("Loading ..."));
if (onSendClick === undefined) return;
const transactionSendValidationObj = transactionSendValidation()
if (transactionSendValidationObj.oneSignerIsRequiredError) {
return
}
// if (isSend == null) {
// setIsSend(false);
// }
// setIsSend(!isSend);
// setTimeout(() => {
setConfirmSendModalOpen({ open: false, confirm: false, loading: false })
if (transactionTemplateToggle == TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS) {
if (isSignSend) {
// SELF SIGN CHECK HERE
window.open(`./../../../sign/${selfUserSign.recipientId}`, "_self");
}
else {
onSendClick(false); // false for not a save action
}
} else {
onSendClick(true, true, "/templates"); // true for save action
}
// }, 1000)
}
useEffect(() => {
if (confirmSendModalOpen.confirm) handleSend()
}, [confirmSendModalOpen])
const zoom = (percentage: number, contentClass: string) => {
const content = document.querySelector(`.${contentClass}`);
if (content) {
(content as HTMLElement).style.zoom = `${percentage}%`;
}
}
useEffect(() => {
let indx = fitObj[selFitIndx].value
if (indx == "FIT") {
indx = "100";
}
zoom(Number(indx), 'zoom-con')
}, [selFitIndx])
useEffect(() => {
if (!transactionSaving) return;
const interval = setInterval(() => {
setDotCount((prev) => (prev + 1) % 4); // Cycle through 0, 1, 2, 3
}, 500); // Update every 0.5s
return () => clearInterval(interval);
}, [transactionSaving]);
const dots = '. '.repeat(dotCount);
return (
<>
{closePage && <CloseConfirmationModal
open={closePage}
onClose={() => setClosePage(false)} // Cancel not closing
onConfirm={() => navigate("/")}
/>}
<ConfirmSendModal
confirmSendModalOpen={confirmSendModalOpen.open}
confirmSendModalOnClose={() => { setConfirmSendModalOpen({ open: false, confirm: false, loading: false }) }}
confirmSendModalOnConfirm={() => { setConfirmSendModalOpen({ open: true, confirm: true, loading: true }) }}
confirmSendModalLoading={confirmSendModalOpen.loading}
documents={selectedDocuments}
recipients={selectedRecipients}
/>
{/* Nav Two - Oprions - START */}
<div className='relative flex justify-between items-center px-4 py-1 bg-white'>
{/* Left Side */}
<div className='flex justify-start items-center gap-2'>
{/* <div>
<Link to={"/"}>
<img width={120} src="/sme-colored.png" alt="Sign Made Easy" />
</Link>
</div> */}
<div className='flex items-center gap-3'>
<div className='flex gap-4 text-xl text-slate-600'>
<button
className='hover:text-[var(--primary)] durartion-300 cursor-pointer'
onClick={() => setClosePage(true)}
>
<IoMdHome />
{/* <img width={120} src="/sme-colored.png" alt="Sign Made Easy" /> */}
</button>
<button
className='hover:text-[var(--primary)] durartion-300 cursor-pointer'
onClick={() => navigate(-1)}
>
<IoArrowBackSharp />
</button>
</div>
<div className='w-[1px] h-[28px] bg-slate-200'></div>
<div className='flex items-center gap-2 text-xs'>
<button
onClick={() => navigate(-1)}
className='underline font-thin cursor-pointer'>
Set Up Transaction
</button>
<FaAngleRight className='font-thin' />
<p className='font-normal'>Add Fields</p>
</div>
</div>
<div
tabIndex={1}
onBlur={() => setIsFitDd(false)}
className='absolute gap-2 flex items-center left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] z-50'
>
<div className='flex'>
<p className='p-2 hover:bg-slate-100 cursor-pointer rounded-sm'>
<LuUndo2 className='text-sm text-slate-600' />
</p>
<p className='p-2 hover:bg-slate-100 cursor-pointer rounded-sm'>
<LuRedo2 className='text-sm text-slate-600' />
</p>
</div>
<div className='w-full h-[20px] border-[1px] border-slate-200'></div>
<div className='flex'>
<p className='p-2 hover:bg-slate-100 cursor-pointer rounded-sm'>
<FaRegCopy className='text-sm text-slate-600' />
</p>
<p className='p-2 hover:bg-slate-100 cursor-pointer rounded-sm'>
<FaRegPaste className='text-sm text-slate-600' />
</p>
</div>
<div className='w-full h-[20px] border-[1px] border-slate-200'></div>
<div className='border border-slate-400 rounded-sm ml-1'>
<div
onClick={() => setIsFitDd(!isFitDd)}
className='hidden sm:flex md:flex items-center gap-1 cursor-pointer text-xs px-2 py-1 rounded-sm'
>
<p className='tracking-wide'>{fitObj[selFitIndx]?.label}</p>
<MdKeyboardArrowDown style={{ transform: `${isFitDd ? "rotate(180deg)" : ""}` }} />
</div>
{isFitDd && <div className='absolute bg-white rounded-sm z-[1000] shadow'>
{fitObj.map((val, indx) => {
return (<div
key={indx}
onClick={() => setSelFitIndx(indx)}
className='flex z-50 items-center justify-between gap-2 w-[70px] p-2 text-xs cursor-default hover:bg-slate-100'>
<div
className='flex items-center justify-between w-full'>
<p className='whitespace-nowrap overflow-hidden text-ellipsis max-w-[12ch]'>{val.label}</p>
{selFitIndx == indx && <FaCheck className='text-sm text-slate-400' />}
</div>
</div>)
})
}
</div>}
</div>
</div>
{/* {!isPreview && <div className='hidden sm:flex items-center gap-1 cursor-pointer text-xs px-2 py-1 rounded-sm'>
<RiResetRightLine
className={`${transactionSaving ? "animate-spin" : ""} transition duration-300`}
/>
<p className="tracking-wide transition-all">{transactionSaving ? `Saving ${dots}` : "Save"}</p>
</div>} */}
</div>
{/* Right Side - STARTS */}
<div className='flex justify-center items-center'>
<div
className="relative inline-block text-left">
{/* Trigger */}
<button
onClick={() => setShowActionsDropDown((prev) => !prev)}
className="flex justify-center items-center bg-white px-4 py-2 text-xs font-medium text-gray-700 hover:bg-gray-50 cursor-pointer">
<p className='tracking-wide mr-1'>Actions</p>
<MdKeyboardArrowDown />
</button>
{/* Menu */}
{showActionsDropDown && <div
className="absolute right-0 mt-2 w-48 rounded-md bg-white shadow-sm ring-1 ring-black/5 z-10">
<div
className="py-1">
{/* <button className="w-full text-left px-4 py-2 text-sm hover:bg-gray-100">
Save & Close
</button> */}
<button
onClick={() => {
if (onSendClick !== undefined) onSendClick(true, false); // true for save action
setShowActionsDropDown(false)
}}
className="cursor-pointer w-full text-left px-4 py-2 text-sm hover:bg-gray-100">
Save Changes
</button>
<button
onClick={() => {
if (onSendClick !== undefined) onSendClick(true, true, transactionTemplateToggle === TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES ? "/templates" : "/"); // true for save action
setShowActionsDropDown(false);
}}
className="cursor-pointer w-full text-left px-4 py-2 text-sm hover:bg-gray-100">
Save & Exit
</button>
<button
onClick={() => {
setMessageModal(true)
setShowActionsDropDown(false)
}}
className="cursor-pointer w-full text-left px-4 py-2 text-sm hover:bg-gray-100">
Edit Message
</button>
<button
onClick={() => {
setEditRecipientsModal(true)
setShowActionsDropDown(false)
}}
className="cursor-pointer w-full text-left px-4 py-2 text-sm hover:bg-gray-100">
Edit Recipients
</button>
{/* <button
onClick={() => {
setEditRecipientsModal(true)
setShowActionsDropDown(false)
}}
className="w-full text-left px-4 py-2 text-sm hover:bg-gray-100">
Edit Documents
</button>
<button className="w-full text-left px-4 py-2 text-sm hover:bg-gray-100">
Advanced Options
</button> */}
</div>
</div>}
</div>
{/* Document Nav */}
<div className='hidden sm:block'
tabIndex={1} onBlur={() => setNav2DocToggle(false)}>
<div onClick={() => setNav2DocToggle(!nav2DocToggle)} className='flex items-center gap-1 cursor-pointer text-xs px-2 py-1 rounded-sm'>
<p className='tracking-wide'>{selectedDocuments.length} Documents</p>
<MdKeyboardArrowDown className={`${nav2DocToggle ? 'rotate-180' : ''} transition-all`} />
</div>
<div
className={`absolute max-w-max shadow rounded-md mt-1 px-2 py-1 z-20 bg-white ${nav2DocToggle ? '' : 'hidden'}`}>
{selectedDocuments.length && selectedDocuments.map((document, indx) => {
return (<div key={indx} className='flex items-center justify-between gap-2 w-full p-2 text-xs rounded-sm cursor-default'>
<div className='flex items-center gap-1'>
{/* <p className='w-3 h-3 rounded-sm' style={{ background: recipient.color }}></p> */}
<IoIosDocument className='text-slate-600 text-lg' />
<p className='whitespace-nowrap overflow-hidden text-ellipsis max-w-[15ch]'>{document.name}</p>
</div>
</div>)
})}
</div>
</div>
{/* Recipients Nav */}
<div className='hidden sm:block relative' tabIndex={1} onBlur={() => setNav2RecToggle(false)}>
<div onClick={() => setNav2RecToggle(!nav2RecToggle)} className='flex items-center gap-1 cursor-pointer text-xs px-2 py-1 rounded-sm'>
<p className='tracking-wide'>{selectedRecipients.length} Recipients</p>
<MdKeyboardArrowDown className={`${nav2RecToggle ? 'rotate-180' : ''} transition-all`} />
</div>
<div
className={`absolute max-w-max shadow rounded-md mt-1 px-2 py-1 z-20 bg-white ${nav2RecToggle ? '' : 'hidden'}`}>
{selectedRecipients.length && selectedRecipients.map((recipient, indx) => {
return (<div key={indx} className='flex items-center justify-between gap-2 w-full p-2 text-xs rounded-sm cursor-default'>
<div className='flex items-center gap-1.5'>
<p className='w-3 h-3 rounded-sm' style={{ background: recipient.color }}></p>
<p className='whitespace-nowrap overflow-hidden text-ellipsis max-w-[22ch]'>{recipient.type + " | "} {recipient.firstName} {recipient.lastName}</p>
</div>
</div>)
})}
</div>
</div>
{/* Send */}
{!isPreview && <>
<div
id='send-sign-dash-btn'
onClick={() => setConfirmSendModalOpen({ open: true, confirm: false, loading: false })}
className='flex items-center gap-2 cursor-pointer text-xs px-4 py-2 ml-3 rounded-sm bg-[var(--primary)]'>
<p className='tracking-wide text-white'>
{transactionTemplateToggle == TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES ? "Save" : "Send"}
</p>
<FaSignature className='text-white text-md' />
</div>
{/* {transactionTemplateToggle != TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES && selfUserSign.sign && <div
id='send-and-sign-dash-btn'
onClick={() => handleSend(selfUserSign.sign)}
className='flex items-center gap-2 cursor-pointer text-xs px-4 py-2 ml-3 rounded-sm bg-[var(--primary)]'>
<p className='tracking-wide text-white'>
Sign & Send
</p>
<FaSignature className='text-white text-md' />
</div>} */}
</>}
{editRecipientsModal && accountId && transactionId && <>
<div className="w-full h-[100vh] absolute top-0 left-0 z-[1000] flex justify-center items-center">
{/* <div className="w-full h-full bg-slate-100 opacity-40 blur-2xl absolute top-0 left-0"></div> */}
<div className="fixed inset-0 bg-black/40 backdrop-blur-sm z-50" />
<div className="z-50 bg-white p-4 rounded-sm shadow-md">
<RecipientsCon
transactionTemplateToggle={transactionTemplateToggle}
accountId={accountId}
transactionId={transactionId}
userData={userDetails}
setEditRecipientsModal={setEditRecipientsModal}
/>
</div>
</div>
</>}
{messageModal && accountId && transactionId && <>
<div className="w-full h-[100vh] absolute top-0 left-0 z-[1000] flex justify-center items-center">
{/* <div className="w-full h-full bg-slate-100 opacity-40 blur-2xl absolute top-0 left-0"></div> */}
<div className="fixed inset-0 bg-black/40 backdrop-blur-sm z-50" />
<div className="z-50 bg-white p-4 rounded-sm shadow-md">
<MessageCon
transactionTemplateToggle={transactionTemplateToggle}
accountId={accountId}
transactionId={transactionId}
messageModal={messageModal}
setMessageModal={setMessageModal}
/>
</div>
</div>
</>}
</div>
{/* Right Side - ENDS */}
</div>
{/* Nav Two - Oprions - End */}
</>
)
}
export default NavTwo