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

857 lines
38 KiB
TypeScript

import React, { useEffect, useLayoutEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { RootState } from '../../../store/store'
import api from '../../../config/api';
import RightSideBar from './rightSideBar/RightSideBar';
import { DroppedItem } from '../../../utlity/types';
import { useNavigate, useParams } from 'react-router-dom';
import { IoMdClose } from 'react-icons/io';
import { fetchRecipients } from '../../../store/slices/selectedRecipientsSlice';
import { fetchDocuments } from '../../../store/slices/documentSlice';
import { FaQuestionCircle } from 'react-icons/fa';
import typeToIconMap from '../../../helper/iconMap';
import { IoAdd } from 'react-icons/io5';
import Loader from '../../dashboard/Loader';
export interface DroppedItemsObj {
[key: string]: DroppedItem[]
}
interface DroppedTagsDefaultFieldType {
[key: string]: string
}
const droppedTagsDefaultField: DroppedTagsDefaultFieldType = {
text: "paragraph",
temporal: "date",
number: "integer",
// image: "STAMP",
select: "single select",
checkbox: "TOGGLE"
}
interface DocumentContainerProps {
isSend: boolean | null;
setIsSend: React.Dispatch<React.SetStateAction<boolean | null>>;
}
const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
const { accountId, transactionId } = useParams<{ accountId: string, transactionId: string }>();
if (!accountId || !transactionId) {
window.location.href = "/";
return null;
}
// const transactionId = useSelector((state: RootState) => state.transaction.transactionId)
const navigate = useNavigate();
const dispatch = useDispatch();
const selectedRecipients = useSelector((state: RootState) => state.selectedRecipients.recipients);
// const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments)
const selectedDocuments = useSelector((state: RootState) => state.documents.documents)
useEffect(() => {
selectedRecipients.length === 0 && dispatch(fetchRecipients({ accountId, transactionId }));
selectedDocuments.length === 0 && dispatch(fetchDocuments({ accountId, transactionId }));
}, [])
// FETCHING TAG - START
useEffect(() => {
if (selectedRecipients.length === 0) return;
const fetchTags = async () => {
try {
const requests = selectedRecipients.map((recipient) =>
api.get(`/api/accounts/${accountId}/transactions/${transactionId}/recipients/${recipient.id}/tags`)
);
const response = await Promise.all(requests);
let recTags = {}
for (const res of response) {
for (const tag of res.data) {
const key = `${tag.documentId}_${tag.pageIndex}`;
if (recTags[key]) {
recTags[key].push(tag);
} else {
recTags[key] = [tag]; // Initialize with an array
}
}
}
// console.log(recTags, "Line 83");
setDroppedItems(recTags)
// Handle your response here
} catch (err) {
console.error(err);
}
};
fetchTags();
}, [selectedRecipients]);
// FETCHING TAG - END
const [droppedItems, setDroppedItems] = useState<DroppedItemsObj>({});
const [droppedItemsCounter, setDroppedItemsCounter] = useState<number>(1);
const [selectedTag, setSelectedTag] = useState<{ key: string, index: number } | null>(null);
// NAVIGATING to Dashboard if Transaction is not created - START
useLayoutEffect(() => {
if (transactionId) return;
navigate("/");
}, [transactionId])
// NAVIGATING to Dashboard if Transaction is not created - END
const groupByRecipientId = (tagsArray: any[]) => {
const tagsData: Record<number, any[]> = {};
for (const tag of tagsArray) {
const recipientId = tag.recipientId;
if (!tagsData[recipientId]) {
tagsData[recipientId] = [];
}
tagsData[recipientId].push(tag);
}
return tagsData;
};
const sendTagsToRecipients = async (
tagsData: Record<number, any[]>,
accountId: string,
transactionId: string
) => {
// tagsData = tagsData.filter((tag, indx) => (("update" in tag && tag.update) || !("id" in tag)) )
// Filter Tags that needs to update
const updatedData = {}
// debugger
for (const [recipientId, tags] of Object.entries(tagsData)) {
console.log(recipientId, tags, "line 133")
const updateTags = []
for (const tag of tags) {
if ("update" in tag && tag.update) {
updateTags.push(tag)
}
if (updateTags.length && "update" in updateTags[updateTags.length - 1]) {
delete updateTags[updateTags.length - 1].update
}
}
updatedData[recipientId] = updateTags
}
const requests = Object.entries(updatedData).map(([recipientId, tags]) => {
return api.put(
`/api/accounts/${accountId}/transactions/${transactionId}/recipients/${recipientId}/tags`,
tags
);
});
try {
const responses = await Promise.all(requests);
const droppedItemsUpdateFalse = Object.fromEntries(
Object.entries(droppedItems).map(([recipientId, tags]) => {
return [recipientId, tags.map(tag => ({ ...tag, update: false }))];
})
)
setDroppedItems(droppedItemsUpdateFalse);
} catch (error) {
console.error("Error submitting recipient tags:", error);
}
};
// Save Tags - START
useEffect(() => {
if (isSend === null) return;
// dispatch(showLoader("Creating Transaction"))
let updatedTags = { ...droppedItems }
// const sendTags = {
// "mod": [],
// "remove": []
// }
let tagsData = []
// const modified = []
// const remove = []
// console.log(updatedTags, "updatedTags");
for (const dropPageIds of Object.keys(updatedTags)) {
for (const dropTag of updatedTags[dropPageIds]) {
let mask = null
console.log(dropTag, "line 132")
// if (dropTag.subType?.toLowerCase() === "password") {
// console.log(dropTag)
mask = {
"type": dropTag.maskType ? `${dropTag.maskType}`.toUpperCase() : null,
"character": dropTag.maskCharacter ? `${dropTag.maskCharacter}`.toUpperCase() : null
}
// }
console.log(dropTag, "line 204")
const isDeleted = "isDeleted" in dropTag ? dropTag.isDeleted : false
const updatedTagData = {
"id": "id" in dropTag ? dropTag.id : null,
"label": dropTag.label,
"dimensions": dropTag.dimensions,
"type": dropTag.type.toUpperCase(),
// "subType": (dropTag.subType ? dropTag.subType.toUpperCase() : null),
"minLength": "minLength" in dropTag ? dropTag.minLength : 0,
"maxLength": "maxLength" in dropTag ? dropTag.maxLength : 0,
"error": ("error" in dropTag && dropTag.error) ? `${dropTag.error}`.toUpperCase() : "error",
"regex": "regex" in dropTag ? dropTag.regex : []
// }
,
"documentId": dropTag.documentId,
"options": ("options" in dropTag) ? dropTag.options : [],
"pageIndex": dropTag.pageIndex,
"recipientId": dropTag.recipientId,
"styles": "styles" in dropTag ? dropTag.styles : {
"font": "",
"italic": false,
"bold": false,
"underline": false,
"color": "black",
"textSize": 0
},
// "required": (dropTag.type.toUpperCase() !== "SIGNATURE" && dropTag.type.toUpperCase() !== "INITIALS") ? dropTag.required : true,
"required": "required" in dropTag ? dropTag.required : true,
"update": "update" in dropTag ? dropTag.update : false,
"readOnly": false,
}
if ("format" in dropTag) {
updatedTagData.format = `${dropTag.subType}`.toUpperCase();
updatedTagData.dateFormat = dropTag.format;
updatedTagData.currentTimeStamp = dropTag.currentTimeStamp
}
if (`${dropTag.type}`.toLowerCase() === "number") {
updatedTagData.decimalPlace = dropTag.decimalPlace
updatedTagData.isCurrency = dropTag.isCurrency
}
if (updatedTagData.type === "TEXT") {
updatedTagData.multiLine = dropTag.subType === "paragraph"
if (dropTag.subType === "password") {
updatedTagData.maskCharacter = mask.character
updatedTagData.maskType = mask.type
}
}
// if ("required" in updatedTagData && !updatedTagData.required) delete updatedTagData.required;
if (updatedTagData.subType === 'SINGLE SELECT') updatedTagData.subType = "SINGLE_SELECT"
if (updatedTagData.subType === 'MULTI SELECT') updatedTagData.subType = "MULTI_SELECT"
if (updatedTagData.options && !updatedTagData.options.length) delete updatedTagData.options;
if (!updatedTagData.id) delete updatedTagData.id;
if (!isDeleted) {
// sendTags.mod.push(updatedTagData);
tagsData.push(updatedTagData)
}
}
}
// for(const recipient of selectedRecipients) {
// const recrecipient
// }
tagsData = groupByRecipientId(tagsData);
sendTagsToRecipients(tagsData, accountId, transactionId);
(async () => {
const res = await api.put(`/api/accounts/${accountId}/transactions/${transactionId}`, {status: "SENT"})
console.log(res, "Check123")
})()
}, [isSend])
// Save Tags - END
const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault(); // Allows the drop event to work
};
// HANDLE DROP - START
const handleDrop = (event: React.DragEvent<HTMLDivElement>, docId: string, documentId: number, pageIndex: number) => {
console.log("// HANDLE DROP - START")
event.preventDefault();
const data = window.dragElemData;
if (!data) return;
const dragElemData = JSON.parse(data); // Get the dropped label
const field = { ...dragElemData }
if (!field.label) return;
// const field = fields.find((item) => item.label === dragElemData.label); // Find corresponding field
// if (!field) return; // If not found, exit
const dropZone = event.currentTarget.getBoundingClientRect();
const x = event.clientX - dropZone.left - dragElemData.offsetX;
const y = event.clientY - dropZone.top - dragElemData.offsetY;
const key = `${docId}_${pageIndex}`;
// const IconComponent = typeToIconMap[field.type] || <FaQuestionCircle />;
let prepData = {
properties: data.properties,
icon: typeToIconMap[field.label.toUpperCase()] || <FaQuestionCircle />,
type: dragElemData.label,
subType: (dragElemData.label in droppedTagsDefaultField) ? droppedTagsDefaultField[dragElemData.label] : '',
label: dragElemData.label,
dimensions: {
left: x,
top: y,
width: dragElemData.width,
height: dragElemData.height,
},
styles: dragElemData.label === "text" ? {
"font": "Great Vibes",
"italic": false,
"bold": false,
"underline": false,
"color": "black",
"textSize": 14.0
} : null,
documentId: docId,
pageIndex: pageIndex,
recipientId: dragElemData.recipientId,
recipientIndx: dragElemData.recipientIndx,
update: true,
isDeleted: false
}
if (prepData.type === "temporal") {
prepData.currentTimeStamp = true;
}
if (prepData.type.toLowerCase() === "number") {
prepData.decimalPlace = 0;
prepData.isCurrency = false;
}
const dataToSet: DroppedItemsObj = {
...droppedItems,
[key]: [...(droppedItems[key] || []),
{
...prepData,
radioGroups: dragElemData.label === "radio" ?
[
{
...prepData,
dimensions: {
...prepData.dimensions, top: 8, left: 10
}
},
{
...prepData, dimensions: {
...prepData.dimensions,
top: 8,
left: 10
}
}
]
:
[]
}],
}
if (dragElemData.label === "radio") {
setDroppedItems(dataToSet);
} else {
setDroppedItems(dataToSet);
}
setDroppedItemsCounter((prev) => prev + 1);
setTimeout(() => {
const tagIndex = key in droppedItems ? droppedItems[key].length : 0;
handleTagClick(key, tagIndex)
}, 0)
};
// HANDLE DROP - END
// HANDLE TAG MOUSE DOWN - START
const handleTagMouseDown = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number) => {
event.preventDefault();
let targetContainer = event?.currentTarget?.parentElement?.parentElement;
let targetElement = event?.currentTarget?.parentElement;
if (!targetContainer || !targetElement) return;
const containerRect = targetContainer.getBoundingClientRect();
const elementRect = targetElement.getBoundingClientRect();
// Calculate the initial offset (where the mouse was clicked inside the element)
const offsetX = event.clientX - elementRect.left;
const offsetY = event.clientY - elementRect.top;
const conScrollWidth = targetContainer?.scrollWidth;
const conScrollHeight = targetContainer?.scrollHeight;
const handleMouseMove = (event: MouseEvent) => {
// Get new X and Y positions relative to the container
let left = event.clientX - containerRect.left - offsetX;
let top = event.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));
// Apply the movement to the element
setDroppedItems({
...droppedItems,
[key]: Array.isArray(droppedItems[key]) // Ensure it's an array
? droppedItems[key].map((item, i) =>
i === index ? { ...item, dimensions: { ...item.dimensions, left, top }, update: true } : item
)
: [], // Provide a fallback in case it's undefined or not an array
});
};
const handleMouseUp = () => {
document.removeEventListener("pointermove", handleMouseMove);
document.removeEventListener("pointerup", handleMouseUp);
};
// Add event listeners
document.addEventListener("pointermove", handleMouseMove);
document.addEventListener("pointerup", handleMouseUp);
};
// HANDLE TAG MOUSE DOWN - END
// HANDLE EXPAND TAG - START
const handleExpandTag = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number) => {
console.log("HANDLE EXPAND TAG - START")
event.preventDefault(); // Prevent text selection issues
const expandingElemIcon = event.currentTarget;
const targetElement = expandingElemIcon.nextElementSibling?.parentElement;
const targetContainer = targetElement?.parentElement;
if (!targetContainer || !targetElement) return;
const elementRect = targetElement.getBoundingClientRect();
const startX = event.clientX;
const startY = event.clientY;
const startWidth = elementRect.width;
const startHeight = elementRect.height;
const handleMouseMove = (event: MouseEvent) => {
let newWidth = startWidth + (event.clientX - startX);
let newHeight = startHeight + (event.clientY - startY);
if (newHeight > 200 || newWidth > 400) {
if (newHeight > 200) {
newHeight = 200
}
if (newWidth > 400) {
newWidth = 400
}
}
// Apply the new width & height
setDroppedItems({
...droppedItems,
[key]: Array.isArray(droppedItems[key]) // Ensure it's an array
? droppedItems[key].map((item, i) =>
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 = () => {
document.removeEventListener("pointermove", handleMouseMove);
document.removeEventListener("pointerup", handleMouseUp);
};
document.addEventListener("pointermove", handleMouseMove);
document.addEventListener("pointerup", handleMouseUp);
};
// HANDLE EXPAND TAG - END
const handleTagClick = (key: string, index: number) => {
setSelectedTag({ key, index })
}
const handleRemoveTag = (key: string, targetIndex: number) => {
const tag = droppedItems[key][targetIndex];
const recipientId = tag.recipientId;
(async () => {
if ("id" in tag) {
try {
const response = await api.delete(`/api/accounts/${accountId}/transactions/${transactionId}/recipients/${recipientId}/tags/${tag.id}`)
if (response.status !== 200) throw "Tag Deletion error"
} catch (err) {
console.error("Tag Deletion error")
return;
}
}
setSelectedTag(null)
setDroppedItems(prevState => ({
...prevState,
[key]: prevState[key].map((item, index) =>
index === targetIndex ? { ...item, isDeleted: true } : item
)
}));
})()
}
const handleAddRadioClick = (key:string) => {
console.log("Handle Radio Clicled", key)
console.log(droppedItems, "line 525")
}
// const handleAddRadio = (e: React.MouseEvent<HTMLElement>, key: string, index: number) => {
// // const dataToSet: DroppedItemsObj = {
// // ...droppedItems,
// // [key]: [...(droppedItems[key] || []),
// // {
// // ...prepData,
// // radioGroups: dragElemData.label === "radio" ? [{ ...prepData }] : []
// // }],
// // }
// // const lastRadioElemRect = e.currentTarget?.parentElement.previousSibling.getBoundingClientRect();
// // console.log(lastRadioElemRect, "lastRadioElemRect")
// const setNewData = droppedItems;
// if (Array.isArray(setNewData[key][index].radioGroups) && setNewData[key][index].radioGroups?.length > 0) {
// setNewData[key][index].radioGroups?.push(setNewData[key][index].radioGroups[0])
// }
// setDroppedItems(setNewData);
// };
// const handleRadioTagMouseDown = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number, radioIndex: number) => {
// event.preventDefault();
// let targetContainer = event?.currentTarget?.parentElement;
// let targetElement = event?.currentTarget;
// if (!targetContainer || !targetElement) return;
// const containerRect = targetContainer.getBoundingClientRect();
// const elementRect = targetElement.getBoundingClientRect();
// // Calculate the initial offset (where the mouse was clicked inside the element)
// const offsetX = event.clientX - elementRect.left;
// const offsetY = event.clientY - elementRect.top;
// const handleMouseMove = (event: PointerEvent) => {
// // Get new X and Y positions relative to the container
// // let x = offsetX;
// // let y = offsetY;
// let x = event.clientX - elementRect.left;
// let y = event.clientY - elementRect.top;
// const newData = droppedItems;
// if (newData[key][index].radioGroups && newData[key][index].radioGroups.length > 0) {
// newData[key][index].radioGroups[radioIndex].dimensions.left = x;
// newData[key][index].radioGroups[radioIndex].dimensions.top = y;
// let topMin = Number.POSITIVE_INFINITY;
// let topMax = Number.NEGATIVE_INFINITY;
// let leftMin = Number.POSITIVE_INFINITY;
// let leftMax = Number.NEGATIVE_INFINITY;
// for (const radio of newData[key][index].radioGroups) {
// if (radio.dimensions.left < leftMin) {
// leftMin = radio.dimensions.left;
// }
// if (radio.dimensions.left > leftMax) {
// leftMax = radio.dimensions.left;
// }
// if (radio.dimensions.top < topMin) {
// topMin = radio.dimensions.top;
// }
// if (radio.dimensions.top > topMax) {
// topMax = radio.dimensions.top;
// }
// }
// newData[key][index].radioPosition = {
// topMin: topMin,
// topMax: topMax,
// leftMin: leftMin,
// leftMax: leftMax,
// width: leftMax - leftMin,
// height: topMax - topMin
// }
// newData[key][index].dimensions.left = x;
// newData[key][index].dimensions.top = y;
// }
// setDroppedItems({ ...newData });
// };
// const handleMouseUp = () => {
// document.removeEventListener("pointermove", handleMouseMove);
// document.removeEventListener("pointerup", handleMouseUp);
// };
// // Add event listeners
// document.addEventListener("pointermove", handleMouseMove);
// document.addEventListener("pointerup", handleMouseUp);
// }
// NEW DIRECTIONAL MOVEMENT HANDLER - START
const handleDirectionalMove = (direction: 'up' | 'down' | 'left' | 'right', stepSize: number = 5) => {
if (!selectedTag) return;
const { key, index } = selectedTag;
const currentItem = droppedItems[key]?.[index];
if (!currentItem) return;
let newLeft = currentItem.dimensions.left;
let newTop = currentItem.dimensions.top;
switch (direction) {
case 'up':
newTop = Math.max(0, newTop - stepSize);
break;
case 'down':
newTop = newTop + stepSize;
break;
case 'left':
newLeft = Math.max(0, newLeft - stepSize);
break;
case 'right':
newLeft = newLeft + stepSize;
break;
}
setDroppedItems({
...droppedItems,
[key]: Array.isArray(droppedItems[key])
? droppedItems[key].map((item, i) =>
i === index
? { ...item, dimensions: { ...item.dimensions, left: newLeft, top: newTop }, update: true }
: item
)
: [],
});
};
// Create a wrapper that matches DirectionalControls' expected signature
const directionalControlsHandler = (direction: 'up' | 'down' | 'left' | 'right') => {
handleDirectionalMove(direction, 5); // Use default stepSize of 5
};
return (
<>
{/* 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'>
{
selectedDocuments.length > 0 ? selectedDocuments.map((doc, indxDoc) => {
return (
<div key={indxDoc} 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.images && doc.images.length > 0 && doc.images.map((page, indx) => {
const key = `${doc.id}_${page.index}`;
return (
<div
key={indx}
id={`${doc.id}${indx}`}
onDrop={(e) => handleDrop(e, doc.id, indxDoc, page.index)}
onDragOver={handleDragOver}
className='drop-page-in shadow-md relative'
>
{/* DROPPED ITEMS - Render only the dropped items for this specific docId and page - STARTS */}
{droppedItems[key]?.map((item, index) => {
if (item.isDeleted) return;
const type = item.type.toUpperCase();
const IconComponent = typeToIconMap[type] || <FaQuestionCircle />;
const selectedRecipient = selectedRecipients.filter((obj, indx) => obj.id === item.recipientId);
return (
<div
key={index}
draggable="false"
className="absolute rounded dropped-item"
onClick={() => handleTagClick(key, index)}
style={{
left: `${item.dimensions.left}px`,
top: `${item.dimensions.top}px`,
width: item.type === "radio" ? `${item.dimensions.width + 20}px` : `${item.dimensions.width}px`,
height: item.type === "radio" ? `max-content` : `${item.dimensions.height}px`
}}
>
{/* If Selected Tag Recipient Info- START */}
{selectedTag?.key && selectedTag.key === key && selectedTag.index === index &&
<div className='absolute flex justify-between items-center w-full max-w-max bg-white top-[-22px] shadow z-20 text-sm rounded-t-sm'>
<div className='flex justify-center items-center gap-1 bg-white px-2 shadow'>
<p className='w-2.5 h-2.5 rounded'
style={{ background: selectedRecipient[0]?.color }}
></p>
<p
className=''>{IconComponent}
</p>
<p className='capitalize text-ellipsis whitespace-nowrap'>{item.label}</p>
<IoMdClose onClick={(e) => {
e.stopPropagation();
handleRemoveTag(key, index)
}} className='cursor-pointer' />
</div>
</div>}
{/* If Selected Tag Recipient Info- END */}
{/* Expand Circle - STARTS */}
{item.type !== "radio" && <div
onPointerDown={(e) => handleExpandTag(e, key, index)}
className='w-2.5 h-2.5 absolute bg-red-400 rounded-full bottom-[-8px] right-[-8px] cursor-nw-resize hover:bg-blue-400'>
</div>}
{/* Expand Circle - ENDS */}
{
item.type !== "radio" ?
<div
onPointerDown={(e) => handleTagMouseDown(e, key, index)}
// style={{ width: `${item.width}px !important` }}
className='p-2 rounded-sm h-full shadow opacity-40 cursor-grab w-full'
style={{ background: selectedRecipient[0]?.color }}
>
<p
className={`flex justify-center items-center w-full text-xl text-white h-full`}
// style={{ color: selectedRecipients[item.recipientIndx]?.color }}
>
{IconComponent}
</p>
</div>
:
<>
<div>
{/* Radio - Container - START */}
<div>
{/* Radio- Item - START */}
<div
onPointerDown={(e) => handleTagMouseDown(e, key, index)}
// style={{ width: `${item.width}px !important` }}
className='p-2 rounded-sm h-full shadow opacity-40 cursor-grab w-full'
style={{ background: selectedRecipient[0]?.color }}
>
<p
className={`flex justify-center items-center w-full text-xl text-white h-full`}
// style={{ color: selectedRecipients[item.recipientIndx]?.color }}
>
{IconComponent}
</p>
</div>
{/* Radio- Item - END */}
</div>
{/* Radio - Container - END */}
<IoAdd onClick={() => handleAddRadioClick(key)} className='ml-[50%] translate-x-[-50%] cursor-pointer' />
</div>
</>
}
</div>
)
}
)}
{/* Render only the dropped items for this specific docId and page - ENDS */}
<img
style={{ "minWidth": page.width, "minHeight": page.height, "maxWidth": page.width, "maxHeight": page.height }}
draggable="false"
width={page.width}
height={page.height}
src={page.src}
loading='lazy'
/>
{/* 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.images && doc.images.length}
</p>
{/* <p className='absolute top-[50%] translate-y-[-50%] rotate-[-90deg] text-xs right-[-140px] text-slate-600'>
Document {indxDoc + 1} {doc.name}
</p> */}
{/* Side details of documents Pages and document Name - END */}
</div>
)
})
}
</div>
</div>
)
}) : <Loader />
}
</div>
{selectedTag && <RightSideBar selectedTag={droppedItems[selectedTag.key][selectedTag.index]} setDroppedItems={setDroppedItems} selTagKey={selectedTag.key} selTagIndx={selectedTag.index} DirectionalControlsProps={{
onMove: directionalControlsHandler,
disabled: false,
stepSize: 5,
className: ''
}} />}
{/* Center Doc Container - END */}
</>
)
}
export default DocumentContainer;