SME-Web/src/components/dashboard/Dashboard.tsx

210 lines
8.6 KiB
TypeScript

// Dashboard.jsx - Updated version
import React, { useEffect, useLayoutEffect } from 'react'
import SideBar from './SideBar'
import { Outlet, useNavigate } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { RootState } from '../../store/store'
import { UserState } from '../../store/slices/userSlice'
import Loader from './Loader'
import { clearTransaction, TRANSACTION_STATUS_ENUMS } from '../../store/slices/transactionSlice'
import { resetSelDoc } from '../../store/slices/selectedDocsSlice'
import { resetSelRecipient } from '../../store/slices/selectedRecipientsSlice'
import { hideLoader, showLoader } from '../../store/slices/loaderSlice'
import SignModal from '../modal/SignModal'
import confetti from 'canvas-confetti'
import { FaCheckCircle } from 'react-icons/fa'
import { IoClose } from 'react-icons/io5'
import CommonNav from '../CommonNav'
function Dashboard() {
const [showSideBar, setShowSideBar] = React.useState(true)
const [showConfetti, setShowConfetti] = React.useState(false)
const [isMobile, setIsMobile] = React.useState(false)
const navigate = useNavigate();
const dispatch = useDispatch();
const user: UserState = useSelector((state: RootState) => state.user);
const globalLoader = useSelector((state: RootState) => state.loader)
const globalModalIsOpen = useSelector((state: RootState) => state.modal.isOpen)
const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments)
const documentSignType = useSelector((state: RootState) => state.selectedDocuments.signType)
const transactionStatus = useSelector((state: RootState) => state.transaction.status)
// Check if cookie already exists - Redirect to Dashboard
useLayoutEffect(() => {
if (transactionStatus === TRANSACTION_STATUS_ENUMS.TRANSACTION_SEND_SUCCESS || transactionStatus === TRANSACTION_STATUS_ENUMS.TRANSACTION_INITIATED || transactionStatus === TRANSACTION_STATUS_ENUMS.TRANSACTION_SEND_FAILURE) {
dispatch(resetSelDoc())
dispatch(resetSelRecipient())
dispatch(clearTransaction())
if (transactionStatus === TRANSACTION_STATUS_ENUMS.TRANSACTION_SEND_SUCCESS) {
setShowConfetti(true)
}
return
}
}, [])
useEffect(() => {
if (transactionStatus === TRANSACTION_STATUS_ENUMS.TRANSACTION_SEND_SUCCESS || transactionStatus === TRANSACTION_STATUS_ENUMS.TRANSACTION_INITIATED) return;
if (selectedDocuments === null || (Array.isArray(selectedDocuments) && !selectedDocuments.length)) {
dispatch(resetSelDoc())
}
dispatch(showLoader("Loading ..."));
if (documentSignType && transactionStatus === TRANSACTION_STATUS_ENUMS.TRANSACTION_NOT_INITIATED) {
if (documentSignType === 'self-sign') {
setTimeout(() => {
navigate('/process-step-one');
}, 1000)
return
} else if (documentSignType === 'multiple-sign') {
setTimeout(() => {
navigate('/process-step-one');
}, 1000)
return
}
}
dispatch(hideLoader());
}, [documentSignType])
useEffect(() => {
if (showConfetti) {
const duration = 3000;
const end = Date.now() + duration;
const interval = setInterval(() => {
if (Date.now() > end) {
clearInterval(interval);
return;
}
confetti({
particleCount: 80, // more particles
angle: Math.random() * 360, // fire in random direction
spread: 220, // wider spread
startVelocity: 15, // more power
scalar: 1.2, // bigger pieces (default is 1)
origin: {
x: Math.random(),
y: Math.random() * 0.6,
},
zIndex: 9999,
});
}, 350); // fire every 150ms
}
}, [showConfetti]);
useEffect(() => {
// Function to handle window resize
const handleResize = () => {
const mobile = window.innerWidth <= 768;
setIsMobile(mobile);
if (mobile) {
setShowSideBar(false); // hide sidebar on mobile by default
} else {
setShowSideBar(true); // show sidebar on desktop
}
};
// Set sidebar visibility on mount
handleResize();
// Add event listener
window.addEventListener('resize', handleResize);
// Cleanup listener on unmount
return () => window.removeEventListener('resize', handleResize);
}, []);
return (
<>
<>
{
showConfetti && (
<div className="absolute top-0 left-0 w-full h-full z-[9999] bg-white/80 backdrop-blur-sm flex items-center justify-center">
{/* <Confetti width={width} height={height} /> */}
<div className="relative bg-white bg-opacity-90 backdrop-blur-lg border border-green-200 shadow-xl rounded-md px-8 py-6 w-[90%] max-w-sm text-center animate-fade-in-up">
{/* Close Icon */}
<button
onClick={() => setShowConfetti(false)} // or whatever logic hides the modal
className="absolute top-2 right-2 text-gray-500 hover:text-gray-700"
aria-label="Close"
>
<IoClose className="text-2xl" />
</button>
{/* Success Icon */}
<FaCheckCircle className="text-green-500 text-5xl mb-4 mx-auto drop-shadow-lg" />
{/* Message */}
<h2 className="text-2xl font-semibold text-gray-800 mb-1">Transaction Successful</h2>
<p className="text-gray-600 text-sm">Your transaction has been created and saved successfully.</p>
</div>
</div>
)
}
</>
{
user?.authorized &&
<div className={`relative`}>
{/* Mobile Overlay when sidebar is open */}
{isMobile && showSideBar && (
<div
className="fixed inset-0 bg-black/30 bg-opacity-50 z-40"
onClick={() => setShowSideBar(false)}
/>
)}
{/* Complete Dashboard Back Side SideBar */}
<div className={`relative w-full h-screen overflow-hidden bg-[var(--dashBoardBg)] ${(globalLoader.isLoading || globalModalIsOpen) ? 'pointer-events-none' : ''}`}>
<SideBar
showSideBar={showSideBar}
setShowSideBar={setShowSideBar}
isMobile={isMobile}
/>
{/* On Top Main Content - START */}
<div
className={`overflow-y-auto absolute no-scrollbar h-full right-0 bottom-0 overflow-hidden bg-[var(--mainViewBg)]`}
style={{
width: !isMobile
? (showSideBar ? 'calc(100% - 250px)' : 'calc(100% - 60px)')
: '100%', // Full width on mobile
transition: 'width 0.6s ease'
}}
>
{/* Main Content */}
<div>
<CommonNav
showSideBar={showSideBar}
setShowSideBar={setShowSideBar}
isMobile={isMobile}
/>
<Outlet />
</div>
</div>
{/* On Top Main Content - END */}
</div>
{globalLoader.isLoading && <Loader />}
{globalModalIsOpen && <SignModal />}
</div>}
</>
)
}
export default Dashboard