353 lines
15 KiB
TypeScript
353 lines
15 KiB
TypeScript
import React, { useEffect, useState } from 'react'
|
|
|
|
import { useDispatch, useSelector } from 'react-redux'
|
|
import { RootState } from '../../../store/store'
|
|
|
|
import { FaCheck, FaSignature } from 'react-icons/fa'
|
|
import { IoIosDocument } from 'react-icons/io'
|
|
import { LuTableOfContents } from 'react-icons/lu'
|
|
import { MdKeyboardArrowDown } from 'react-icons/md'
|
|
import { RiResetRightLine } from 'react-icons/ri'
|
|
import { fetchRecipients, toggleToTemplates, TRANSACTION_TEMPLATE_TOGGLE } from '../../../store/slices/selectedRecipientsSlice'
|
|
import { fetchDocuments } from '../../../store/slices/documentSlice'
|
|
import { useNavigate, useParams } from 'react-router-dom'
|
|
import { Bounce, toast } from 'react-toastify'
|
|
|
|
interface NavTwoProps {
|
|
transactionSaving: boolean;
|
|
// setTransactionSaving: React.Dispatch<React.SetStateAction<boolean>>
|
|
isFields: boolean;
|
|
setIsFields: React.Dispatch<React.SetStateAction<boolean>>
|
|
isSend: boolean | null;
|
|
setIsSend: React.Dispatch<React.SetStateAction<boolean | null>>
|
|
}
|
|
|
|
|
|
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, isFields, setIsFields, isSend, setIsSend }) => {
|
|
let transactionTemplateToggle = TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS;
|
|
const dispatch = useDispatch();
|
|
const params = useParams<{ accountId?: string; transactionId?: string; templateId?: string }>();
|
|
const 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;
|
|
}
|
|
|
|
|
|
// const [transactionSaving, setTransactionSaving] = useState<boolean>(false);
|
|
const [dotCount, setDotCount] = useState(0);
|
|
|
|
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
|
|
};
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
if (userEmailPresent.present && userEmailPresent.routingOrder === minRoutingOrder) {
|
|
setSelfUserSign({ sign: true, recipientId: userEmailPresent.recipientId })
|
|
}
|
|
}
|
|
}, [selectedRecipients])
|
|
|
|
const [nav2RecToggle, setNav2RecToggle] = useState<boolean>(false);
|
|
const [nav2DocToggle, setNav2DocToggle] = useState<boolean>(false);
|
|
|
|
function handleSend(isSignSend: boolean = false) {
|
|
// dispatch(showLoader("Loading ..."));
|
|
if (isSend === null) {
|
|
setIsSend(false);
|
|
}
|
|
setIsSend(!isSend);
|
|
|
|
setTimeout(() => {
|
|
if (transactionTemplateToggle === TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS) {
|
|
if (isSignSend) {
|
|
// navigate(`./../../../sign/${selfUserSign.recipientId}`,{ replace: true });
|
|
}
|
|
else {
|
|
// navigate(`/document-completion-screen/${accountId}/${transactionId}`, { replace: true })
|
|
}
|
|
} else {
|
|
navigate(`/templates`);
|
|
toast.success("Template Saved...!", {
|
|
position: "top-center",
|
|
autoClose: 1500,
|
|
hideProgressBar: false,
|
|
closeOnClick: false,
|
|
pauseOnHover: true,
|
|
draggable: true,
|
|
progress: undefined,
|
|
theme: "light",
|
|
transition: Bounce,
|
|
});
|
|
}
|
|
}, 1000)
|
|
}
|
|
|
|
const handleSetIsFields = (setTo: boolean) => {
|
|
if (setTo !== isFields) setIsFields(setTo);
|
|
}
|
|
|
|
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(() => {
|
|
// let timeoutId: number;
|
|
// const timeOutIn = 8000;
|
|
|
|
// const updateLabel = () => {
|
|
// if (document.visibilityState === 'visible') {
|
|
// setTransactionSaving(true);
|
|
// setTimeout(() => {
|
|
// setTransactionSaving(false);
|
|
// }, 4000)
|
|
// }
|
|
// timeoutId = setTimeout(updateLabel, timeOutIn);
|
|
// };
|
|
// timeoutId = setTimeout(updateLabel, timeOutIn);
|
|
|
|
// // Cleanup on unmount
|
|
// return () => clearTimeout(timeoutId);
|
|
// }, []);
|
|
|
|
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 (
|
|
<>
|
|
|
|
{/* Nav Two - Oprions - START */}
|
|
<div className='flex justify-between items-center px-4 py-1 bg-white'>
|
|
|
|
{/* Left Side */}
|
|
<div className='flex justify-start items-center gap-2'>
|
|
|
|
<div
|
|
onClick={() => handleSetIsFields(true)}
|
|
className={`flex items-center gap-1 cursor-pointer text-xs px-2 py-1 rounded-sm ${isFields ? 'bg-slate-100' : ''}`}>
|
|
<LuTableOfContents />
|
|
<p className='tracking-wide'>Fields</p>
|
|
</div>
|
|
|
|
<div
|
|
onClick={() => handleSetIsFields(false)}
|
|
className={`flex items-center gap-1 cursor-pointer text-xs px-2 py-1 rounded-sm ${!isFields ? 'bg-slate-100' : ''}`}>
|
|
<IoIosDocument />
|
|
<p className='tracking-wide'>Pages</p>
|
|
</div>
|
|
|
|
{/* <div className='flex items-center gap-1 cursor-pointer text-xs px-2 py-1 rounded-sm'>
|
|
<RiResetLeftLine />
|
|
<p className='tracking-wide'>Reset</p>
|
|
</div> */}
|
|
|
|
{/* <div className='flex items-center gap-1 cursor-pointer text-xs px-2 py-1 rounded-sm'>
|
|
<p className='tracking-wide'>Fit</p>
|
|
<MdKeyboardArrowDown />
|
|
</div> */}
|
|
|
|
<div
|
|
tabIndex={1}
|
|
onBlur={() => setIsFitDd(false)}
|
|
>
|
|
<div
|
|
onClick={() => setIsFitDd(!isFitDd)}
|
|
className='flex items-center gap-1 cursor-pointer text-xs px-2 py-1 rounded-sm'>
|
|
<p className='tracking-wide'>Fit</p>
|
|
<MdKeyboardArrowDown style={{ transform: `${isFitDd ? "rotate(180deg)" : ""}` }} />
|
|
</div>
|
|
|
|
{isFitDd && <div className='absolute bg-white rounded-sm z-50'>
|
|
{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 className='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'>
|
|
|
|
{/* Documnt Nav */}
|
|
<div 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='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-[12ch]'>{recipient.firstName} {recipient.lastName}</p>
|
|
</div>
|
|
</div>)
|
|
})}
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{/* Send */}
|
|
<div
|
|
id='send-sign-dash-btn'
|
|
onClick={() => handleSend()}
|
|
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>}
|
|
|
|
|
|
|
|
</div>
|
|
{/* Right Side - ENDS */}
|
|
</div >
|
|
{/* Nav Two - Oprions - End */}
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default NavTwo |