zoom fix + tag placement fix for process step two + expand and collapse tag
This commit is contained in:
parent
6efe737e50
commit
68c45678a3
|
|
@ -142,6 +142,22 @@ const fitObj = [
|
||||||
label: "200%",
|
label: "200%",
|
||||||
value: "200"
|
value: "200"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "250%",
|
||||||
|
value: "250"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "300%",
|
||||||
|
value: "300"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "350%",
|
||||||
|
value: "350"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "400%",
|
||||||
|
value: "400"
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
enum RightSideNav {
|
enum RightSideNav {
|
||||||
|
|
@ -150,6 +166,7 @@ enum RightSideNav {
|
||||||
}
|
}
|
||||||
|
|
||||||
const SignDocument = () => {
|
const SignDocument = () => {
|
||||||
|
|
||||||
const windowWidth = window.innerWidth;
|
const windowWidth = window.innerWidth;
|
||||||
const { recipientId } = useParams();
|
const { recipientId } = useParams();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
@ -158,6 +175,9 @@ const SignDocument = () => {
|
||||||
|
|
||||||
// Signer data - START
|
// Signer data - START
|
||||||
const [selectedDocuments, setSelectedDocuments] = useState<DocumentType[] | null>(null);
|
const [selectedDocuments, setSelectedDocuments] = useState<DocumentType[] | null>(null);
|
||||||
|
|
||||||
|
const [imageSizes, setImageSizes] = useState<Record<string, { width: number; height: number }>>({});
|
||||||
|
|
||||||
const [selectedTag, setSelectedTag] = useState<{ key: string, index: number } | null>(null);
|
const [selectedTag, setSelectedTag] = useState<{ key: string, index: number } | null>(null);
|
||||||
const [isPages, setIsPages] = useState<boolean>(true);
|
const [isPages, setIsPages] = useState<boolean>(true);
|
||||||
|
|
||||||
|
|
@ -167,7 +187,7 @@ const SignDocument = () => {
|
||||||
const [recSignStatus, setRecSignStatus] = useState<string | null>(null);
|
const [recSignStatus, setRecSignStatus] = useState<string | null>(null);
|
||||||
|
|
||||||
const [droppedItems, setDroppedItems] = useState<DroppedItem[]>([]);
|
const [droppedItems, setDroppedItems] = useState<DroppedItem[]>([]);
|
||||||
|
|
||||||
const [signTagId, setSignTagId] = useState<number>(0)
|
const [signTagId, setSignTagId] = useState<number>(0)
|
||||||
const [showConfetti, setShowConfetti] = useState<boolean>(false)
|
const [showConfetti, setShowConfetti] = useState<boolean>(false)
|
||||||
|
|
||||||
|
|
@ -208,6 +228,55 @@ const SignDocument = () => {
|
||||||
const [provideTags, setProvideTags] = useState(false)
|
const [provideTags, setProvideTags] = useState(false)
|
||||||
const [showCompletionScreen, setShowCompletionScreen] = useState(false)
|
const [showCompletionScreen, setShowCompletionScreen] = useState(false)
|
||||||
|
|
||||||
|
const [zoomScale, setZoomScale] = useState<number>(100)
|
||||||
|
const scaleFactor: number = (zoomScale ?? 100) / 100;
|
||||||
|
|
||||||
|
// To center the container on every zoom scale change - START
|
||||||
|
useEffect(() => {
|
||||||
|
const container = document.getElementById("doc-con");
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
const prevScrollRatio = container.scrollTop / (container.scrollHeight || 1);
|
||||||
|
|
||||||
|
const newScrollTop = prevScrollRatio * container.scrollHeight;
|
||||||
|
const newScrollLeft = (container.scrollWidth - container.clientWidth) / 2;
|
||||||
|
|
||||||
|
container.scrollTo({
|
||||||
|
top: newScrollTop,
|
||||||
|
left: newScrollLeft,
|
||||||
|
behavior: "instant" as ScrollBehavior
|
||||||
|
});
|
||||||
|
}, [zoomScale]);
|
||||||
|
// To center the container on every zoom scale change - END
|
||||||
|
|
||||||
|
// Handle Tags and Image Size - START
|
||||||
|
useEffect(() => {
|
||||||
|
const observers: ResizeObserver[] = [];
|
||||||
|
|
||||||
|
Object.keys(imageRefs.current).forEach((key) => {
|
||||||
|
const el = imageRefs.current[key];
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
const observer = new ResizeObserver((entries) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
const { width, height } = entry.contentRect;
|
||||||
|
setImageSizes((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[key]: { width, height },
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(el);
|
||||||
|
observers.push(observer);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => observers.forEach((o) => o.disconnect());
|
||||||
|
|
||||||
|
}, [selectedDocuments]); // re-run when documents load
|
||||||
|
// Handle Tags anf Image Size = END
|
||||||
|
|
||||||
|
|
||||||
const [saved, setSaved] = useState<SaveType>({
|
const [saved, setSaved] = useState<SaveType>({
|
||||||
signatureId: null,
|
signatureId: null,
|
||||||
saveType: null,
|
saveType: null,
|
||||||
|
|
@ -229,25 +298,31 @@ const SignDocument = () => {
|
||||||
|
|
||||||
const [signConfObj, setSignConfObj] = useState<SignConfTypeObj | {}>({});
|
const [signConfObj, setSignConfObj] = useState<SignConfTypeObj | {}>({});
|
||||||
|
|
||||||
|
const handleFitSelect = (indx: number) => {
|
||||||
const zoom = (percentage: number, contentClass: string) => {
|
setSelFitIndx(indx);
|
||||||
const content = document.querySelector(`.${contentClass}`);
|
let value = fitObj[indx].value;
|
||||||
if (content) {
|
if (value === "FIT") value = "100";
|
||||||
(content as HTMLElement).style.zoom = `${percentage}%`;
|
setZoomScale?.(Number(value));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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])
|
||||||
|
|
||||||
const handleTagClick = (key: string, index: number) => {
|
const handleTagClick = (key: string, index: number) => {
|
||||||
setSelectedTag({ key, index })
|
setSelectedTag({ key, index })
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let indx = fitObj[selFitIndx].value
|
|
||||||
if (indx == "FIT") {
|
|
||||||
indx = "100";
|
|
||||||
}
|
|
||||||
zoom(Number(indx), 'zoom-con')
|
|
||||||
}, [selFitIndx])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(showLoader("Loading ..."));
|
dispatch(showLoader("Loading ..."));
|
||||||
|
|
@ -894,7 +969,8 @@ const SignDocument = () => {
|
||||||
{fitObj.map((val, indx) => {
|
{fitObj.map((val, indx) => {
|
||||||
return (<div
|
return (<div
|
||||||
key={indx}
|
key={indx}
|
||||||
onClick={() => setSelFitIndx(indx)}
|
// onClick={() => setSelFitIndx(indx)}
|
||||||
|
onClick={() => handleFitSelect(indx)}
|
||||||
className='flex z-50 items-center justify-between gap-2 w-[70px] p-2 text-xs cursor-default hover:bg-slate-100'>
|
className='flex z-50 items-center justify-between gap-2 w-[70px] p-2 text-xs cursor-default hover:bg-slate-100'>
|
||||||
<div
|
<div
|
||||||
|
|
||||||
|
|
@ -1087,139 +1163,168 @@ const SignDocument = () => {
|
||||||
id="doc-con"
|
id="doc-con"
|
||||||
className={`zoom-con relative ${provideTags ? (isFields && selectedTag != null ? "col-span-8" : "col-span-10") : (isFields ? "col-span-12" : "col-span-10")} sm:px-4 bg-slate-100 h-full w-full overflow-auto scroll-smooth transition-all duration-200 pb-[4rem]`}
|
className={`zoom-con relative ${provideTags ? (isFields && selectedTag != null ? "col-span-8" : "col-span-10") : (isFields ? "col-span-12" : "col-span-10")} sm:px-4 bg-slate-100 h-full w-full overflow-auto scroll-smooth transition-all duration-200 pb-[4rem]`}
|
||||||
>
|
>
|
||||||
{
|
|
||||||
selectedDocuments && selectedDocuments.length > 0 && selectedDocuments.map((doc) => {
|
|
||||||
return (
|
|
||||||
<div key={doc.documentId} className='flex flex-col'>
|
|
||||||
<div className='py-2 text-sm'>
|
|
||||||
<p className='text-center'>{doc.name}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='flex flex-col gap-3 max-w-max relative left-[50%] translate-x-[-50%]'>
|
|
||||||
{
|
|
||||||
doc.pages && doc.pages.length > 0 && doc.pages.map((page, indx) => {
|
|
||||||
const key = `${doc.documentId}_${page.index}`;
|
|
||||||
// const tagJsonData = [...droppedItems];
|
|
||||||
const currDocTags = droppedItems
|
|
||||||
.map((val, index) => ({ ...val, originalIndex: index })) // add original index
|
|
||||||
.filter(val => val.pageIndex === page.index);
|
|
||||||
let scale: { x: number | null, y: number | null } = { x: null, y: null }
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={indx}
|
|
||||||
id={doc.documentId + indx}
|
|
||||||
onDrop={(e) => handleDrop(e, doc.documentId, doc.documentId, page.index)}
|
|
||||||
onDragOver={(e) => handleDragOver(e)}
|
|
||||||
className='drop-page-in shadow-md relative'
|
|
||||||
>
|
|
||||||
|
|
||||||
<img
|
|
||||||
// style={{ "minWidth": page.width, "minHeight": page.height, "maxWidth": page.width, "maxHeight": page.height }}
|
|
||||||
id={`${doc.documentId}-${page.index}`}
|
|
||||||
// style={{ "width": page.width, "height": page.height, "maxWidth": "100%", "maxHeight": "100%" }}
|
|
||||||
className={`w-[${page.width / 2}px] h-[${page.height / 2}px] sm:w-[${page.width}px] sm:h-[${page.height}px]`}
|
|
||||||
ref={(el) => (imageRefs.current[page.index] = el)}
|
|
||||||
draggable="false"
|
|
||||||
// onLoad={(imgElem) => {
|
|
||||||
// setPageScales((prev) => ({
|
|
||||||
// ...prev,
|
|
||||||
// [page.index]: {
|
|
||||||
// x: imgElem.clientWidth / page.width,
|
|
||||||
// y: imgElem.clientHeight / page.height,
|
|
||||||
// },
|
|
||||||
// }));
|
|
||||||
// }}
|
|
||||||
width={page.width}
|
|
||||||
height={page.height}
|
|
||||||
src={page.src}
|
|
||||||
loading='lazy'
|
|
||||||
/>
|
|
||||||
|
|
||||||
{!hideTags && <>
|
|
||||||
<TagsCon
|
|
||||||
pageWidth={page.width}
|
|
||||||
pageHeight={page.height}
|
|
||||||
renderedWidth={imageRefs.current[page.index]?.offsetWidth || 0}
|
|
||||||
renderedHeight={imageRefs.current[page.index]?.offsetHeight || 0}
|
|
||||||
currDocTags={currDocTags}
|
|
||||||
pageIdkey={key}
|
|
||||||
provideTags={provideTags}
|
|
||||||
documentId={doc.documentId}
|
|
||||||
pageIndex={page.index}
|
|
||||||
hideTags={hideTags}
|
|
||||||
transparentTags={transparentTags}
|
|
||||||
focusElement={focusElement}
|
|
||||||
selectedTag={selectedTag}
|
|
||||||
droppedItems={droppedItems}
|
|
||||||
saved={saved}
|
|
||||||
signConfObj={signConfObj}
|
|
||||||
recipientId={recipientId as string}
|
|
||||||
setSaved={setSaved}
|
|
||||||
setStamp={setStamp}
|
|
||||||
setSignConfObj={setSignConfObj}
|
|
||||||
setOpenSign={setOpenSign}
|
|
||||||
setSignTagId={setSignTagId}
|
|
||||||
setDroppedItems={setDroppedItems}
|
|
||||||
setSelectedTag={setSelectedTag}
|
|
||||||
setFocusElement={setFocusElement}
|
|
||||||
handleTagNavClick={handleTagNavClick}
|
|
||||||
/>
|
|
||||||
</>}
|
|
||||||
|
|
||||||
{/* Side details of documents Pages and document Name - START */}
|
|
||||||
< p className='hidden sm:block absolute top-[50%] translate-y-[-50%] rotate-[-90deg] text-xs left-[-50px] text-slate-600' >
|
|
||||||
page {indx + 1} of {doc.pages && doc.pages.length}
|
|
||||||
</p>
|
|
||||||
{/* Side details of documents Pages and document Name - END */}
|
|
||||||
|
|
||||||
|
|
||||||
{!transparentTags && focusElement != null && focusElement && Object.keys(focusElement).length > 1 && focusElement.documentId == doc.documentId && focusElement.pageIndex == page.index &&
|
<div style={{
|
||||||
|
width: `${100 * scaleFactor}%`, // ← outer wrapper grows to make room
|
||||||
|
height: `${100 * scaleFactor}%`,
|
||||||
|
}}>
|
||||||
|
<div className="zoom-con"
|
||||||
|
style={{
|
||||||
|
transform: `scale(${scaleFactor})`,
|
||||||
|
transformOrigin: 'top left', // ← change to top left
|
||||||
|
width: `${100 / scaleFactor}%`,
|
||||||
|
height: scaleFactor < 1
|
||||||
|
? `${100 / scaleFactor}%` // zoomed out — expand to fill
|
||||||
|
: 'auto', // zoomed in — let content grow
|
||||||
|
}}>
|
||||||
|
|
||||||
|
{
|
||||||
|
selectedDocuments && selectedDocuments.length > 0 && selectedDocuments.map((doc) => {
|
||||||
|
return (
|
||||||
|
<div key={doc.documentId} className='flex flex-col'>
|
||||||
|
<div className='py-2 text-sm'>
|
||||||
|
<p className='text-center'>{doc.name}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex flex-col gap-3 max-w-max relative left-[50%] translate-x-[-50%]'>
|
||||||
|
{
|
||||||
|
doc.pages && doc.pages.length > 0 && doc.pages.map((page, indx) => {
|
||||||
|
const key = `${doc.documentId}_${page.index}`;
|
||||||
|
// const tagJsonData = [...droppedItems];
|
||||||
|
const currDocTags = droppedItems
|
||||||
|
.map((val, index) => ({ ...val, originalIndex: index })) // add original index
|
||||||
|
.filter(val => val.pageIndex === page.index);
|
||||||
|
let scale: { x: number | null, y: number | null } = { x: null, y: null }
|
||||||
|
return (
|
||||||
<div
|
<div
|
||||||
id="tag-navigation-btn"
|
key={indx}
|
||||||
className={`hidden absolute right-0 translate-x-[100%] sm:flex justify-center gap-0 items-center z-50 cursor-pointer transition-all duration-300`}
|
id={doc.documentId + indx}
|
||||||
style={{ top: (focusElement.dimensions.top) + "px" }}
|
onDrop={(e) => handleDrop(e, doc.documentId, doc.documentId, page.index)}
|
||||||
onClick={() => handleTagNavClick("N")}
|
onDragOver={(e) => handleDragOver(e)}
|
||||||
|
className='drop-page-in shadow-md relative'
|
||||||
>
|
>
|
||||||
|
|
||||||
<svg width="100" height="35" viewBox="0 0 112 45" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<img
|
||||||
<path d="M1.87927 20.8542L15.0554 2.53357C15.7668 1.54438 16.9108 0.958008 18.1292 0.958008H108.049C110.14 0.958008 111.835 2.65317 111.835 4.74426V41.0235C111.835 43.1146 110.14 44.8098 108.049 44.8098H18.1084C16.9016 44.8098 15.7671 44.2345 15.054 43.261L1.89871 25.3024C0.930133 23.9802 0.92229 22.1849 1.87927 20.8542Z" fill="#005AB5" />
|
// style={{ "minWidth": page.width, "minHeight": page.height, "maxWidth": page.width, "maxHeight": page.height }}
|
||||||
{/* <path d="M53.2649 16.7474V28.3838H51.3899L45.907 20.4577H45.8104V28.3838H43.7024V16.7474H45.5888L51.0661 24.6792H51.1683V16.7474H53.2649ZM58.8545 28.5542C57.9795 28.5542 57.2238 28.3724 56.5875 28.0088C55.9549 27.6414 55.4682 27.1224 55.1272 26.452C54.7863 25.7777 54.6159 24.9842 54.6159 24.0713C54.6159 23.1736 54.7863 22.3857 55.1272 21.7077C55.4719 21.0258 55.953 20.4955 56.5704 20.1167C57.1879 19.7342 57.9132 19.5429 58.7466 19.5429C59.2844 19.5429 59.792 19.63 60.2693 19.8042C60.7504 19.9747 61.1746 20.2398 61.542 20.5997C61.9132 20.9595 62.2049 21.4179 62.417 21.9747C62.6291 22.5277 62.7352 23.1868 62.7352 23.952V24.5827H55.5818V23.1963H60.7636C60.7598 22.8023 60.6746 22.452 60.5079 22.1452C60.3413 21.8345 60.1083 21.5902 59.8091 21.4122C59.5136 21.2342 59.1689 21.1452 58.775 21.1452C58.3545 21.1452 57.9852 21.2474 57.667 21.452C57.3488 21.6527 57.1007 21.9179 56.9227 22.2474C56.7485 22.5732 56.6594 22.9311 56.6557 23.3213V24.5315C56.6557 25.0391 56.7485 25.4747 56.9341 25.8383C57.1197 26.1982 57.3791 26.4747 57.7125 26.6679C58.0458 26.8573 58.436 26.952 58.8829 26.952C59.1822 26.952 59.453 26.9103 59.6954 26.827C59.9379 26.7398 60.1481 26.613 60.3261 26.4463C60.5041 26.2796 60.6386 26.0732 60.7295 25.827L62.65 26.0429C62.5288 26.5505 62.2977 26.9936 61.9568 27.3724C61.6197 27.7474 61.1879 28.0391 60.6613 28.2474C60.1348 28.452 59.5325 28.5542 58.8545 28.5542ZM65.4896 19.6565L67.2509 22.8781L69.0407 19.6565H71.2168L68.5862 24.0202L71.2623 28.3838H69.0975L67.2509 25.2417L65.4214 28.3838H63.2396L65.8987 24.0202L63.3078 19.6565H65.4896ZM76.6857 19.6565V21.2474H71.6687V19.6565H76.6857ZM72.9073 17.5656H74.9641V25.7588C74.9641 26.0353 75.0058 26.2474 75.0891 26.3952C75.1762 26.5391 75.2899 26.6376 75.43 26.6906C75.5702 26.7436 75.7255 26.7702 75.8959 26.7702C76.0247 26.7702 76.1421 26.7607 76.2482 26.7417C76.3581 26.7228 76.4414 26.7058 76.4982 26.6906L76.8448 28.2986C76.735 28.3364 76.5778 28.3781 76.3732 28.4236C76.1725 28.469 75.9262 28.4955 75.6346 28.5031C75.1194 28.5183 74.6554 28.4406 74.2425 28.2702C73.8296 28.0959 73.502 27.827 73.2596 27.4633C73.0209 27.0997 72.9035 26.6452 72.9073 26.0997V17.5656Z" fill="white" /> */}
|
id={`${doc.documentId}-${page.index}`}
|
||||||
|
// style={{ "width": page.width, "height": page.height, "maxWidth": "100%", "maxHeight": "100%" }}
|
||||||
|
className={`w-[${page.width / 2}px] h-[${page.height / 2}px] sm:w-[${page.width}px] sm:h-[${page.height}px]`}
|
||||||
|
ref={(el) => (imageRefs.current[page.index] = el)}
|
||||||
|
onLoad={(e) => {
|
||||||
|
const el = e.currentTarget;
|
||||||
|
setImageSizes((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[page.index]: {
|
||||||
|
width: el.offsetWidth,
|
||||||
|
height: el.offsetHeight,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
draggable="false"
|
||||||
|
// onLoad={(imgElem) => {
|
||||||
|
// setPageScales((prev) => ({
|
||||||
|
// ...prev,
|
||||||
|
// [page.index]: {
|
||||||
|
// x: imgElem.clientWidth / page.width,
|
||||||
|
// y: imgElem.clientHeight / page.height,
|
||||||
|
// },
|
||||||
|
// }));
|
||||||
|
// }}
|
||||||
|
width={page.width}
|
||||||
|
height={page.height}
|
||||||
|
src={page.src}
|
||||||
|
loading='lazy'
|
||||||
|
/>
|
||||||
|
|
||||||
<text className="font-semibold capitalize" x="55%" y="54%" fill="white" font-size="14" font-family="Arial, sans-serif" dominant-baseline="middle" text-anchor="middle">
|
{!hideTags && <>
|
||||||
{requiredFilled && focusElement.required == true ? "Submit" : focusElement.type.toLowerCase()}
|
<TagsCon
|
||||||
</text>
|
zoomScale={zoomScale}
|
||||||
</svg>
|
pageWidth={page.width}
|
||||||
|
pageHeight={page.height}
|
||||||
|
renderedWidth={imageSizes[page.index]?.width || imageRefs.current[page.index]?.offsetWidth || 0}
|
||||||
|
renderedHeight={imageSizes[page.index]?.height || imageRefs.current[page.index]?.offsetHeight || 0}
|
||||||
|
currDocTags={currDocTags}
|
||||||
|
pageIdkey={key}
|
||||||
|
provideTags={provideTags}
|
||||||
|
documentId={doc.documentId}
|
||||||
|
pageIndex={page.index}
|
||||||
|
hideTags={hideTags}
|
||||||
|
transparentTags={transparentTags}
|
||||||
|
focusElement={focusElement}
|
||||||
|
selectedTag={selectedTag}
|
||||||
|
droppedItems={droppedItems}
|
||||||
|
saved={saved}
|
||||||
|
signConfObj={signConfObj}
|
||||||
|
recipientId={recipientId as string}
|
||||||
|
setSaved={setSaved}
|
||||||
|
setStamp={setStamp}
|
||||||
|
setSignConfObj={setSignConfObj}
|
||||||
|
setOpenSign={setOpenSign}
|
||||||
|
setSignTagId={setSignTagId}
|
||||||
|
setDroppedItems={setDroppedItems}
|
||||||
|
setSelectedTag={setSelectedTag}
|
||||||
|
setFocusElement={setFocusElement}
|
||||||
|
handleTagNavClick={handleTagNavClick}
|
||||||
|
/>
|
||||||
|
</>}
|
||||||
|
|
||||||
{/* NEXT Button - END */}
|
{/* Side details of documents Pages and document Name - START */}
|
||||||
</div>}
|
< p className='hidden sm:block absolute top-[50%] translate-y-[-50%] rotate-[-90deg] text-xs left-[-50px] text-slate-600' >
|
||||||
</div>
|
page {indx + 1} of {doc.pages && doc.pages.length}
|
||||||
)
|
</p>
|
||||||
})
|
{/* Side details of documents Pages and document Name - END */}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
{!transparentTags && focusElement != null && focusElement && Object.keys(focusElement).length > 1 && focusElement.documentId == doc.documentId && focusElement.pageIndex == page.index &&
|
||||||
|
<div
|
||||||
|
id="tag-navigation-btn"
|
||||||
|
className={`hidden absolute right-0 translate-x-[100%] sm:flex justify-center gap-0 items-center z-50 cursor-pointer transition-all duration-300`}
|
||||||
|
style={{ top: (focusElement.dimensions.top) + "px" }}
|
||||||
|
onClick={() => handleTagNavClick("N")}
|
||||||
|
>
|
||||||
|
|
||||||
|
<svg width="100" height="35" viewBox="0 0 112 45" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1.87927 20.8542L15.0554 2.53357C15.7668 1.54438 16.9108 0.958008 18.1292 0.958008H108.049C110.14 0.958008 111.835 2.65317 111.835 4.74426V41.0235C111.835 43.1146 110.14 44.8098 108.049 44.8098H18.1084C16.9016 44.8098 15.7671 44.2345 15.054 43.261L1.89871 25.3024C0.930133 23.9802 0.92229 22.1849 1.87927 20.8542Z" fill="#005AB5" />
|
||||||
|
{/* <path d="M53.2649 16.7474V28.3838H51.3899L45.907 20.4577H45.8104V28.3838H43.7024V16.7474H45.5888L51.0661 24.6792H51.1683V16.7474H53.2649ZM58.8545 28.5542C57.9795 28.5542 57.2238 28.3724 56.5875 28.0088C55.9549 27.6414 55.4682 27.1224 55.1272 26.452C54.7863 25.7777 54.6159 24.9842 54.6159 24.0713C54.6159 23.1736 54.7863 22.3857 55.1272 21.7077C55.4719 21.0258 55.953 20.4955 56.5704 20.1167C57.1879 19.7342 57.9132 19.5429 58.7466 19.5429C59.2844 19.5429 59.792 19.63 60.2693 19.8042C60.7504 19.9747 61.1746 20.2398 61.542 20.5997C61.9132 20.9595 62.2049 21.4179 62.417 21.9747C62.6291 22.5277 62.7352 23.1868 62.7352 23.952V24.5827H55.5818V23.1963H60.7636C60.7598 22.8023 60.6746 22.452 60.5079 22.1452C60.3413 21.8345 60.1083 21.5902 59.8091 21.4122C59.5136 21.2342 59.1689 21.1452 58.775 21.1452C58.3545 21.1452 57.9852 21.2474 57.667 21.452C57.3488 21.6527 57.1007 21.9179 56.9227 22.2474C56.7485 22.5732 56.6594 22.9311 56.6557 23.3213V24.5315C56.6557 25.0391 56.7485 25.4747 56.9341 25.8383C57.1197 26.1982 57.3791 26.4747 57.7125 26.6679C58.0458 26.8573 58.436 26.952 58.8829 26.952C59.1822 26.952 59.453 26.9103 59.6954 26.827C59.9379 26.7398 60.1481 26.613 60.3261 26.4463C60.5041 26.2796 60.6386 26.0732 60.7295 25.827L62.65 26.0429C62.5288 26.5505 62.2977 26.9936 61.9568 27.3724C61.6197 27.7474 61.1879 28.0391 60.6613 28.2474C60.1348 28.452 59.5325 28.5542 58.8545 28.5542ZM65.4896 19.6565L67.2509 22.8781L69.0407 19.6565H71.2168L68.5862 24.0202L71.2623 28.3838H69.0975L67.2509 25.2417L65.4214 28.3838H63.2396L65.8987 24.0202L63.3078 19.6565H65.4896ZM76.6857 19.6565V21.2474H71.6687V19.6565H76.6857ZM72.9073 17.5656H74.9641V25.7588C74.9641 26.0353 75.0058 26.2474 75.0891 26.3952C75.1762 26.5391 75.2899 26.6376 75.43 26.6906C75.5702 26.7436 75.7255 26.7702 75.8959 26.7702C76.0247 26.7702 76.1421 26.7607 76.2482 26.7417C76.3581 26.7228 76.4414 26.7058 76.4982 26.6906L76.8448 28.2986C76.735 28.3364 76.5778 28.3781 76.3732 28.4236C76.1725 28.469 75.9262 28.4955 75.6346 28.5031C75.1194 28.5183 74.6554 28.4406 74.2425 28.2702C73.8296 28.0959 73.502 27.827 73.2596 27.4633C73.0209 27.0997 72.9035 26.6452 72.9073 26.0997V17.5656Z" fill="white" /> */}
|
||||||
|
|
||||||
|
<text className="font-semibold capitalize" x="55%" y="54%" fill="white" font-size="14" font-family="Arial, sans-serif" dominant-baseline="middle" text-anchor="middle">
|
||||||
|
{requiredFilled && focusElement.required == true ? "Submit" : focusElement.type.toLowerCase()}
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{/* NEXT Button - END */}
|
||||||
|
</div>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{(navigationTagPos == NavigationTagPosEnum.ABOVE || navigationTagPos == NavigationTagPosEnum.BELOW) &&
|
||||||
|
<div
|
||||||
|
onClick={() => scrollToElement(focusElement?.navigationOrder)}
|
||||||
|
className={`hidden sm:block cursor-pointer fixed ${navigationTagPos == NavigationTagPosEnum.ABOVE ? "top-[45px]" : requiredFilled ? "bottom-[82px]" : "bottom-[35px]"} right-[8%] flex flex-col items-center`}>
|
||||||
|
{/* Arrow pointing up */}
|
||||||
|
{navigationTagPos == NavigationTagPosEnum.ABOVE && <div className="w-0 h-0 border-l-6 border-r-6 border-b-6 border-l-transparent border-r-transparent border-b-[var(--primary)]"></div>}
|
||||||
|
|
||||||
|
{/* Label box */}
|
||||||
|
<div
|
||||||
|
className="bg-[var(--primary)] text-white text-sm px-3 py-1 rounded-md shadow-md flex items-center gap-1">
|
||||||
|
<span className="capitalize">{focusElement?.type.toLowerCase()}</span>
|
||||||
</div>
|
</div>
|
||||||
|
{navigationTagPos == NavigationTagPosEnum.BELOW && <div className="w-0 h-0 border-l-6 border-r-6 border-b-6 border-l-transparent border-r-transparent border-b-[var(--primary)] rotate-[180deg]"></div>}
|
||||||
|
</div>}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
{(navigationTagPos == NavigationTagPosEnum.ABOVE || navigationTagPos == NavigationTagPosEnum.BELOW) &&
|
|
||||||
<div
|
|
||||||
onClick={() => scrollToElement(focusElement?.navigationOrder)}
|
|
||||||
className={`hidden sm:block cursor-pointer fixed ${navigationTagPos == NavigationTagPosEnum.ABOVE ? "top-[45px]" : requiredFilled ? "bottom-[82px]" : "bottom-[35px]"} right-[8%] flex flex-col items-center`}>
|
|
||||||
{/* Arrow pointing up */}
|
|
||||||
{navigationTagPos == NavigationTagPosEnum.ABOVE && <div className="w-0 h-0 border-l-6 border-r-6 border-b-6 border-l-transparent border-r-transparent border-b-[var(--primary)]"></div>}
|
|
||||||
|
|
||||||
{/* Label box */}
|
|
||||||
<div
|
|
||||||
className="bg-[var(--primary)] text-white text-sm px-3 py-1 rounded-md shadow-md flex items-center gap-1">
|
|
||||||
<span className="capitalize">{focusElement?.type.toLowerCase()}</span>
|
|
||||||
</div>
|
|
||||||
{navigationTagPos == NavigationTagPosEnum.BELOW && <div className="w-0 h-0 border-l-6 border-r-6 border-b-6 border-l-transparent border-r-transparent border-b-[var(--primary)] rotate-[180deg]"></div>}
|
|
||||||
</div>}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{provideTags && selectedTag && selectedTag != null && "key" in selectedTag && "index" in selectedTag &&
|
{provideTags && selectedTag && selectedTag != null && "key" in selectedTag && "index" in selectedTag &&
|
||||||
|
|
@ -1247,6 +1352,7 @@ const SignDocument = () => {
|
||||||
<div style={{ display: `${openSign ? 'block' : 'none'}` }}>
|
<div style={{ display: `${openSign ? 'block' : 'none'}` }}>
|
||||||
{recipient &&
|
{recipient &&
|
||||||
<ClientSignCon
|
<ClientSignCon
|
||||||
|
zoomScale={zoomScale}
|
||||||
recipient={recipient}
|
recipient={recipient}
|
||||||
recipientId={recipientId as string}
|
recipientId={recipientId as string}
|
||||||
setOpenSign={setOpenSign} saved={saved}
|
setOpenSign={setOpenSign} saved={saved}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import axios from 'axios';
|
||||||
|
|
||||||
|
|
||||||
interface TagsConProps {
|
interface TagsConProps {
|
||||||
|
zoomScale: number,
|
||||||
pageWidth: number,
|
pageWidth: number,
|
||||||
pageHeight: number,
|
pageHeight: number,
|
||||||
renderedWidth: number,
|
renderedWidth: number,
|
||||||
|
|
@ -43,6 +44,7 @@ interface TagsConProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const TagsCon: React.FC<TagsConProps> = ({
|
const TagsCon: React.FC<TagsConProps> = ({
|
||||||
|
zoomScale,
|
||||||
pageWidth,
|
pageWidth,
|
||||||
pageHeight,
|
pageHeight,
|
||||||
renderedWidth,
|
renderedWidth,
|
||||||
|
|
@ -71,60 +73,76 @@ const TagsCon: React.FC<TagsConProps> = ({
|
||||||
handleTagNavClick
|
handleTagNavClick
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
|
const scaleFactor: number = (zoomScale ?? 100) / 100;
|
||||||
|
|
||||||
const [dateValues, setDateValues] = useState<{ [key: string]: string }>({});
|
const [dateValues, setDateValues] = useState<{ [key: string]: string }>({});
|
||||||
const [isDateOpen, setIsDateOpen] = useState<string | null>(null);
|
const [isDateOpen, setIsDateOpen] = useState<string | null>(null);
|
||||||
|
|
||||||
const handleTagMouseDown = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number) => {
|
const handleTagMouseDown = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number) => {
|
||||||
setSelectedTag({ key, index })
|
setSelectedTag({ key, index });
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
const scale = scaleFactor ?? 1; // zoom factor
|
||||||
|
|
||||||
let targetContainer = event?.currentTarget?.parentElement?.parentElement;
|
let targetContainer = event?.currentTarget?.parentElement?.parentElement;
|
||||||
let targetElement = event?.currentTarget;
|
let targetElement = event?.currentTarget?.parentElement;
|
||||||
|
|
||||||
if (!targetContainer || !targetElement) return;
|
if (!targetContainer || !targetElement) return;
|
||||||
|
|
||||||
const containerRect = targetContainer.getBoundingClientRect();
|
const containerRect = targetContainer.getBoundingClientRect();
|
||||||
const elementRect = targetElement.getBoundingClientRect();
|
const elementRect = targetElement.getBoundingClientRect();
|
||||||
|
|
||||||
// Calculate the initial offset (where the mouse was clicked inside the element)
|
const scaleX = renderedWidth && pageWidth ? renderedWidth / pageWidth : 1;
|
||||||
const offsetX = event.clientX - elementRect.left;
|
const scaleY = renderedHeight && pageHeight ? renderedHeight / pageHeight : 1;
|
||||||
const offsetY = event.clientY - elementRect.top;
|
|
||||||
|
|
||||||
const conScrollWidth = targetContainer?.scrollWidth;
|
// Click offset in screen pixels
|
||||||
const conScrollHeight = targetContainer?.scrollHeight;
|
const clickOffsetX = event.clientX - elementRect.left;
|
||||||
|
const clickOffsetY = event.clientY - elementRect.top;
|
||||||
|
|
||||||
let isGroupAttr = event.currentTarget.hasAttribute("group");
|
let isGroupAttr = event.currentTarget.hasAttribute("group");
|
||||||
let groupId = null;
|
let groupId = null;
|
||||||
if (isGroupAttr) {
|
if (isGroupAttr) groupId = event.currentTarget.getAttribute("group");
|
||||||
groupId = event.currentTarget.getAttribute("group");
|
|
||||||
}
|
|
||||||
|
|
||||||
let groupElements: NodeListOf<HTMLElement> | null = null
|
let groupElements: NodeListOf<HTMLElement> | null = null;
|
||||||
if (isGroupAttr && groupId) {
|
if (isGroupAttr && groupId) {
|
||||||
groupElements = document.querySelectorAll(`div[group="${groupId}"]`);
|
groupElements = document.querySelectorAll(`div[group="${groupId}"]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleMouseMove = (event: MouseEvent) => {
|
const handleMouseMove = (event: MouseEvent) => {
|
||||||
// Get new X and Y positions relative to the container
|
const currentContainerRect = targetContainer!.getBoundingClientRect();
|
||||||
let left = event.clientX - containerRect.left - offsetX;
|
|
||||||
let top = event.clientY - containerRect.top - offsetY;
|
|
||||||
|
|
||||||
|
// Mouse position relative to container in screen pixels
|
||||||
|
const mouseX = event.clientX - currentContainerRect.left;
|
||||||
|
const mouseY = event.clientY - currentContainerRect.top;
|
||||||
|
|
||||||
// **Restrict movement within container bounds**
|
// Convert to rendered pixel space (undo zoom)
|
||||||
left = Math.max(0, Math.min(left, conScrollWidth - elementRect.width));
|
const renderedLeft = (mouseX - clickOffsetX) / scale;
|
||||||
top = Math.max(0, Math.min(top, conScrollHeight - elementRect.height));
|
const renderedTop = (mouseY - clickOffsetY) / scale;
|
||||||
|
|
||||||
|
// Convert to original coord space for storage
|
||||||
|
const originalLeft = renderedLeft / scaleX;
|
||||||
|
const originalTop = renderedTop / scaleY;
|
||||||
|
|
||||||
if (groupElements != null && groupElements.length) handleGroupBorderPosition(groupElements, containerRect, offsetX, offsetY);
|
if (groupElements != null && groupElements.length) {
|
||||||
|
handleGroupBorderPosition(groupElements, currentContainerRect, clickOffsetX, clickOffsetY);
|
||||||
|
}
|
||||||
|
|
||||||
// Apply the movement to the element
|
// Update state in original coord space
|
||||||
setDroppedItems(
|
setDroppedItems(
|
||||||
droppedItems.map((item, i) =>
|
droppedItems.map((item, i) =>
|
||||||
i == index ? { ...item, dimensions: { ...item.dimensions, left, top }, update: true } : item
|
i === index
|
||||||
|
? {
|
||||||
|
...item,
|
||||||
|
dimensions: {
|
||||||
|
...item.dimensions,
|
||||||
|
left: Math.max(0, originalLeft),
|
||||||
|
top: Math.max(0, originalTop),
|
||||||
|
},
|
||||||
|
update: true
|
||||||
|
}
|
||||||
|
: item
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseUp = () => {
|
const handleMouseUp = () => {
|
||||||
|
|
@ -132,7 +150,6 @@ const TagsCon: React.FC<TagsConProps> = ({
|
||||||
document.removeEventListener("pointerup", handleMouseUp);
|
document.removeEventListener("pointerup", handleMouseUp);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add event listeners
|
|
||||||
document.addEventListener("pointermove", handleMouseMove);
|
document.addEventListener("pointermove", handleMouseMove);
|
||||||
document.addEventListener("pointerup", handleMouseUp);
|
document.addEventListener("pointerup", handleMouseUp);
|
||||||
};
|
};
|
||||||
|
|
@ -308,9 +325,6 @@ const TagsCon: React.FC<TagsConProps> = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
console.log(signConfObj, saved, "Line 305")
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{currDocTags.map((item, index) => {
|
{currDocTags.map((item, index) => {
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@ import { hideLoader, showLoader } from '../../../store/slices/loaderSlice';
|
||||||
import DroppedItemsTagsCon from './DroppedItemsTagsCon';
|
import DroppedItemsTagsCon from './DroppedItemsTagsCon';
|
||||||
import DocumentPages from './documentPages/DocumentPages';
|
import DocumentPages from './documentPages/DocumentPages';
|
||||||
import {
|
import {
|
||||||
initializeDroppedItems,
|
initializeDroppedItems,
|
||||||
setDroppedItems,
|
setDroppedItems,
|
||||||
clearTransactionTags,
|
clearTransactionTags,
|
||||||
incrementCounter,
|
incrementCounter,
|
||||||
} from '../../../store/slices/documentTagsSlice';
|
} from '../../../store/slices/documentTagsSlice';
|
||||||
|
|
||||||
export interface DroppedItemsObj {
|
export interface DroppedItemsObj {
|
||||||
|
|
@ -42,6 +42,9 @@ export const droppedTagsDefaultField: DroppedTagsDefaultFieldType = {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DocumentContainerProps {
|
interface DocumentContainerProps {
|
||||||
|
isPages: boolean;
|
||||||
|
setIsPages: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
zoomScale: number;
|
||||||
transactionSaving?: boolean;
|
transactionSaving?: boolean;
|
||||||
setTransactionSaving?: React.Dispatch<React.SetStateAction<boolean>>;
|
setTransactionSaving?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
isSend?: boolean | null;
|
isSend?: boolean | null;
|
||||||
|
|
@ -62,10 +65,11 @@ export interface DocumentContainerRef {
|
||||||
handleTransactionProcess: (isSave?: boolean, isNavigate?: boolean, navigateTo?: string) => void;
|
handleTransactionProcess: (isSave?: boolean, isNavigate?: boolean, navigateTo?: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const DocumentContainer = forwardRef<DocumentContainerRef, DocumentContainerProps>(
|
const DocumentContainer = forwardRef<DocumentContainerRef, DocumentContainerProps>(
|
||||||
({ transactionSaving, setTransactionSaving, isSend, isPreview = false, aId = null, tId = null, selectedRecipientIndx = 0 }, ref) => {
|
({ isPages, zoomScale, transactionSaving, setTransactionSaving, isSend, isPreview = false, aId = null, tId = null, selectedRecipientIndx = 0, setIsPages }, ref) => {
|
||||||
|
|
||||||
|
const scaleFactor: number = (zoomScale ?? 100) / 100;
|
||||||
|
|
||||||
let transactionTemplateToggle = TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS;
|
let transactionTemplateToggle = TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS;
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const params = useParams<{ accountId?: string; transactionId?: string; templateId?: string }>();
|
const params = useParams<{ accountId?: string; transactionId?: string; templateId?: string }>();
|
||||||
|
|
@ -93,12 +97,42 @@ const DocumentContainer = forwardRef<DocumentContainerRef, DocumentContainerProp
|
||||||
const tagUndoRef = useRef<DroppedItem[] | []>([]);
|
const tagUndoRef = useRef<DroppedItem[] | []>([]);
|
||||||
|
|
||||||
const imageRefs = useRef<{ [key: string]: HTMLImageElement | null }>({});
|
const imageRefs = useRef<{ [key: string]: HTMLImageElement | null }>({});
|
||||||
const [imageSizes, setImageSizes] = useState<Record<string, { width: number; height: number }>>({});
|
|
||||||
|
|
||||||
const selectedRecipients = useSelector((state: RootState) => state.selectedRecipients.recipients);
|
const selectedRecipients = useSelector((state: RootState) => state.selectedRecipients.recipients);
|
||||||
// const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments)
|
// const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments)
|
||||||
const selectedDocuments = useSelector((state: RootState) => state.documents.documents)
|
const selectedDocuments = useSelector((state: RootState) => state.documents.documents)
|
||||||
|
|
||||||
|
|
||||||
|
// handle Tag - Document Pos and size for Responsiveness - START
|
||||||
|
const [imageSizes, setImageSizes] = useState<Record<string, { width: number; height: number }>>({});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const observers: ResizeObserver[] = [];
|
||||||
|
|
||||||
|
Object.keys(imageRefs.current).forEach((key) => {
|
||||||
|
const el = imageRefs.current[key];
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
const observer = new ResizeObserver((entries) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
const { width, height } = entry.contentRect;
|
||||||
|
setImageSizes((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[key]: { width, height },
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(el);
|
||||||
|
observers.push(observer);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => observers.forEach((o) => o.disconnect());
|
||||||
|
|
||||||
|
}, [selectedDocuments]);
|
||||||
|
// handle Tag - Document Pos and size for Responsiveness - START
|
||||||
|
|
||||||
// Redux state for dropped items
|
// Redux state for dropped items
|
||||||
const transactionKey = `${accountId}_${transactionId}`;
|
const transactionKey = `${accountId}_${transactionId}`;
|
||||||
const droppedItems = useSelector((state: RootState) => state.documentTags.items[transactionKey] || {});
|
const droppedItems = useSelector((state: RootState) => state.documentTags.items[transactionKey] || {});
|
||||||
|
|
@ -358,8 +392,11 @@ const DocumentContainer = forwardRef<DocumentContainerRef, DocumentContainerProp
|
||||||
clientY = event.clientY;
|
clientY = event.clientY;
|
||||||
}
|
}
|
||||||
|
|
||||||
let x = clientX - dropZone.left - (dragElemData.width / 2);
|
// let x = (clientX - dropZone.left) - (dragElemData.width / 2);
|
||||||
let y = clientY - dropZone.top - (dragElemData.height / 2);
|
// let y = (clientY - dropZone.top) - (dragElemData.height / 2);
|
||||||
|
|
||||||
|
let x = (clientX - dropZone.left) / scaleFactor - (dragElemData.width / 2);
|
||||||
|
let y = (clientY - dropZone.top) / scaleFactor - (dragElemData.height / 2);
|
||||||
|
|
||||||
// Handling Drop Over Right
|
// Handling Drop Over Right
|
||||||
// if (dropZone.width < x + dragElemData.width) {
|
// if (dropZone.width < x + dragElemData.width) {
|
||||||
|
|
@ -378,8 +415,11 @@ const DocumentContainer = forwardRef<DocumentContainerRef, DocumentContainerProp
|
||||||
// y = 0;
|
// y = 0;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
x = Math.max(0, Math.min(x, dropZone.width - dragElemData.width));
|
// x = Math.max(0, Math.min(x, dropZone.width - dragElemData.width));
|
||||||
y = Math.max(0, Math.min(y, dropZone.height - dragElemData.height));
|
// y = Math.max(0, Math.min(y, dropZone.height - dragElemData.height));
|
||||||
|
|
||||||
|
x = Math.max(0, Math.min(x, originalWidth - dragElemData.width));
|
||||||
|
y = Math.max(0, Math.min(y, originalHeight - dragElemData.height));
|
||||||
|
|
||||||
const key = `${docId}_${pageIndex}`;
|
const key = `${docId}_${pageIndex}`;
|
||||||
|
|
||||||
|
|
@ -561,114 +601,128 @@ const DocumentContainer = forwardRef<DocumentContainerRef, DocumentContainerProp
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Center Doc Container - START */}
|
{/* Center Doc Container - START */}
|
||||||
<div id="doc-con" className={`zoom-con col-span-8 bg-slate-100 h-full w-full overflow-auto scroll-smooth`}>
|
<div id="doc-con"
|
||||||
|
className={`sm:col-span-8 bg-slate-100 h-full w-full overflow-auto scroll-smooth`}>
|
||||||
|
<div style={{
|
||||||
|
width: `${100 * scaleFactor}%`, // ← outer wrapper grows to make room
|
||||||
|
height: `${100 * scaleFactor}%`,
|
||||||
|
}}>
|
||||||
|
<div className="zoom-con"
|
||||||
|
style={{
|
||||||
|
transform: `scale(${scaleFactor})`,
|
||||||
|
transformOrigin: 'top left', // ← change to top left
|
||||||
|
width: `${100 / scaleFactor}%`,
|
||||||
|
height: scaleFactor < 1
|
||||||
|
? `${100 / scaleFactor}%` // zoomed out — expand to fill
|
||||||
|
: 'auto', // zoomed in — let content grow
|
||||||
|
}}>
|
||||||
|
{
|
||||||
|
selectedDocuments.length > 0 ? selectedDocuments.map((doc, indxDoc) => {
|
||||||
|
return (
|
||||||
|
<div key={indxDoc} className='flex flex-col overflow-x-auto'>
|
||||||
|
<div
|
||||||
|
className='py-2 text-sm'>
|
||||||
|
<p className='text-center'>{doc.name}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{
|
<div className={`flex flex-col gap-3 max-w-max relative left-[50%] translate-x-[-50%] ${isPreview ? "pointer-events-none" : ""}`}>
|
||||||
selectedDocuments.length > 0 ? selectedDocuments.map((doc, indxDoc) => {
|
{
|
||||||
return (
|
doc.pages && doc.pages.length > 0 && doc.pages.map((page, indx) => {
|
||||||
<div key={indxDoc} className='flex flex-col overflow-x-auto'>
|
const key = `${doc.id}_${page.index}`;
|
||||||
<div
|
return (
|
||||||
className='py-2 text-sm'>
|
<div
|
||||||
<p className='text-center'>{doc.name}</p>
|
tabIndex={-1}
|
||||||
</div>
|
onFocus={() => handleDocumentFocus(key)}
|
||||||
|
key={indx}
|
||||||
|
id={`${doc.id}${indx}`}
|
||||||
|
onDrop={(e) => handleDrop(e, doc.id, indxDoc, page.index, page.width, page.height)}
|
||||||
|
onDragOver={handleDragOver}
|
||||||
|
className='drop-page-in shadow-md relative'
|
||||||
|
style={{ aspectRatio: `${page.width}/${page.height}` }}
|
||||||
|
>
|
||||||
|
|
||||||
<div className={`flex flex-col gap-3 max-w-max relative left-[50%] translate-x-[-50%] ${isPreview ? "pointer-events-none" : ""}`}>
|
<img
|
||||||
{
|
// style={{ "minWidth": page.width, "minHeight": page.height, "maxWidth": page.width, "maxHeight": page.height }}
|
||||||
doc.pages && doc.pages.length > 0 && doc.pages.map((page, indx) => {
|
// style={{ "width": page.width, "height": page.height, "maxWidth": "100%", "maxHeight": "100%" }}
|
||||||
const key = `${doc.id}_${page.index}`;
|
// style={{ "width": "100%", "height": "100%", "maxWidth": "100%", "maxHeight": "100%" }}
|
||||||
return (
|
// className={`w-[${(page.width / 2)}px] h-[${(page.height / 2)}px] sm:w-[${page.width}px] sm:h-[${page.height}px]`}
|
||||||
<div
|
id={`${doc.id}-${page.index}`}
|
||||||
tabIndex={-1}
|
className={`w-[${page.width / 2}px] h-[${page.height / 2}px] sm:w-[${page.width}px] sm:h-[${page.height}px]`}
|
||||||
onFocus={() => handleDocumentFocus(key)}
|
ref={(el) => {
|
||||||
key={indx}
|
const pageRefKey = `${doc.id}_${page.index}`;
|
||||||
id={`${doc.id}${indx}`}
|
imageRefs.current[pageRefKey] = el;
|
||||||
onDrop={(e) => handleDrop(e, doc.id, indxDoc, page.index, page.width, page.height)}
|
}}
|
||||||
onDragOver={handleDragOver}
|
onLoad={(event) => {
|
||||||
className='drop-page-in shadow-md relative'
|
const pageRefKey = `${doc.id}_${page.index}`;
|
||||||
style={{ aspectRatio: `${page.width}/${page.height}` }}
|
const el = event.currentTarget;
|
||||||
>
|
setImageSizes((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[pageRefKey]: {
|
||||||
|
width: el.offsetWidth,
|
||||||
|
height: el.offsetHeight,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
draggable="false"
|
||||||
|
width={page.width}
|
||||||
|
height={page.height}
|
||||||
|
// src={`http://10.10.1.99:8083/api/v1/accounts/${accountId}/transactions/${transactionId}/documents/${doc.id}/pages/${page.id}`}
|
||||||
|
src={page.src}
|
||||||
|
loading='lazy'
|
||||||
|
data-doc-img="true"
|
||||||
|
/>
|
||||||
|
|
||||||
<img
|
<DroppedItemsTagsCon
|
||||||
// style={{ "minWidth": page.width, "minHeight": page.height, "maxWidth": page.width, "maxHeight": page.height }}
|
scaleFactor={scaleFactor}
|
||||||
// style={{ "width": page.width, "height": page.height, "maxWidth": "100%", "maxHeight": "100%" }}
|
pageWidth={page.width}
|
||||||
// style={{ "width": "100%", "height": "100%", "maxWidth": "100%", "maxHeight": "100%" }}
|
pageHeight={page.height}
|
||||||
// className={`w-[${(page.width / 2)}px] h-[${(page.height / 2)}px] sm:w-[${page.width}px] sm:h-[${page.height}px]`}
|
renderedWidth={imageSizes[key]?.width || imageRefs.current[key]?.offsetWidth || 0}
|
||||||
id={`${doc.id}-${page.index}`}
|
renderedHeight={imageSizes[key]?.height || imageRefs.current[key]?.offsetHeight || 0}
|
||||||
className={`w-[${page.width / 2}px] h-[${page.height / 2}px] sm:w-[${page.width}px] sm:h-[${page.height}px]`}
|
ref={childRef}
|
||||||
ref={(el) => {
|
droppedItems={droppedItems}
|
||||||
const pageRefKey = `${doc.id}_${page.index}`;
|
pageIdkey={key}
|
||||||
imageRefs.current[pageRefKey] = el;
|
selectedTag={selectedTag}
|
||||||
}}
|
selectedRecipients={selectedRecipients}
|
||||||
onLoad={(event) => {
|
setSelectedTag={setSelectedTag}
|
||||||
const pageRefKey = `${doc.id}_${page.index}`;
|
setDroppedItems={(updateFn: any) => {
|
||||||
const el = event.currentTarget;
|
const newItems = typeof updateFn === 'function'
|
||||||
setImageSizes((prev) => ({
|
? updateFn(droppedItems)
|
||||||
...prev,
|
: updateFn;
|
||||||
[pageRefKey]: {
|
dispatch(setDroppedItems({
|
||||||
width: el.offsetWidth,
|
transactionKey,
|
||||||
height: el.offsetHeight,
|
items: newItems
|
||||||
},
|
}));
|
||||||
}));
|
}}
|
||||||
}}
|
accountId={accountId}
|
||||||
draggable="false"
|
transactionId={transactionId}
|
||||||
width={page.width}
|
transactionTemplateToggle={transactionTemplateToggle}
|
||||||
height={page.height}
|
tagUndoRef={tagUndoRef}
|
||||||
// src={`http://10.10.1.99:8083/api/v1/accounts/${accountId}/transactions/${transactionId}/documents/${doc.id}/pages/${page.id}`}
|
transactionKey={transactionKey}
|
||||||
src={page.src}
|
/>
|
||||||
loading='lazy'
|
|
||||||
data-doc-img="true"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<DroppedItemsTagsCon
|
{/* Side details of documents Pages and document Name - START */}
|
||||||
pageWidth={page.width}
|
<p className='absolute top-[50%] translate-y-[-50%] rotate-[-90deg] text-xs left-[-60px] text-slate-600'>
|
||||||
pageHeight={page.height}
|
page {indx + 1} of {doc.pages && doc.pages.length}
|
||||||
renderedWidth={imageSizes[key]?.width || imageRefs.current[key]?.offsetWidth || 0}
|
</p>
|
||||||
renderedHeight={imageSizes[key]?.height || imageRefs.current[key]?.offsetHeight || 0}
|
{/* <p className='absolute top-[50%] translate-y-[-50%] rotate-[-90deg] text-xs right-[-140px] text-slate-600'>
|
||||||
ref={childRef}
|
|
||||||
droppedItems={droppedItems}
|
|
||||||
pageIdkey={key}
|
|
||||||
selectedTag={selectedTag}
|
|
||||||
selectedRecipients={selectedRecipients}
|
|
||||||
setSelectedTag={setSelectedTag}
|
|
||||||
setDroppedItems={(updateFn: any) => {
|
|
||||||
const newItems = typeof updateFn === 'function'
|
|
||||||
? updateFn(droppedItems)
|
|
||||||
: updateFn;
|
|
||||||
dispatch(setDroppedItems({
|
|
||||||
transactionKey,
|
|
||||||
items: newItems
|
|
||||||
}));
|
|
||||||
}}
|
|
||||||
accountId={accountId}
|
|
||||||
transactionId={transactionId}
|
|
||||||
transactionTemplateToggle={transactionTemplateToggle}
|
|
||||||
tagUndoRef={tagUndoRef}
|
|
||||||
transactionKey={transactionKey}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Side details of documents Pages and document Name - START */}
|
|
||||||
<p className='absolute top-[50%] translate-y-[-50%] rotate-[-90deg] text-xs left-[-60px] text-slate-600'>
|
|
||||||
page {indx + 1} of {doc.pages && doc.pages.length}
|
|
||||||
</p>
|
|
||||||
{/* <p className='absolute top-[50%] translate-y-[-50%] rotate-[-90deg] text-xs right-[-140px] text-slate-600'>
|
|
||||||
Document {indxDoc + 1} {doc.name}
|
Document {indxDoc + 1} {doc.name}
|
||||||
</p> */}
|
</p> */}
|
||||||
{/* Side details of documents Pages and document Name - END */}
|
{/* Side details of documents Pages and document Name - END */}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}) : <Loader />
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}) : <Loader />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -678,8 +732,8 @@ const DocumentContainer = forwardRef<DocumentContainerRef, DocumentContainerProp
|
||||||
droppedItems={droppedItems}
|
droppedItems={droppedItems}
|
||||||
selectedTag={droppedItems[selectedTag.key][selectedTag.index]}
|
selectedTag={droppedItems[selectedTag.key][selectedTag.index]}
|
||||||
setDroppedItems={(updateFn: any) => {
|
setDroppedItems={(updateFn: any) => {
|
||||||
const newItems = typeof updateFn === 'function'
|
const newItems = typeof updateFn === 'function'
|
||||||
? updateFn(droppedItems)
|
? updateFn(droppedItems)
|
||||||
: updateFn;
|
: updateFn;
|
||||||
dispatch(setDroppedItems({
|
dispatch(setDroppedItems({
|
||||||
transactionKey,
|
transactionKey,
|
||||||
|
|
@ -695,6 +749,8 @@ const DocumentContainer = forwardRef<DocumentContainerRef, DocumentContainerProp
|
||||||
</>
|
</>
|
||||||
|
|
||||||
{selectedDocuments && selectedDocuments.length > 0 && <DocumentPages
|
{selectedDocuments && selectedDocuments.length > 0 && <DocumentPages
|
||||||
|
isPages={isPages}
|
||||||
|
setIsPages={setIsPages}
|
||||||
droppedItems={droppedItems}
|
droppedItems={droppedItems}
|
||||||
/>}
|
/>}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import { DroppedItem } from '../../../utlity/types';
|
||||||
import { setDroppedItems as setDroppedItemsAction } from '../../../store/slices/documentTagsSlice';
|
import { setDroppedItems as setDroppedItemsAction } from '../../../store/slices/documentTagsSlice';
|
||||||
|
|
||||||
interface DroppedItemsTagsConProps {
|
interface DroppedItemsTagsConProps {
|
||||||
|
scaleFactor: number,
|
||||||
pageWidth: number,
|
pageWidth: number,
|
||||||
pageHeight: number,
|
pageHeight: number,
|
||||||
renderedWidth: number,
|
renderedWidth: number,
|
||||||
|
|
@ -41,6 +42,7 @@ interface DroppedItemsTagsConProps {
|
||||||
|
|
||||||
// 👶 Child component with forwardRef
|
// 👶 Child component with forwardRef
|
||||||
const DroppedItemsTagsCon = forwardRef(({
|
const DroppedItemsTagsCon = forwardRef(({
|
||||||
|
scaleFactor,
|
||||||
pageWidth,
|
pageWidth,
|
||||||
pageHeight,
|
pageHeight,
|
||||||
renderedWidth,
|
renderedWidth,
|
||||||
|
|
@ -163,109 +165,85 @@ const DroppedItemsTagsCon = forwardRef(({
|
||||||
handleRemoveTag
|
handleRemoveTag
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// HANDLE TAG MOUSE DOWN - START
|
|
||||||
// Updated handleTagMouseDown function with proper group border positioning
|
|
||||||
const handleTagMouseDown = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number) => {
|
const handleTagMouseDown = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
const scale = scaleFactor ?? 1;
|
||||||
|
const scaleX = renderedWidth && pageWidth ? renderedWidth / pageWidth : 1;
|
||||||
|
const scaleY = renderedHeight && pageHeight ? renderedHeight / pageHeight : 1;
|
||||||
|
|
||||||
|
console.log("=== DRAG DEBUG ===");
|
||||||
|
console.log("scaleFactor (zoom):", scale);
|
||||||
|
console.log("renderedWidth:", renderedWidth, "pageWidth:", pageWidth);
|
||||||
|
console.log("renderedHeight:", renderedHeight, "pageHeight:", pageHeight);
|
||||||
|
console.log("scaleX (render ratio):", scaleX);
|
||||||
|
console.log("scaleY (render ratio):", scaleY);
|
||||||
|
console.log("combined scaleX:", scaleX * scale);
|
||||||
|
console.log("combined scaleY:", scaleY * scale);
|
||||||
|
|
||||||
let targetContainer = event?.currentTarget?.parentElement?.parentElement;
|
let targetContainer = event?.currentTarget?.parentElement?.parentElement;
|
||||||
let targetElement = event?.currentTarget?.parentElement;
|
let targetElement = event?.currentTarget?.parentElement;
|
||||||
|
|
||||||
if (!targetContainer || !targetElement) return;
|
if (!targetContainer || !targetElement) return;
|
||||||
|
|
||||||
const containerRect = targetContainer.getBoundingClientRect();
|
// Get container rect in screen space
|
||||||
|
// const containerRect = targetContainer.getBoundingClientRect();
|
||||||
const elementRect = targetElement.getBoundingClientRect();
|
const elementRect = targetElement.getBoundingClientRect();
|
||||||
|
|
||||||
let clientX = event.clientX
|
const containerRect = targetContainer.getBoundingClientRect();
|
||||||
let clientY = event.clientY
|
|
||||||
|
|
||||||
if ((event as any).changedTouches?.[0]) {
|
console.log("containerRect:", containerRect.left, containerRect.top, containerRect.width, containerRect.height);
|
||||||
clientX = (event as any).changedTouches[0].pageX;
|
console.log("elementRect:", elementRect.left, elementRect.top, elementRect.width, elementRect.height);
|
||||||
clientY = (event as any).changedTouches[0].pageY;
|
console.log("mouse at:", event.clientX, event.clientY);
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the initial offset (where the mouse was clicked inside the element)
|
// Current tag position in original coord space (from state)
|
||||||
const offsetY = event.clientY - elementRect.top;
|
const currentItem = droppedItems[key][index];
|
||||||
const offsetX = event.clientX - elementRect.left;
|
const tagOriginalLeft = currentItem.dimensions.left;
|
||||||
|
const tagOriginalTop = currentItem.dimensions.top;
|
||||||
|
|
||||||
positionRef.current = { left: event.clientX - containerRect.left - offsetX, top: event.clientY - containerRect.top - offsetY };
|
// Tag's top-left in screen space
|
||||||
|
const tagScreenLeft = containerRect.left + tagOriginalLeft * scaleX * scale;
|
||||||
|
const tagScreenTop = containerRect.top + tagOriginalTop * scaleY * scale;
|
||||||
|
|
||||||
const conScrollWidth = targetContainer?.scrollWidth;
|
// Click offset within tag in screen pixels
|
||||||
const conScrollHeight = targetContainer?.scrollHeight;
|
const clickOffsetX = event.clientX - tagScreenLeft;
|
||||||
|
const clickOffsetY = event.clientY - tagScreenTop;
|
||||||
|
|
||||||
let isGroupAttr = event.currentTarget.hasAttribute("group");
|
let isGroupAttr = event.currentTarget.hasAttribute("group");
|
||||||
let groupId = null;
|
let groupId = null;
|
||||||
if (isGroupAttr) {
|
if (isGroupAttr) groupId = event.currentTarget.getAttribute("group");
|
||||||
groupId = event.currentTarget.getAttribute("group");
|
|
||||||
}
|
|
||||||
|
|
||||||
let groupElements: NodeListOf<HTMLElement> | null = null;
|
let groupElements: NodeListOf<HTMLElement> | null = null;
|
||||||
if (isGroupAttr && groupId) {
|
if (isGroupAttr && groupId) {
|
||||||
groupElements = document.querySelectorAll(`div[group="${groupId}"]`);
|
groupElements = document.querySelectorAll(`div[group="${groupId}"]`);
|
||||||
// Show initial border position during drag start
|
handleGroupBorderPosition(groupElements, containerRect, clickOffsetX, clickOffsetY);
|
||||||
handleGroupBorderPosition(groupElements, containerRect, offsetX, offsetY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// let timeOut = null
|
|
||||||
const handleMouseMove = (event: MouseEvent) => {
|
const handleMouseMove = (event: MouseEvent) => {
|
||||||
|
const currentContainerRect = targetContainer!.getBoundingClientRect();
|
||||||
|
|
||||||
// AUTO SCROLL ON DRAG - START
|
// Mouse relative to container in screen pixels
|
||||||
// const scrollContainer = document.getElementById("doc-con");
|
const mouseScreenX = event.clientX - currentContainerRect.left;
|
||||||
|
const mouseScreenY = event.clientY - currentContainerRect.top;
|
||||||
|
|
||||||
// const rect = scrollContainer.getBoundingClientRect();
|
// Subtract click offset to get tag's top-left in screen pixels
|
||||||
|
const tagScreenX = mouseScreenX - clickOffsetX;
|
||||||
|
const tagScreenY = mouseScreenY - clickOffsetY;
|
||||||
|
|
||||||
// const threshold = 80; // distance from edge
|
// Convert screen pixels to original coord space
|
||||||
// const scrollSpeed = 15;
|
// screen = original * scaleX * scale → original = screen / scaleX / scale
|
||||||
|
const originalLeft = tagScreenX / scale / scaleX;
|
||||||
|
const originalTop = tagScreenY / scale / scaleY;
|
||||||
|
|
||||||
// // mouse near bottom
|
positionRef.current = { left: originalLeft, top: originalTop };
|
||||||
// if (event.clientY > rect.bottom - threshold) {
|
|
||||||
// scrollContainer.scrollTop += scrollSpeed;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // mouse near top
|
// Set style in rendered pixel space (original * scaleX)
|
||||||
// else if (event.clientY < rect.top + threshold) {
|
// The parent transform:scale handles the rest
|
||||||
// scrollContainer.scrollTop -= scrollSpeed;
|
targetElement!.style.left = `${originalLeft * scaleX}px`;
|
||||||
// }
|
targetElement!.style.top = `${originalTop * scaleY}px`;
|
||||||
// AUTO SCROLL ON DRAG - END
|
|
||||||
|
|
||||||
// Get new X and Y positions relative to the container
|
|
||||||
let clientX = event.clientX
|
|
||||||
let clientY = event.clientY
|
|
||||||
|
|
||||||
if ((event as any).changedTouches?.[0]) {
|
|
||||||
clientX = (event as any).changedTouches[0].pageX;
|
|
||||||
clientY = (event as any).changedTouches[0].pageY;
|
|
||||||
}
|
|
||||||
|
|
||||||
let left = clientX - containerRect.left - offsetX;
|
|
||||||
let top = clientY - containerRect.top - offsetY;
|
|
||||||
|
|
||||||
// Restrict movement within container bounds
|
|
||||||
// left = Math.max(0, Math.min(left, conScrollWidth - elementRect.width));
|
|
||||||
// top = Math.max(0, Math.min(top, conScrollHeight - elementRect.height));
|
|
||||||
|
|
||||||
// Save in ref (fast, no re-render)
|
|
||||||
positionRef.current = { left, top };
|
|
||||||
|
|
||||||
// Update DOM directly
|
|
||||||
targetElement!.style.top = `${top}px`;
|
|
||||||
targetElement!.style.left = `${left}px`;
|
|
||||||
|
|
||||||
// Apply the movement to the element first
|
|
||||||
// setDroppedItems(prevState => ({
|
|
||||||
// ...prevState,
|
|
||||||
// [key]: Array.isArray(prevState[key])
|
|
||||||
// ? prevState[key].map((item, i) =>
|
|
||||||
// i == index ? { ...item, dimensions: { ...item.dimensions, left, top }, update: true } : item
|
|
||||||
// )
|
|
||||||
// : [],
|
|
||||||
// }));
|
|
||||||
|
|
||||||
// Update group border position during drag if it's a group element
|
|
||||||
if (groupElements != null && groupElements.length) {
|
if (groupElements != null && groupElements.length) {
|
||||||
// Use a small timeout to ensure DOM is updated before recalculating borders
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
handleGroupBorderPosition(groupElements!, containerRect, offsetX, offsetY);
|
handleGroupBorderPosition(groupElements!, currentContainerRect, clickOffsetX, clickOffsetY);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -284,33 +262,24 @@ const DroppedItemsTagsCon = forwardRef(({
|
||||||
documentId: ""
|
documentId: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// N: Adding pointer event to none get page not tag itselef from elementFromPoint
|
|
||||||
targetElement.style.pointerEvents = "none";
|
targetElement.style.pointerEvents = "none";
|
||||||
|
const el = document.elementFromPoint(e.clientX, e.clientY) as HTMLElement | null;
|
||||||
const el = document.elementFromPoint(
|
const hoveredContainer = el?.closest(".drop-page-in");
|
||||||
e.clientX,
|
|
||||||
e.clientY
|
|
||||||
) as HTMLElement | null;
|
|
||||||
|
|
||||||
const hoveredContainer = el?.closest(".drop-page-in")
|
|
||||||
|
|
||||||
targetElement.style.pointerEvents = "auto";
|
targetElement.style.pointerEvents = "auto";
|
||||||
// N: Adding pointer event to auto changing back the changes
|
|
||||||
|
|
||||||
if (hoveredContainer) {
|
if (hoveredContainer) {
|
||||||
const imgElem: HTMLElement | null = hoveredContainer.querySelector("[data-doc-img]");
|
const imgElem: HTMLElement | null = hoveredContainer.querySelector("[data-doc-img]");
|
||||||
|
hoveredDocId = imgElem ? imgElem.getAttribute("id") || "" : "";
|
||||||
hoveredDocId = imgElem ? imgElem.getAttribute("id") || "" : ""
|
|
||||||
hoveredDocId = hoveredDocId.split("-");
|
hoveredDocId = hoveredDocId.split("-");
|
||||||
hoveredPageIndex = hoveredDocId[hoveredDocId.length - 1];
|
hoveredPageIndex = hoveredDocId[hoveredDocId.length - 1];
|
||||||
hoveredDocId.pop()
|
hoveredDocId.pop();
|
||||||
hoveredDocId = hoveredDocId.join("-");
|
hoveredDocId = hoveredDocId.join("-");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hoveredContainer === null || hoveredDocId != currentDocumentId) { // NOT WORKING STILL MOVING THE TAG OUTSIDE THE COTEND DOCUMENT PAGE OVERFLOWING
|
if (hoveredContainer === null || hoveredDocId != currentDocumentId) {
|
||||||
targetElement!.style.top = `${droppedItems[key][index].dimensions.top}px`;
|
// Revert
|
||||||
targetElement!.style.left = `${droppedItems[key][index].dimensions.left}px`;
|
targetElement!.style.left = `${tagOriginalLeft * scaleX}px`;
|
||||||
|
targetElement!.style.top = `${tagOriginalTop * scaleY}px`;
|
||||||
|
|
||||||
document.removeEventListener("pointermove", handleMouseMove);
|
document.removeEventListener("pointermove", handleMouseMove);
|
||||||
document.removeEventListener("pointerup", handleMouseUp);
|
document.removeEventListener("pointerup", handleMouseUp);
|
||||||
|
|
@ -318,18 +287,11 @@ const DroppedItemsTagsCon = forwardRef(({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key in droppedItems && index in droppedItems[key]) {
|
if (key in droppedItems && index in droppedItems[key]) {
|
||||||
// const tag = droppedItems[key][index];
|
|
||||||
const documentId = droppedItems[key][index]["documentId"];
|
const documentId = droppedItems[key][index]["documentId"];
|
||||||
const pageIndex = droppedItems[key][index]["pageIndex"];
|
const pageIndex = droppedItems[key][index]["pageIndex"];
|
||||||
// const targetElemTag = e.target.closest("[data-doc-id]")
|
|
||||||
|
|
||||||
tagDocumentUpdate.pageIndex = pageIndex
|
tagDocumentUpdate.pageIndex = pageIndex;
|
||||||
tagDocumentUpdate.documentId = documentId
|
tagDocumentUpdate.documentId = documentId;
|
||||||
|
|
||||||
|
|
||||||
// if (targetElemTag) {
|
|
||||||
// let hoveredDocId = targetElemTag.getAttribute("data-doc-id");
|
|
||||||
// if (hoveredDocId) {
|
|
||||||
|
|
||||||
if (hoveredDocId == documentId) {
|
if (hoveredDocId == documentId) {
|
||||||
if (hoveredPageIndex != pageIndex) {
|
if (hoveredPageIndex != pageIndex) {
|
||||||
|
|
@ -341,150 +303,66 @@ const DroppedItemsTagsCon = forwardRef(({
|
||||||
tagDocumentUpdate.updatingDocument = true;
|
tagDocumentUpdate.updatingDocument = true;
|
||||||
tagDocumentUpdate.updatingPage = true;
|
tagDocumentUpdate.updatingPage = true;
|
||||||
tagDocumentUpdate.pageIndex = hoveredPageIndex;
|
tagDocumentUpdate.pageIndex = hoveredPageIndex;
|
||||||
tagDocumentUpdate.documentId = hoveredDocId
|
tagDocumentUpdate.documentId = hoveredDocId;
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupElements != null && groupElements.length && groupId) {
|
if (groupElements != null && groupElements.length && groupId) {
|
||||||
// Multiple approaches to ensure the positioning works:
|
setTimeout(() => { handleIGroupBorderPosition(groupId); }, 10);
|
||||||
|
setTimeout(() => { handleIGroupBorderPosition(groupId); }, 100);
|
||||||
// 1. Immediate update
|
requestAnimationFrame(() => { setTimeout(() => { handleIGroupBorderPosition(groupId); }, 50); });
|
||||||
setTimeout(() => {
|
|
||||||
handleIGroupBorderPosition(groupId);
|
|
||||||
}, 10);
|
|
||||||
|
|
||||||
// 2. Secondary update to ensure it's properly positioned
|
|
||||||
setTimeout(() => {
|
|
||||||
handleIGroupBorderPosition(groupId);
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// 3. Final update using requestAnimationFrame for DOM sync
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
handleIGroupBorderPosition(groupId);
|
|
||||||
}, 50);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// const tempDroppedItems = (droppedItems: any) => ({
|
|
||||||
// ...droppedItems,
|
|
||||||
// [key]: Array.isArray(droppedItems[key])
|
|
||||||
// ? droppedItems[key].map((item, i) =>
|
|
||||||
// i == index ? { ...item, dimensions: { ...item.dimensions, left, top }, update: true } : item
|
|
||||||
// )
|
|
||||||
// : [],
|
|
||||||
// })
|
|
||||||
|
|
||||||
// setDroppedItems(prevState => ({
|
|
||||||
// ...prevState,
|
|
||||||
// [key]: Array.isArray(prevState[key])
|
|
||||||
// ? prevState[key].map((item, i) =>
|
|
||||||
// i == index ? { ...item, documentId: tagDocumentUpdate.documentId, pageIndex: tagDocumentUpdate.pageIndex, dimensions: { ...item.dimensions, left, top }, update: true } : item
|
|
||||||
// )
|
|
||||||
// : [],
|
|
||||||
// }));
|
|
||||||
|
|
||||||
setDroppedItems(prevState => {
|
setDroppedItems(prevState => {
|
||||||
// check documentId match
|
const isSameDocument = currentDocumentId == tagDocumentUpdate.documentId;
|
||||||
const isSameDocument =
|
if (!isSameDocument) return prevState;
|
||||||
currentDocumentId == tagDocumentUpdate.documentId;
|
|
||||||
|
|
||||||
if (!isSameDocument) return prevState
|
|
||||||
|
|
||||||
// check pageIndex match
|
|
||||||
const isSamePage = currentPageIndex == tagDocumentUpdate.pageIndex;
|
const isSamePage = currentPageIndex == tagDocumentUpdate.pageIndex;
|
||||||
const scaleX = renderedWidth && pageWidth ? renderedWidth / pageWidth : 1;
|
|
||||||
const scaleY = renderedHeight && pageHeight ? renderedHeight / pageHeight : 1;
|
|
||||||
|
|
||||||
// same document + same page
|
|
||||||
if (isSameDocument && isSamePage) {
|
if (isSameDocument && isSamePage) {
|
||||||
left = Math.max(0, Math.min(left, conScrollWidth - elementRect.width));
|
const clampedLeft = Math.max(0, Math.min(left, pageWidth - currentItem.dimensions.width));
|
||||||
top = Math.max(0, Math.min(top, conScrollHeight - elementRect.height));
|
const clampedTop = Math.max(0, Math.min(top, pageHeight - currentItem.dimensions.height));
|
||||||
|
|
||||||
const normalizedLeft = left / scaleX;
|
|
||||||
const normalizedTop = top / scaleY;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...prevState,
|
...prevState,
|
||||||
[key]: Array.isArray(prevState[key])
|
[key]: Array.isArray(prevState[key])
|
||||||
? prevState[key].map((item, i) =>
|
? prevState[key].map((item, i) =>
|
||||||
i === index
|
i === index ? {
|
||||||
? {
|
...item,
|
||||||
...item,
|
documentId: tagDocumentUpdate.documentId,
|
||||||
documentId:
|
pageIndex: tagDocumentUpdate.pageIndex,
|
||||||
tagDocumentUpdate.documentId,
|
dimensions: { ...item.dimensions, left: clampedLeft, top: clampedTop },
|
||||||
pageIndex:
|
update: true,
|
||||||
tagDocumentUpdate.pageIndex,
|
} : item
|
||||||
dimensions: {
|
) : [],
|
||||||
...item.dimensions,
|
|
||||||
left: normalizedLeft,
|
|
||||||
top: normalizedTop,
|
|
||||||
},
|
|
||||||
update: true,
|
|
||||||
}
|
|
||||||
: item
|
|
||||||
)
|
|
||||||
: [],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// left = left - containerRect.left
|
// Cross page
|
||||||
const newContainerRect = hoveredContainer?.getBoundingClientRect() as DOMRect;
|
const newContainerRect = hoveredContainer?.getBoundingClientRect() as DOMRect;
|
||||||
|
const newMouseScreenX = e.clientX - newContainerRect.left;
|
||||||
|
const newMouseScreenY = e.clientY - newContainerRect.top;
|
||||||
|
left = Math.max(0, Math.min(
|
||||||
|
(newMouseScreenX - clickOffsetX) / scale / scaleX,
|
||||||
|
pageWidth - currentItem.dimensions.width
|
||||||
|
));
|
||||||
|
top = Math.max(0, Math.min(
|
||||||
|
(newMouseScreenY - clickOffsetY) / scale / scaleY,
|
||||||
|
pageHeight - currentItem.dimensions.height
|
||||||
|
));
|
||||||
|
|
||||||
left = e.clientX - newContainerRect.left - offsetX;
|
|
||||||
top = e.clientY - newContainerRect.top - offsetY;
|
|
||||||
|
|
||||||
left = Math.max(
|
|
||||||
0,
|
|
||||||
Math.min(left, newContainerRect.width - elementRect.width)
|
|
||||||
);
|
|
||||||
|
|
||||||
top = Math.max(
|
|
||||||
0,
|
|
||||||
Math.min(top, newContainerRect.height - elementRect.height)
|
|
||||||
);
|
|
||||||
|
|
||||||
// move to another page/document
|
|
||||||
const targetKey = `${tagDocumentUpdate.documentId}_${tagDocumentUpdate.pageIndex}`;
|
const targetKey = `${tagDocumentUpdate.documentId}_${tagDocumentUpdate.pageIndex}`;
|
||||||
|
const currentItems = Array.isArray(prevState[key]) ? [...prevState[key]] : [];
|
||||||
const currentItems = Array.isArray(prevState[key])
|
|
||||||
? [...prevState[key]]
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const movedItem = currentItems[index];
|
const movedItem = currentItems[index];
|
||||||
|
|
||||||
if (!movedItem) return prevState;
|
if (!movedItem) return prevState;
|
||||||
|
|
||||||
// remove from old array
|
|
||||||
currentItems.splice(index, 1);
|
currentItems.splice(index, 1);
|
||||||
|
|
||||||
// updated item
|
|
||||||
const updatedItem = {
|
|
||||||
...movedItem,
|
|
||||||
documentId: tagDocumentUpdate.documentId,
|
|
||||||
pageIndex: tagDocumentUpdate.pageIndex,
|
|
||||||
dimensions: {
|
|
||||||
...movedItem.dimensions,
|
|
||||||
left,
|
|
||||||
top,
|
|
||||||
},
|
|
||||||
update: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...prevState,
|
...prevState,
|
||||||
|
|
||||||
// old container updated
|
|
||||||
[key]: currentItems,
|
[key]: currentItems,
|
||||||
|
|
||||||
// new container updated
|
|
||||||
[targetKey]: [
|
[targetKey]: [
|
||||||
...(Array.isArray(prevState[targetKey])
|
...(Array.isArray(prevState[targetKey]) ? prevState[targetKey] : []),
|
||||||
? prevState[targetKey]
|
{ ...movedItem, documentId: tagDocumentUpdate.documentId, pageIndex: tagDocumentUpdate.pageIndex, dimensions: { ...movedItem.dimensions, left, top }, update: true },
|
||||||
: []),
|
|
||||||
updatedItem,
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
@ -493,15 +371,23 @@ const DroppedItemsTagsCon = forwardRef(({
|
||||||
document.removeEventListener("pointerup", handleMouseUp);
|
document.removeEventListener("pointerup", handleMouseUp);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add event listeners
|
|
||||||
document.addEventListener("pointermove", handleMouseMove);
|
document.addEventListener("pointermove", handleMouseMove);
|
||||||
document.addEventListener("pointerup", handleMouseUp);
|
document.addEventListener("pointerup", handleMouseUp);
|
||||||
};
|
};
|
||||||
|
|
||||||
// HANDLE TAG MOUSE DOWN - END
|
// HANDLE TAG MOUSE DOWN - END
|
||||||
|
|
||||||
// HANDLE EXPAND TAG - START
|
// HANDLE EXPAND TAG - START
|
||||||
const handleExpandTag = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number) => {
|
const handleExpandTag = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number) => {
|
||||||
event.preventDefault(); // Prevent text selection issues
|
event.preventDefault();
|
||||||
|
|
||||||
|
const scale = scaleFactor ?? 1;
|
||||||
|
const scaleX = renderedWidth && pageWidth ? renderedWidth / pageWidth : 1;
|
||||||
|
const scaleY = renderedHeight && pageHeight ? renderedHeight / pageHeight : 1;
|
||||||
|
|
||||||
|
// Combined scale: zoom * render ratio
|
||||||
|
const combinedScaleX = scaleX * scale;
|
||||||
|
const combinedScaleY = scaleY * scale;
|
||||||
|
|
||||||
const expandingElemIcon = event.currentTarget;
|
const expandingElemIcon = event.currentTarget;
|
||||||
const targetElement = expandingElemIcon.nextElementSibling?.parentElement;
|
const targetElement = expandingElemIcon.nextElementSibling?.parentElement;
|
||||||
|
|
@ -514,49 +400,41 @@ const DroppedItemsTagsCon = forwardRef(({
|
||||||
const startX = event.clientX;
|
const startX = event.clientX;
|
||||||
const startY = event.clientY;
|
const startY = event.clientY;
|
||||||
|
|
||||||
const startWidth = elementRect.width;
|
const startWidth = elementRect.width / combinedScaleX;
|
||||||
const startHeight = elementRect.height;
|
const startHeight = elementRect.height / combinedScaleY;
|
||||||
|
|
||||||
const handleMouseMove = (event: MouseEvent) => {
|
const handleMouseMove = (event: MouseEvent) => {
|
||||||
|
const dropZone = targetContainer.getBoundingClientRect();
|
||||||
|
|
||||||
|
const deltaX = (event.clientX - startX) / combinedScaleX;
|
||||||
|
const deltaY = (event.clientY - startY) / combinedScaleY;
|
||||||
|
|
||||||
const dropZone: DOMRect = targetContainer?.getBoundingClientRect() as DOMRect;
|
let newWidth = startWidth + deltaX;
|
||||||
const droppedElemRect: DOMRect = targetElement?.getBoundingClientRect() as DOMRect;
|
let newHeight = startHeight + deltaY;
|
||||||
|
|
||||||
console.log(dropZone, "dropZone Line 309")
|
if (newWidth > 400) newWidth = 400;
|
||||||
console.log(droppedElemRect, "rect Line 309")
|
if (newHeight > 200) newHeight = 200;
|
||||||
|
if (newWidth < 20) newWidth = 20;
|
||||||
|
if (newHeight < 10) newHeight = 10;
|
||||||
|
|
||||||
let newWidth = startWidth + (event.clientX - startX);
|
const maxWidth = dropZone.width / combinedScaleX;
|
||||||
let newHeight = startHeight + (event.clientY - startY);
|
const maxHeight = dropZone.height / combinedScaleY;
|
||||||
|
const currentLeft = droppedItems[key][index].dimensions.left;
|
||||||
|
const currentTop = droppedItems[key][index].dimensions.top;
|
||||||
|
|
||||||
|
if (currentLeft + newWidth > maxWidth) newWidth = maxWidth - currentLeft;
|
||||||
|
if (currentTop + newHeight > maxHeight) newHeight = maxHeight - currentTop;
|
||||||
|
|
||||||
if (newHeight > 200 || newWidth > 400) {
|
|
||||||
if (newHeight > 200) {
|
|
||||||
newHeight = 200
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newWidth > 400) {
|
|
||||||
newWidth = 400
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dropZone.right - (droppedElemRect.left + newWidth)) < 0) {
|
|
||||||
newWidth = startWidth
|
|
||||||
}
|
|
||||||
if ((dropZone.bottom - (droppedElemRect.bottom + newHeight)) < 0) {
|
|
||||||
newHeight = startHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply the new width & height
|
|
||||||
setDroppedItems({
|
setDroppedItems({
|
||||||
...droppedItems,
|
...droppedItems,
|
||||||
[key]: Array.isArray(droppedItems[key]) // Ensure it's an array
|
[key]: Array.isArray(droppedItems[key])
|
||||||
? droppedItems[key].map((item, i) =>
|
? droppedItems[key].map((item, i) =>
|
||||||
i == index ? { ...item, dimensions: { ...item.dimensions, width: newWidth, height: newHeight }, update: true } : item
|
i === index
|
||||||
|
? { ...item, dimensions: { ...item.dimensions, width: newWidth, height: newHeight }, update: true }
|
||||||
|
: item
|
||||||
)
|
)
|
||||||
: [], // Provide a fallback in case it's undefined or not an array
|
: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseUp = () => {
|
const handleMouseUp = () => {
|
||||||
|
|
|
||||||
|
|
@ -308,7 +308,7 @@ const FieldList: React.FC<FieldListProps> = ({ color, recipientId, recipientIndx
|
||||||
// );
|
// );
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-row sm:flex-wrap gap-2 justify-start items-start w-full overflow-x-auto'>
|
<div className='flex flex-row sm:flex-wrap gap-2 justify-start items-start overflow-x-auto w-[90vw] sm:w-full px-2'>
|
||||||
{tagsData.map((field, index) => {
|
{tagsData.map((field, index) => {
|
||||||
|
|
||||||
const IconComponent = typeToIconMap[field.type] || <FaQuestionCircle />;
|
const IconComponent = typeToIconMap[field.type] || <FaQuestionCircle />;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { MdKeyboardArrowDown } from 'react-icons/md'
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { fetchDocuments } from '../../../store/slices/documentSlice';
|
import { fetchDocuments } from '../../../store/slices/documentSlice';
|
||||||
import { FaAngleUp } from 'react-icons/fa';
|
import { FaAngleUp } from 'react-icons/fa';
|
||||||
|
import { SlDocs } from "react-icons/sl";
|
||||||
|
|
||||||
interface LeftSideBarProps {
|
interface LeftSideBarProps {
|
||||||
isFields: boolean;
|
isFields: boolean;
|
||||||
|
|
@ -78,16 +79,16 @@ const LeftSideBar: React.FC<LeftSideBarProps> = ({ isFields, selectedRecipientIn
|
||||||
}, [selectedRecipient])
|
}, [selectedRecipient])
|
||||||
|
|
||||||
if (selectedRecipient && selectedRecipient.type == recipientType.CC) {
|
if (selectedRecipient && selectedRecipient.type == recipientType.CC) {
|
||||||
return <div className='col-span-2 bg-white h-full p-4 overflow-y-auto'></div>;
|
return <div className='sm:col-span-2 bg-white h-full p-4 overflow-y-auto'></div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Left Side Bar - START */}
|
{/* Left Side Bar - START */}
|
||||||
<div className='col-span-2'>
|
<div className='sm:col-span-2'>
|
||||||
|
|
||||||
{
|
{
|
||||||
isFields && <div className={`sm:block p-4 absolute sm:top-[0] rounded-tr-md z-50 sm:relative sm:col-span-2 bg-white border-t-1 border-r-1 border-slate-300 sm:h-[calc(100vh-40px)] overflow-y-auto sm:w-auto ${isFields ? "h-[150px] bottom-0 overflow-x-hidden w-full" : "h-[calc(100vh-40px)]"} `}>
|
(isFields || window.innerWidth > 638) && <div className={`sm:block p-4 absolute sm:top-[0] rounded-tr-md z-50 sm:relative sm:col-span-2 bg-white border-t-1 border-r-1 border-slate-300 sm:h-[calc(100vh-40px)] overflow-y-auto sm:w-auto ${(isFields || window.innerWidth > 638) ? "h-[100px] bottom-0 overflow-x-hidden w-full" : "h-[calc(100vh-40px)]"} `}>
|
||||||
{/* <div
|
{/* <div
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// handleSetIsPages(false)
|
// handleSetIsPages(false)
|
||||||
|
|
@ -114,7 +115,7 @@ const LeftSideBar: React.FC<LeftSideBarProps> = ({ isFields, selectedRecipientIn
|
||||||
</div> */}
|
</div> */}
|
||||||
|
|
||||||
|
|
||||||
{selectedRecipients.length > 0 && isFields && <>
|
{selectedRecipients.length > 0 && (isFields || window.innerWidth > 638) && <>
|
||||||
{/* Fields List and Recipeint - Start */}
|
{/* Fields List and Recipeint - Start */}
|
||||||
{/* Side Bar showing Recipients */}
|
{/* Side Bar showing Recipients */}
|
||||||
<div className='sm:relative sm:top-0 sm:left-0 fixed w-full'>
|
<div className='sm:relative sm:top-0 sm:left-0 fixed w-full'>
|
||||||
|
|
@ -177,7 +178,10 @@ const LeftSideBar: React.FC<LeftSideBarProps> = ({ isFields, selectedRecipientIn
|
||||||
<div
|
<div
|
||||||
id='tags-con-dash-left'
|
id='tags-con-dash-left'
|
||||||
className='mt-2 w-full h-[400px] sm:h-auto'>
|
className='mt-2 w-full h-[400px] sm:h-auto'>
|
||||||
<FieldList color={selectedRecipient?.color || '#2d2d2d'} recipientId={selectedRecipient.id} recipientIndx={selectedRecipientIndx} />
|
<FieldList
|
||||||
|
color={selectedRecipient?.color || '#2d2d2d'}
|
||||||
|
recipientId={selectedRecipient.id}
|
||||||
|
recipientIndx={selectedRecipientIndx} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -195,25 +199,26 @@ const LeftSideBar: React.FC<LeftSideBarProps> = ({ isFields, selectedRecipientIn
|
||||||
{/* Left Side Pages */}
|
{/* Left Side Pages */}
|
||||||
{<div
|
{<div
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// handleSetIsPages(true)
|
handleSetIsPages(true)
|
||||||
handleSetIsFields(false)
|
// handleSetIsFields(false)
|
||||||
}}
|
}}
|
||||||
className='sm:hidden fixed top-[8%] left-0 bg-[var(--primary)] z-50 flex items-center text-white rounded-tr-md rounded-br-md cursor-pointer opacity-50 hover:opacity-100 transition-all duration-300'>
|
className='sm:hidden fixed top-[8%] left-0 bg-[var(--primary)] z-50 flex items-center text-white rounded-tr-sm rounded-br-sm cursor-pointer opacity-50 hover:opacity-100 transition-all duration-300'>
|
||||||
<div className='py-2 pl-2 pr-1'>
|
<div className='py-2 pl-2 pr-2'>
|
||||||
<FaAngleUp className='rotate-90' />
|
{/* <FaAngleUp className='rotate-90' /> */}
|
||||||
<p className='flex flex-col justify-center items-center text-xs tracking-widest mt-1 pt-1 border-t-1 border-white'>
|
<SlDocs />
|
||||||
|
{/* <p className='flex flex-col justify-center items-center text-xs tracking-widest mt-1 pt-1 border-t-1 border-white'>
|
||||||
<span>P</span>
|
<span>P</span>
|
||||||
<span>A</span>
|
<span>A</span>
|
||||||
<span>G</span>
|
<span>G</span>
|
||||||
<span>E</span>
|
<span>E</span>
|
||||||
<span>S</span>
|
<span>S</span>
|
||||||
</p>
|
</p> */}
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
|
|
||||||
|
|
||||||
{!isFields && <div
|
{(!isFields && window.innerWidth <= 638) && <div
|
||||||
className='sm:hidden fixed bottom-0 left-0 rounded-tr-2xl rounded-tl-2xl bg-[var(--primary)] z-50 w-full flex justify-center text-white cursor-pointer opacity-50 hover:opacity-100 transition-all duration-300'
|
className='sm:hidden fixed bottom-0 left-0 rounded-tr-sm rounded-tl-sm bg-[var(--primary)] z-50 w-full flex justify-center text-white cursor-pointer opacity-50 hover:opacity-100 transition-all duration-300'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// handleSetIsPages(false)
|
// handleSetIsPages(false)
|
||||||
handleSetIsFields(true)
|
handleSetIsFields(true)
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,18 @@ import React, { useEffect, useState } from 'react'
|
||||||
import { useDispatch, useSelector } from 'react-redux'
|
import { useDispatch, useSelector } from 'react-redux'
|
||||||
import { RootState } from '../../../store/store'
|
import { RootState } from '../../../store/store'
|
||||||
|
|
||||||
import { FaAngleRight, FaCheck, FaChevronRight, FaPaste, FaRegCopy, FaSave, FaSignature } from 'react-icons/fa'
|
import { FaAngleRight, FaCheck, FaRegCopy, FaSignature } from 'react-icons/fa'
|
||||||
import { IoIosDocument, IoMdArrowRoundBack, IoMdHome } from 'react-icons/io'
|
import { IoIosDocument, IoMdHome } from 'react-icons/io'
|
||||||
import { LuRedo2, LuTableOfContents, LuUndo2 } from 'react-icons/lu'
|
import { LuRedo2, LuUndo2 } from 'react-icons/lu'
|
||||||
import { MdKeyboardArrowDown, MdOutlineKeyboardBackspace } from 'react-icons/md'
|
import { MdKeyboardArrowDown } from 'react-icons/md'
|
||||||
import { RiResetRightLine } from 'react-icons/ri'
|
|
||||||
import { fetchRecipients, recipientType, toggleToTemplates, TRANSACTION_TEMPLATE_TOGGLE } from '../../../store/slices/selectedRecipientsSlice'
|
import { fetchRecipients, recipientType, toggleToTemplates, TRANSACTION_TEMPLATE_TOGGLE } from '../../../store/slices/selectedRecipientsSlice'
|
||||||
import { fetchDocuments } from '../../../store/slices/documentSlice'
|
import { fetchDocuments } from '../../../store/slices/documentSlice'
|
||||||
import { Link, useNavigate, useParams } from 'react-router-dom'
|
import { useNavigate, useParams } from 'react-router-dom'
|
||||||
import { Bounce, toast } from 'react-toastify'
|
|
||||||
import { FiChevronDown } from 'react-icons/fi'
|
|
||||||
import RecipientsCon from '../processStepOne/RecipientsCon'
|
import RecipientsCon from '../processStepOne/RecipientsCon'
|
||||||
import MessageCon from '../processStepOne/MessageCon'
|
import MessageCon from '../processStepOne/MessageCon'
|
||||||
import { IoArrowBackSharp, IoCopy } from 'react-icons/io5'
|
import { IoArrowBackSharp } from 'react-icons/io5'
|
||||||
import { FaRegPaste } from 'react-icons/fa6'
|
import { FaRegPaste } from 'react-icons/fa6'
|
||||||
import ConfirmSendModal from './TransactionSendConfirmationModal'
|
import ConfirmSendModal from './TransactionSendConfirmationModal'
|
||||||
import { RxDividerVertical } from 'react-icons/rx'
|
|
||||||
import CloseConfirmationModal from './CloseCofirmationModal'
|
import CloseConfirmationModal from './CloseCofirmationModal'
|
||||||
|
|
||||||
interface NavTwoProps {
|
interface NavTwoProps {
|
||||||
|
|
@ -34,6 +30,7 @@ interface NavTwoProps {
|
||||||
aId?: string | null
|
aId?: string | null
|
||||||
tId?: string | null
|
tId?: string | null
|
||||||
onSendClick?: (isSave?: boolean, navigate?: boolean, navigateTo?: string) => void;
|
onSendClick?: (isSave?: boolean, navigate?: boolean, navigateTo?: string) => void;
|
||||||
|
onZoomChange?: React.Dispatch<React.SetStateAction<number>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -59,20 +56,37 @@ const fitObj = [
|
||||||
label: "200%",
|
label: "200%",
|
||||||
value: "200"
|
value: "200"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "250%",
|
||||||
|
value: "250"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "300%",
|
||||||
|
value: "300"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "350%",
|
||||||
|
value: "350"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "400%",
|
||||||
|
value: "400"
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const NavTwo: React.FC<NavTwoProps> = ({
|
const NavTwo: React.FC<NavTwoProps> = ({
|
||||||
transactionSaving = false,
|
transactionSaving = false,
|
||||||
isFields,
|
// isFields,
|
||||||
setIsFields,
|
// setIsFields,
|
||||||
isPages,
|
// isPages,
|
||||||
setIsPages,
|
// setIsPages,
|
||||||
isSend,
|
// isSend,
|
||||||
setIsSend,
|
// setIsSend,
|
||||||
isPreview = false,
|
isPreview = false,
|
||||||
aId = null,
|
aId = null,
|
||||||
tId = null,
|
tId = null,
|
||||||
onSendClick,
|
onSendClick,
|
||||||
|
onZoomChange
|
||||||
}) => {
|
}) => {
|
||||||
let transactionTemplateToggle = TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS;
|
let transactionTemplateToggle = TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS;
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
@ -181,6 +195,17 @@ const NavTwo: React.FC<NavTwoProps> = ({
|
||||||
return transactionSendValidationObj;
|
return transactionSendValidationObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove the zoom() function and the useEffect that calls it
|
||||||
|
// Instead:
|
||||||
|
const handleFitSelect = (indx: number) => {
|
||||||
|
setSelFitIndx(indx);
|
||||||
|
let value = fitObj[indx].value;
|
||||||
|
if (value === "FIT") value = "100";
|
||||||
|
onZoomChange?.(Number(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function handleSend(isSignSend: boolean = false) {
|
function handleSend(isSignSend: boolean = false) {
|
||||||
// dispatch(showLoader("Loading ..."));
|
// dispatch(showLoader("Loading ..."));
|
||||||
if (onSendClick === undefined) return;
|
if (onSendClick === undefined) return;
|
||||||
|
|
@ -215,20 +240,20 @@ const NavTwo: React.FC<NavTwoProps> = ({
|
||||||
if (confirmSendModalOpen.confirm) handleSend()
|
if (confirmSendModalOpen.confirm) handleSend()
|
||||||
}, [confirmSendModalOpen])
|
}, [confirmSendModalOpen])
|
||||||
|
|
||||||
const zoom = (percentage: number, contentClass: string) => {
|
// const zoom = (percentage: number, contentClass: string) => {
|
||||||
const content = document.querySelector(`.${contentClass}`);
|
// const content = document.querySelector(`.${contentClass}`);
|
||||||
if (content) {
|
// if (content) {
|
||||||
(content as HTMLElement).style.zoom = `${percentage}%`;
|
// (content as HTMLElement).style.zoom = `${percentage}%`;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
let indx = fitObj[selFitIndx].value
|
// let indx = fitObj[selFitIndx].value
|
||||||
if (indx == "FIT") {
|
// if (indx == "FIT") {
|
||||||
indx = "100";
|
// indx = "100";
|
||||||
}
|
// }
|
||||||
zoom(Number(indx), 'zoom-con')
|
// zoom(Number(indx), 'zoom-con')
|
||||||
}, [selFitIndx])
|
// }, [selFitIndx])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!transactionSaving) return;
|
if (!transactionSaving) return;
|
||||||
|
|
@ -277,7 +302,7 @@ const NavTwo: React.FC<NavTwoProps> = ({
|
||||||
className='hover:text-[var(--primary)] durartion-300 cursor-pointer'
|
className='hover:text-[var(--primary)] durartion-300 cursor-pointer'
|
||||||
onClick={() => setClosePage(true)}
|
onClick={() => setClosePage(true)}
|
||||||
>
|
>
|
||||||
<IoMdHome />
|
<IoMdHome className='text-[var(--primary)] sm:text-slate-600' />
|
||||||
{/* <img width={120} src="/sme-colored.png" alt="Sign Made Easy" /> */}
|
{/* <img width={120} src="/sme-colored.png" alt="Sign Made Easy" /> */}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
|
@ -288,10 +313,10 @@ const NavTwo: React.FC<NavTwoProps> = ({
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='w-[1px] h-[28px] bg-slate-200'></div>
|
<div className='w-[0px] md:w-[1px] h-[28px] bg-slate-200'></div>
|
||||||
|
|
||||||
|
|
||||||
<div className='flex items-center gap-2 text-xs'>
|
<div className='hidden md:flex items-center gap-2 text-xs'>
|
||||||
<button
|
<button
|
||||||
onClick={() => navigate(-1)}
|
onClick={() => navigate(-1)}
|
||||||
className='underline font-thin cursor-pointer'>
|
className='underline font-thin cursor-pointer'>
|
||||||
|
|
@ -306,7 +331,7 @@ const NavTwo: React.FC<NavTwoProps> = ({
|
||||||
<div
|
<div
|
||||||
tabIndex={1}
|
tabIndex={1}
|
||||||
onBlur={() => setIsFitDd(false)}
|
onBlur={() => setIsFitDd(false)}
|
||||||
className='absolute gap-2 flex items-center left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] z-50'
|
className='hidden absolute gap-2 lg:flex items-center left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] z-50'
|
||||||
>
|
>
|
||||||
|
|
||||||
<div className='flex'>
|
<div className='flex'>
|
||||||
|
|
@ -344,7 +369,8 @@ const NavTwo: React.FC<NavTwoProps> = ({
|
||||||
{fitObj.map((val, indx) => {
|
{fitObj.map((val, indx) => {
|
||||||
return (<div
|
return (<div
|
||||||
key={indx}
|
key={indx}
|
||||||
onClick={() => setSelFitIndx(indx)}
|
// onClick={() => setSelFitIndx(indx)}
|
||||||
|
onClick={() => handleFitSelect(indx)}
|
||||||
className='flex z-50 items-center justify-between gap-2 w-[70px] p-2 text-xs cursor-default hover:bg-slate-100'>
|
className='flex z-50 items-center justify-between gap-2 w-[70px] p-2 text-xs cursor-default hover:bg-slate-100'>
|
||||||
<div
|
<div
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ const ProcessStepTwo = () => {
|
||||||
const windowWidth = window.innerWidth;
|
const windowWidth = window.innerWidth;
|
||||||
|
|
||||||
const [isFields, setIsFields] = useState(windowWidth > 638 ? true : false);
|
const [isFields, setIsFields] = useState(windowWidth > 638 ? true : false);
|
||||||
const [isPages, setIsPages] = useState(false);
|
const [isPages, setIsPages] = useState(windowWidth > 638 ? true : false);
|
||||||
|
|
||||||
const [selectedRecipient, setSelectedRecipient] = useState(0);
|
const [selectedRecipient, setSelectedRecipient] = useState(0);
|
||||||
|
|
||||||
|
|
@ -70,21 +70,13 @@ const ProcessStepTwo = () => {
|
||||||
|
|
||||||
|
|
||||||
const handleSetIsFields = (setTo: boolean) => {
|
const handleSetIsFields = (setTo: boolean) => {
|
||||||
if (setTo != undefined && setTo != isFields) {
|
setIsFields(true)
|
||||||
setIsFields(setTo)
|
setIsPages(false)
|
||||||
if (setTo == true) {
|
|
||||||
setIsPages(false)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSetIsPages = (setTo: boolean) => {
|
const handleSetIsPages = (setTo: boolean) => {
|
||||||
if (setTo != undefined && setTo != isPages) {
|
setIsFields(false)
|
||||||
setIsPages(setTo)
|
setIsPages(true)
|
||||||
if (setTo == true) {
|
|
||||||
setIsFields(false)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const docRef = useRef<DocumentContainerRef>(null);
|
const docRef = useRef<DocumentContainerRef>(null);
|
||||||
|
|
@ -93,13 +85,59 @@ const ProcessStepTwo = () => {
|
||||||
docRef.current?.handleTransactionProcess(isSave, isNavigate, navigateTo);
|
docRef.current?.handleTransactionProcess(isSave, isNavigate, navigateTo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [zoomScale, setZoomScale] = useState<number>(100); // percentage
|
||||||
|
|
||||||
|
// To center the container on every zoom scale change - START
|
||||||
|
useEffect(() => {
|
||||||
|
const container = document.getElementById("doc-con");
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
const prevScrollRatio = container.scrollTop / (container.scrollHeight || 1);
|
||||||
|
|
||||||
|
const newScrollTop = prevScrollRatio * container.scrollHeight;
|
||||||
|
const newScrollLeft = (container.scrollWidth - container.clientWidth) / 2;
|
||||||
|
|
||||||
|
container.scrollTo({
|
||||||
|
top: newScrollTop,
|
||||||
|
left: newScrollLeft,
|
||||||
|
behavior: "instant" as ScrollBehavior
|
||||||
|
});
|
||||||
|
}, [zoomScale]);
|
||||||
|
// To center the container on every zoom scale change - END
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`min-w-full relative h-screen bg-slate-100 overflow-hidden ${(globalLoader.isLoading) ? 'pointer-events-none' : ''}`}>
|
<div className={`min-w-full relative h-screen bg-slate-100 overflow-hidden ${(globalLoader.isLoading) ? 'pointer-events-none' : ''}`}>
|
||||||
<NavTwo transactionSaving={transactionSaving} isFields={isFields} isPages={isPages} setIsPages={setIsPages} setIsFields={setIsFields} isSend={isSend} setIsSend={setIsSend} onSendClick={handleSendClick} />
|
<NavTwo
|
||||||
|
onZoomChange={setZoomScale}
|
||||||
|
transactionSaving={transactionSaving}
|
||||||
|
// isFields={isFields}
|
||||||
|
// isPages={isPages}
|
||||||
|
// setIsPages={setIsPages}
|
||||||
|
// setIsFields={setIsFields}
|
||||||
|
// isSend={isSend}
|
||||||
|
// setIsSend={setIsSend}
|
||||||
|
onSendClick={handleSendClick} />
|
||||||
|
|
||||||
<div className='sm:grid sm:grid-cols-12 sm:gap-1 mt-1 h-[calc(100vh-46px)] overflow-hidden'>
|
<div className='sm:grid sm:grid-cols-12 sm:gap-1 mt-1 h-[calc(100vh-46px)] overflow-hidden'>
|
||||||
<LeftSideBar isFields={isFields} isPages={isPages} selectedRecipientIndx={selectedRecipient} setSelectedRecipient={setSelectedRecipient} handleSetIsFields={handleSetIsFields} handleSetIsPages={handleSetIsPages} />
|
<LeftSideBar
|
||||||
<DocumentContainer ref={docRef} selectedRecipientIndx={selectedRecipient} transactionSaving={transactionSaving} setTransactionSaving={setTransactionSaving} isSend={isSend} setIsSend={setIsSend} />
|
isFields={isFields}
|
||||||
|
isPages={isPages}
|
||||||
|
selectedRecipientIndx={selectedRecipient}
|
||||||
|
setSelectedRecipient={setSelectedRecipient}
|
||||||
|
handleSetIsFields={handleSetIsFields}
|
||||||
|
handleSetIsPages={handleSetIsPages}
|
||||||
|
/>
|
||||||
|
<DocumentContainer
|
||||||
|
isPages={isPages}
|
||||||
|
setIsPages={setIsPages}
|
||||||
|
ref={docRef}
|
||||||
|
zoomScale={zoomScale}
|
||||||
|
selectedRecipientIndx={selectedRecipient}
|
||||||
|
transactionSaving={transactionSaving}
|
||||||
|
setTransactionSaving={setTransactionSaving}
|
||||||
|
isSend={isSend}
|
||||||
|
setIsSend={setIsSend}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{globalLoader.isLoading && <Loader />}
|
{globalLoader.isLoading && <Loader />}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,11 @@ import { DroppedItemsObj } from '../DocumentContainer';
|
||||||
import { MdKeyboardArrowUp, MdMoreVert } from 'react-icons/md';
|
import { MdKeyboardArrowUp, MdMoreVert } from 'react-icons/md';
|
||||||
import { PiTagSimpleFill } from 'react-icons/pi';
|
import { PiTagSimpleFill } from 'react-icons/pi';
|
||||||
|
|
||||||
const DocumentPages: React.FC<{ droppedItems: DroppedItemsObj }> = ({ droppedItems }) => {
|
const DocumentPages: React.FC<{
|
||||||
|
isPages: boolean;
|
||||||
|
droppedItems: DroppedItemsObj;
|
||||||
|
setIsPages: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
}> = ({ isPages, droppedItems, setIsPages }) => {
|
||||||
|
|
||||||
type RecipientPageTagInfo = {
|
type RecipientPageTagInfo = {
|
||||||
color: string;
|
color: string;
|
||||||
|
|
@ -132,8 +136,22 @@ const DocumentPages: React.FC<{ droppedItems: DroppedItemsObj }> = ({ droppedIte
|
||||||
|
|
||||||
}, [droppedItems]);
|
}, [droppedItems]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!isPages) return
|
||||||
|
const docPagesCon = document.getElementById("document-pages");
|
||||||
|
|
||||||
|
if (docPagesCon) {
|
||||||
|
docPagesCon.focus();
|
||||||
|
}
|
||||||
|
}, 0)
|
||||||
|
}, [isPages]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="col-span-2 flex flex-col w-full overflow-y-auto">
|
<div id='document-pages'
|
||||||
|
tabIndex={-1}
|
||||||
|
onBlur={() => window.innerWidth <= 638 && setIsPages(false)}
|
||||||
|
className={`h-[100vh] absolute ${isPages || window.innerWidth > 638 ? "" : "hidden"} top-0 left-0 sm:static max-w-max bg-slate-100 z-50 sm:col-span-2 flex flex-col w-full overflow-y-auto`}>
|
||||||
{selectedDocuments.map((document, indx) => (
|
{selectedDocuments.map((document, indx) => (
|
||||||
<div key={indx} className="border-b border-slate-200 pb-3 mb-1">
|
<div key={indx} className="border-b border-slate-200 pb-3 mb-1">
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ interface Signature {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ClientSignConProps {
|
interface ClientSignConProps {
|
||||||
|
zoomScale: number,
|
||||||
setOpenSign?: (value: boolean) => void;
|
setOpenSign?: (value: boolean) => void;
|
||||||
getAllSignatures: () => Promise<void>;
|
getAllSignatures: () => Promise<void>;
|
||||||
// editingSignature?: Signature | null;
|
// editingSignature?: Signature | null;
|
||||||
|
|
@ -90,6 +91,7 @@ const fontsMap = [
|
||||||
|
|
||||||
|
|
||||||
const ClientSignCon: React.FC<ClientSignConProps> = ({
|
const ClientSignCon: React.FC<ClientSignConProps> = ({
|
||||||
|
zoomScale,
|
||||||
recipient,
|
recipient,
|
||||||
setOpenSign,
|
setOpenSign,
|
||||||
recipientId,
|
recipientId,
|
||||||
|
|
@ -98,7 +100,8 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
||||||
signTagId
|
signTagId
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
console.log("savedModal", recipient)
|
// const scaleFactor: number = (zoomScale ?? 100) / 100;
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState<'SELECT' | 'DRAW' | 'UPLOAD' | 'SAVED'>('DRAW');
|
const [activeTab, setActiveTab] = useState<'SELECT' | 'DRAW' | 'UPLOAD' | 'SAVED'>('DRAW');
|
||||||
const [fullName, setFullName] = useState('');
|
const [fullName, setFullName] = useState('');
|
||||||
const [initials, setInitials] = useState('');
|
const [initials, setInitials] = useState('');
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ export default defineConfig({
|
||||||
server: {
|
server: {
|
||||||
port: 5173,
|
port: 5173,
|
||||||
allowedHosts: [
|
allowedHosts: [
|
||||||
|
'smashing-albacore-engaging.ngrok-free.app',
|
||||||
'quality-friendly-goldfish.ngrok-free.app',
|
'quality-friendly-goldfish.ngrok-free.app',
|
||||||
'officially-powerful-goat.ngrok-free.app',
|
'officially-powerful-goat.ngrok-free.app',
|
||||||
'89f0-49-36-189-120.ngrok-free.app',
|
'89f0-49-36-189-120.ngrok-free.app',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue