SME-Web/src/components/process/processStepTwo/documentPages/DocumentPages.tsx

263 lines
12 KiB
TypeScript

import React, { useEffect, useState } from 'react'
import { RootState } from '../../../../store/store';
import { useSelector } from 'react-redux';
import { DroppedItemsObj } from '../DocumentContainer';
import { MdKeyboardArrowUp, MdMoreVert } from 'react-icons/md';
import { PiTagSimpleFill } from 'react-icons/pi';
const DocumentPages: React.FC<{
isPages: boolean;
droppedItems: DroppedItemsObj;
setIsPages: React.Dispatch<React.SetStateAction<boolean>>;
}> = ({ isPages, droppedItems, setIsPages }) => {
type RecipientPageTagInfo = {
color: string;
recipientIndex: number;
recipientTagCount?: number;
};
type DocumentTagsMapping = {
[documentId: string]: {
[pageIndex: string]: RecipientPageTagInfo[];
};
};
const selectedDocuments = useSelector((state: RootState) => state.documents.documents)
const [documentPagesTagsMapping, setDocumentPagesTagsMapping] = useState<DocumentTagsMapping>({});
const recipients = useSelector((state: RootState) => state.selectedRecipients.recipients);
const [openDocs, setOpenDocs] = useState<Record<string, boolean>>(
() => Object.fromEntries(selectedDocuments.map((d, i) => [d.id, i === 0]))
)
const [activePage, setActivePage] = useState<string | null>(
selectedDocuments[0] ? `${selectedDocuments[0].id}_0` : null
)
const toggleDoc = (docId: string) => {
setOpenDocs(prev => ({ ...prev, [docId]: !prev[docId] }))
}
const goToPage = (docId: string, pageIndex: number) => {
const key = `${docId}_${pageIndex}`
setActivePage(key)
window.location.hash = docId + "" + pageIndex
}
// useEffect(() => {
// setTimeout(() => {
// let documentPagesTagsMappingLocal: {
// [documentId: string]: {
// [pageIndex: number]: [number, string];
// };
// }[] = [];
// recipients && recipients.length && recipients.forEach((selectedRecipient, selectedRecipientIndx) => {
// const selectedRecipientColor = selectedRecipient.color
// let activeRecipientTagsCount = 0;
// droppedItems && Object.keys(droppedItems).length > 0 && Object.keys(droppedItems).forEach(key => {
// activeRecipientTagsCount = (droppedItems[key] && droppedItems[key].length) > 0 ? droppedItems[key].reduce((acc, item) => !item.isDeleted && item.recipientIndx == selectedRecipientIndx ? acc + 1 : acc, 0) : 0;
// if (activeRecipientTagsCount == 0) return;
// const [documentId, pageIndex] = key.split("_");
// if (!documentPagesTagsMappingLocal[documentId]) {
// documentPagesTagsMappingLocal[documentId] = {};
// }
// documentPagesTagsMappingLocal.push({ [documentId]: { [pageIndex]: [activeRecipientTagsCount, selectedRecipientColor] } })
// })
// })
// setDocumentPagesTagsMapping(documentPagesTagsMappingLocal)
// }, 300)
// // }, [droppedItems, selectedRecipientIndx])
// }, [droppedItems])
useEffect(() => {
setTimeout(() => {
let documentTagsMappingLocal: DocumentTagsMapping = {};
recipients &&
recipients.length &&
recipients.forEach((selectedRecipient, selectedRecipientIndx) => {
const selectedRecipientColor = selectedRecipient.color;
droppedItems &&
Object.keys(droppedItems).length > 0 &&
Object.keys(droppedItems).forEach(key => {
const activeRecipientTagsCount =
(droppedItems[key] && droppedItems[key].length) > 0
? droppedItems[key].reduce((acc, item) => {
return !item.isDeleted &&
item.recipientIndx == selectedRecipientIndx
? acc + 1
: acc;
}, 0)
: 0;
if (activeRecipientTagsCount === 0) return;
const [documentId, pageIndex] = key.split("_");
// Create document object
if (!documentTagsMappingLocal[documentId]) {
documentTagsMappingLocal[documentId] = {};
}
// Create page array
if (!documentTagsMappingLocal[documentId][pageIndex]) {
documentTagsMappingLocal[documentId][pageIndex] = [];
}
// Push recipient info
documentTagsMappingLocal[documentId][pageIndex].push({
color: selectedRecipientColor,
recipientIndex: selectedRecipientIndx,
recipientTagCount: activeRecipientTagsCount,
});
});
});
setDocumentPagesTagsMapping(documentTagsMappingLocal);
}, 300);
}, [droppedItems]);
useEffect(() => {
setTimeout(() => {
if (!isPages) return
const docPagesCon = document.getElementById("document-pages");
if (docPagesCon) {
docPagesCon.focus();
}
}, 0)
}, [isPages]);
return (
<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) => (
<div key={indx} className="border-b border-slate-200 pb-3 mb-1">
{/* Section label (if any) */}
{document.section && (
<p className="text-[10px] font-semibold uppercase tracking-wide text-slate-400 px-3 pt-2 pb-1">
{document.section}
</p>
)}
{/* Document Header */}
<div
onClick={() => toggleDoc(document.id)}
className="flex items-start justify-between px-3 py-2.5 cursor-pointer hover:bg-slate-50 transition-colors"
>
<div>
<p className="text-[13px] font-medium text-slate-800 leading-tight">{document.name}</p>
<p className="text-[11px] text-slate-400 mt-0.5">
{document.pages?.length} {document.pages?.length === 1 ? 'page' : 'pages'}
</p>
</div>
<MdKeyboardArrowUp
size={20}
className={`text-slate-400 mt-0.5 flex-shrink-0 transition-transform duration-200 ${openDocs[document.id] ? '' : 'rotate-180'}`}
/>
</div>
{/* Page Thumbnails */}
{openDocs[document.id] && (
<div className="flex flex-col px-2">
{document.pages?.map((_: any, pageIndex: number) => {
const key = `${document.id}_${pageIndex}`
const isActive = activePage === key
return (
<div
key={pageIndex}
onClick={() => goToPage(document.id, pageIndex)}
className="flex flex-col items-center py-2 px-1 rounded-md cursor-pointer hover:bg-slate-50 transition-colors"
>
{/* Big Thumbnail */}
<div className={`relative sm:p-2 lg:p-4 bg-slate-100 rounded border flex items-center justify-center overflow-hidden
${isActive ? 'border-blue-500 border-2' : 'border-slate-200'}`}
>
{document.thumbnail ? (
<img
src={"data:image/png;base64," + document.thumbnail}
alt={`Page ${pageIndex + 1}`}
className="w-[140px] h-[180px] h-full object-cover"
/>
) : (
<div className="text-slate-300 text-4xl">Document</div>
)}
{/* Page number + dots menu */}
<div className="absolute bottom-0 bg-slate-800 flex items-center justify-between w-full pl-4 pr-2 py-3 bg-white">
<span className="text-[13px] text-slate-500">{pageIndex + 1}</span>
{
// <>
// <button
// onClick={(e) => { e.stopPropagation(); /* open context menu */ }}
// className="text-slate-400 hover:text-slate-600 hover:bg-slate-100 rounded p-0.5"
// >
// <MdMoreVert size={18} />
// </button>
// </>
}
</div>
<div className='absolute top-4 left-2 h-[80%] overflow-y-auto overflow-x-hidden'>
{documentPagesTagsMapping[document.id]?.[pageIndex]?.length > 0 && (
<>
{documentPagesTagsMapping[document.id][pageIndex].map((tagInfo, indx) => (
<div key={indx} className='relative'>
{/* Count */}
{/* Optional */}
{/* <span className='absolute text-white text-[9px] font-medium top-[50%] left-[50%] transform -translate-x-1/2 -translate-y-1/2 pointer-events-none select-none z-10'>
{tagInfo.recipientTagCount}
</span> */}
{/* Tag */}
<PiTagSimpleFill
style={{
fontSize: '1.2rem',
color: tagInfo.color,
}}
/>
</div>
))}
</>
)}
</div>
</div>
</div>
)
})}
</div>
)}
</div>
))}
</div>
)
}
export default DocumentPages