jai #16

Merged
jaipandey merged 4 commits from jai into main 2025-08-05 06:44:08 +00:00
9 changed files with 465 additions and 41 deletions
Showing only changes of commit 7b091a9dd5 - Show all commits

View File

@ -94,7 +94,8 @@ const App = () => {
{/* Links work wothout Login */} {/* Links work wothout Login */}
<Route path="/login" element={<Login />} /> <Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} /> <Route path="/register" element={<Register />} />
<Route path="/sign/:recipientId" element={<SignDocument />} /> <Route path="/sign/:recipientId/:signType" element={<SignDocument />} />
<Route path="/sign/:recipientId/" element={<SignDocument />} />
<Route path="/view" element={<DocView />} /> <Route path="/view" element={<DocView />} />
{/* Links work wothout Login */} {/* Links work wothout Login */}

View File

@ -0,0 +1,380 @@
import React, { useState, useEffect } from 'react';
import {
FiDownload,
FiCheckCircle,
FiZap,
FiShield,
FiClock,
FiFileText,
FiX,
} from 'react-icons/fi';
import { IoMdArrowRoundBack } from 'react-icons/io';
import { useParams } from 'react-router-dom';
import { SignTypeEnum } from '../../utlity/types';
const SignCompletionScreen: React.FC = () => {
const { signType } = useParams();
const [showDownloadModal, setShowDownloadModal] = useState(false);
const [animationPhase, setAnimationPhase] = useState(0);
useEffect(() => {
// Trigger animation phases sequentially
const timers = [
setTimeout(() => setAnimationPhase(1), 200),
setTimeout(() => setAnimationPhase(2), 800),
setTimeout(() => setAnimationPhase(3), 1400),
setTimeout(() => setAnimationPhase(4), 2000),
];
return () => timers.forEach(clearTimeout);
}, []);
const handleDownload = (format: string) => {
console.log(`Downloading document in ${format} format`);
const content = `Signed document - ${new Date().toISOString()}`;
const blob = new Blob([content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `signed-document.${format.toLowerCase()}`;
a.click();
URL.revokeObjectURL(url);
};
return (
<div className="min-h-screen w-screen z-1000 bg-gradient-to-br from-slate-50/50 via-blue-50 to-indigo-200/40 flex items-center justify-center p-4 overflow-hidden absolute top-0 left-0">
<style jsx>{`
:root {
--primary: #3D74B6;
--primaryLight: #ffffff;
--primaryLight2: #6a92c2;
--primaryLight3: #dae9de;
--dashBoardBg: #ffffff;
--mainViewBg: #edeaeb;
--highlightBg1: #edeaeb;
--menuTextCol: #98a0a8;
--menuTextColActive: #3D74B6;
--menuBgColActive: #edeaeb;
--menuTextHoverCol: #e7e7e7;
--greyTextCol: #98a0a8;
--lightGreyCol: #e1e1e1;
--compBgCol: #ffffff;
--avatarBgCol: #3D74B6;
--avatarTextCol: #ffffff;
--profileMenuModalBg: #ffffff;
--profileMenuModalTextCol: #98a0a8;
--profileMenuModalTextColActive: #2d2d2d;
--profileMenuModalBgColActive: #edeaeb;
--sendForSignTextCol: #ffffff;
--sendForSignBgCol: #d02f56;
--sendForSignDropDownText: #000000;
--sendForSignDropDownBg: #ffffff;
--sendForSignDropDownHover: #e7e7e7;
--loaderBg: #ffffff;
--modalBg: #ffffff;
--hideModalBg: #2d2d2d;
--processStepOneTextHead: #000000;
--modalSubmitBG: #1919d7;
--modalSubmitBGHover: #395ee1;
}
.completion-container {
animation: fadeInScale 1.2s cubic-bezier(0.16, 1, 0.3, 1);
}
.success-icon {
animation: successPulse 2s ease-out infinite;
}
.floating-particles {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
pointer-events: none;
}
.particle {
position: absolute;
width: 8px;
height: 8px;
background: linear-gradient(45deg, var(--primary), var(--primaryLight2));
border-radius: 50%;
animation: float 6s ease-in-out infinite;
opacity: 0.6;
}
.particle:nth-child(1) { top: 20%; left: 10%; animation-delay: 0s; }
.particle:nth-child(2) { top: 60%; left: 20%; animation-delay: 1s; }
.particle:nth-child(3) { top: 30%; left: 80%; animation-delay: 2s; }
.particle:nth-child(4) { top: 80%; left: 70%; animation-delay: 1.5s; }
.particle:nth-child(5) { top: 10%; left: 60%; animation-delay: 0.5s; }
.particle:nth-child(6) { top: 70%; left: 40%; animation-delay: 2.5s; }
.premium-glow {
box-shadow:
0 0 0 1px rgba(255, 255, 255, 0.1),
0 4px 32px rgba(61, 116, 182, 0.15),
0 16px 64px rgba(61, 116, 182, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.1);
}
.premium-card {
background: linear-gradient(135deg,
rgba(255, 255, 255, 0.95) 0%,
rgba(255, 255, 255, 0.9) 100%);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.status-badge {
background: linear-gradient(135deg, #10b981, #059669);
box-shadow: 0 4px 16px rgba(16, 185, 129, 0.3);
}
.download-btn-primary {
background: linear-gradient(135deg, var(--primary), var(--primaryLight2));
box-shadow: 0 8px 24px rgba(61, 116, 182, 0.3);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.download-btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 12px 32px rgba(61, 116, 182, 0.4);
}
.download-btn-secondary {
background: rgba(255, 255, 255, 0.8);
border: 2px solid rgba(61, 116, 182, 0.2);
backdrop-filter: blur(10px);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.download-btn-secondary:hover {
transform: translateY(-2px);
background: rgba(255, 255, 255, 0.95);
border-color: var(--primary);
}
.modal-backdrop {
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(8px);
animation: fadeIn 0.3s ease-out;
}
.modal-content {
animation: modalSlideUp 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes fadeInScale {
0% {
opacity: 0;
transform: scale(0.9) translateY(20px);
}
100% {
opacity: 1;
transform: scale(1) translateY(0);
}
}
@keyframes successPulse {
0%, 100% {
transform: scale(1);
box-shadow: 0 0 0 0 var(--primary);
}
50% {
transform: scale(1.05);
box-shadow: 0 0 0 20px rgba(61, 116, 182, 0); /* var(--primary) with 0 alpha */
}
}
@keyframes float {
0%, 100% {
transform: translateY(0px) rotate(0deg);
opacity: 0.6;
}
50% {
transform: translateY(-20px) rotate(180deg);
opacity: 1;
}
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes modalSlideUp {
0% {
opacity: 0;
transform: translateY(50px) scale(0.9);
}
100% {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.fade-in-up {
animation: fadeInUp 0.8s ease-out forwards;
opacity: 0;
}
.fade-in-up-delay-1 {
animation: fadeInUp 0.8s ease-out 0.3s forwards;
opacity: 0;
}
.fade-in-up-delay-2 {
animation: fadeInUp 0.8s ease-out 0.6s forwards;
opacity: 0;
}
.fade-in-up-delay-3 {
animation: fadeInUp 0.8s ease-out 0.9s forwards;
opacity: 0;
}
@keyframes fadeInUp {
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in-up,
.fade-in-up-delay-1,
.fade-in-up-delay-2,
.fade-in-up-delay-3 {
transform: translateY(30px);
}
`}</style>
{/* Floating Particles Background */}
<div className="floating-particles">
<div className="particle"></div>
<div className="particle"></div>
<div className="particle"></div>
<div className="particle"></div>
<div className="particle"></div>
<div className="particle"></div>
</div>
{/* Main Completion Screen */}
<div className="completion-container w-full max-w-[50vw]">
<div className="premium-card premium-glow rounded-3xl p-8 text-center relative overflow-hidden">
{/* Success Icon */}
<div className="relative mb-4">
<div className="success-icon inline-flex items-center justify-center w-20 h-20 bg-[var(--primary)] rounded-full mb-6">
<FiCheckCircle className="w-12 h-12 text-white" />
</div>
<FiZap className="absolute top-0 right-1/3 w-6 h-6 text-yellow-400 animate-pulse" />
<FiZap className="absolute bottom-2 left-1/3 w-4 h-4 text-yellow-400 animate-pulse" style={{ animationDelay: '0.5s' }} />
</div>
{/* Main Success Message */}
<div className={`mb-2 ${animationPhase >= 1 ? 'fade-in-up' : ''}`}>
<h1 className="text-xl font-bold text-gray-900 mb-2">
Signature Complete!
</h1>
<p className="text-md text-gray-600 mb-3">
Your document has been successfully signed.
</p>
</div>
{/* Action Buttons */}
<div className='flex justify-between items-center gap-2'>
<button
// onClick={() => setShowDownloadModal(true)}
className="w-full download-btn-secondary text-gray-400 py-2 px-2 rounded-xl font-medium flex items-center justify-center"
>
<FiDownload className="w-5 h-5 mr-3" />
Download Signed Document
</button>
{signType === SignTypeEnum.selfSign ? <a
href="http://localhost:5173/"
// target="_blank"
rel="noopener noreferrer"
className="w-full download-btn-secondary text-gray-400 py-2 px-2 rounded-xl font-medium flex items-center justify-center"
>
{/* <a> */}
<IoMdArrowRoundBack className="w-5 h-5 mr-3" />
Back Sign Made Easy
{/* </a> */}
</a> :
<a
href="https://signmadeasy.com/"
// target="_blank"
rel="noopener noreferrer"
className="w-full download-btn-secondary text-gray-400 py-2 px-2 rounded-xl font-medium flex items-center justify-center"
>
{/* <a> */}
<IoMdArrowRoundBack className="w-5 h-5 mr-3" />
Visit Sign Made Easy
{/* </a> */}
</a>
}
</div>
{/* Additional Info */}
<div className={`mt-8 pt-3 border-t border-gray-200 border-opacity-50`}>
<p className="text-sm text-gray-500">
Your document is signed and ready. You can download it or return to the sign made easy.
</p>
</div>
</div>
</div>
{/* Premium Download Modal */}
{/* {showDownloadModal && (
<div className="fixed inset-0 bg-white/60 backdrop-blur-sm bg-opacity-50 flex items-center justify-center p-4 z-50">
<div className="modal-content premium-card premium-glow rounded-3xl p-8 w-full max-w-md relative">
<button
onClick={() => setShowDownloadModal(false)}
className="absolute top-6 right-6 p-2 hover:bg-gray-100 rounded-full transition-colors duration-200"
>
<FiX className="w-5 h-5 text-gray-500" />
</button>
<div className="text-center mb-4">
<div className="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-full mb-4">
<FiDownload className="w-8 h-8 text-white" />
</div>
<h2 className="text-2xl font-bold text-gray-900 mb-2">Choose Download Format</h2>
<p className="text-gray-600">Select your preferred file format</p>
</div>
<div className="space-y-4">
<button
onClick={() => handleDownload('PDF')}
className="w-full download-btn-primary text-white py-4 px-6 rounded-xl font-semibold flex items-center justify-center"
>
<FiFileText className="w-5 h-5 mr-3" />
Download as PDF
<span className="ml-auto text-sm opacity-80">Recommended</span>
</button>
<button
onClick={() => handleDownload('DOCX')}
className="w-full download-btn-secondary text-gray-700 py-4 px-6 rounded-xl font-semibold flex items-center justify-center"
>
<FiFileText className="w-5 h-5 mr-3" />
Download as DOCX
</button>
</div>
<div className="mt-6 pt-6 border-t border-gray-200 border-opacity-50 text-center">
<p className="text-xs text-gray-500">
Files are automatically encrypted and timestamped
</p>
</div>
</div>
</div>
)} */}
</div>
);
};
export default SignCompletionScreen;

View File

@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
import axios from "axios" import axios from "axios"
import { RootState } from "../../store/store"; import { RootState } from "../../store/store";
import { useParams } from "react-router-dom" import { useNavigate, useParams } from "react-router-dom"
import { DroppedItem, DroppedItemsObj, TagsTypes } from "../../utlity/types"; import { DroppedItem, DroppedItemsObj, TagsTypes } from "../../utlity/types";
import Loader from "../dashboard/Loader"; import Loader from "../dashboard/Loader";
@ -24,6 +24,7 @@ import DocumentPages from "./DocumentPages";
import FieldList from "../process/processStepTwo/FieldList"; import FieldList from "../process/processStepTwo/FieldList";
import typeToIconMap from "../../helper/iconMap"; import typeToIconMap from "../../helper/iconMap";
import { droppedTagsDefaultField } from "../process/processStepTwo/DocumentContainer"; import { droppedTagsDefaultField } from "../process/processStepTwo/DocumentContainer";
import SignCompletionScreen from "./SignCompletionScreen";
@ -173,6 +174,7 @@ const SignDocument = () => {
const [transparentTags, setTransparentTags] = useState<boolean>(false); const [transparentTags, setTransparentTags] = useState<boolean>(false);
const [provideTags, setProvideTags] = useState(false) const [provideTags, setProvideTags] = useState(false)
const [showCompletionScreen, setShowCompletionScreen] = useState(false)
const [saved, setSaved] = useState<SaveType>({ const [saved, setSaved] = useState<SaveType>({
saveType: null, saveType: null,
@ -181,6 +183,7 @@ const SignDocument = () => {
initial: null, initial: null,
}); });
const navigate = useNavigate();
const [signConfObj, setSignConfObj] = useState<SignConfTypeObj | {}>({}); const [signConfObj, setSignConfObj] = useState<SignConfTypeObj | {}>({});
@ -314,6 +317,10 @@ const SignDocument = () => {
setProvideTags(true) setProvideTags(true)
} }
if (res.data.status ==="COMPLETED" ) {
setShowCompletionScreen(true)
}
setTimeout(() => { setTimeout(() => {
dispatch(hideLoader()); dispatch(hideLoader());
}, 600); }, 600);
@ -466,7 +473,10 @@ const SignDocument = () => {
theme: "light", theme: "light",
transition: Bounce, transition: Bounce,
}); });
// Completion Sign Screen Modal and download file
setShowCompletionScreen(true)
}, 800) }, 800)
} }
}) })
.catch((err) => { .catch((err) => {
@ -766,7 +776,7 @@ const SignDocument = () => {
<div className={`w-full h-screen overflow-hidden relative ${(globalLoader.isLoading) ? 'pointer-events-none overflow-hidden' : ''}`}> <div className={`w-full h-screen overflow-hidden relative ${(globalLoader.isLoading) ? 'pointer-events-none overflow-hidden' : ''}`}>
<> <>
{/* <TermsModal showTerms={showTerms} setShowTerms={setShowTerms} recipientId={recipientId || ""} /> */} {/* <TermsModal showTerms={showTerms} setShowTerms={setShowTerms} recipientId={recipientId || ""} /> */}
{showCompletionScreen && <SignCompletionScreen />}
<form className="bg-slate-100" <form className="bg-slate-100"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => handleFormSubmit(e)} onSubmit={(e: React.FormEvent<HTMLFormElement>) => handleFormSubmit(e)}
> >
@ -1329,6 +1339,9 @@ const SignDocument = () => {
</div> </div>
{/* <SignatureCon recipientId={recipientId as string} openSign={openSign} setOpenSign={setOpenSign} savedSignature={savedSignature} setSavedSignature={setSavedSignature} /> {/* <SignatureCon recipientId={recipientId as string} openSign={openSign} setOpenSign={setOpenSign} savedSignature={savedSignature} setSavedSignature={setSavedSignature} />
<InitialCon openInitial={openInitial} setOpenInitial={setOpenInitial} savedInitial={savedInitial} setSavedInitial={setSavedInitial} /> */} <InitialCon openInitial={openInitial} setOpenInitial={setOpenInitial} savedInitial={savedInitial} setSavedInitial={setSavedInitial} /> */}

View File

@ -231,7 +231,7 @@ const Cards: React.FC<CardsProps> = ({ type = 'dashboard', onOpenModal, onDateRa
</div> </div>
</div> </div>
</div> : </div> :
<div className="flex flex-wrap gap-2 justify-between"> <div className="flex flex-wrap gap-2 justify-end">
{cards.map((card, index) => ( {cards.map((card, index) => (
<div <div
key={card.title} key={card.title}

View File

@ -299,7 +299,7 @@ const ProcessStepOne = () => {
try { try {
const res = await api.put(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`, { status: "SENT" }) const res = await api.put(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`, { status: "SENT" })
console.log(res, "Check123"); console.log(res, "Check123");
navigate(`/sign/${recipientId}`); navigate(`/sign/${recipientId}/self_sign`);
} catch (err) { } catch (err) {
console.log("Error Transaction Sent", err.message); console.log("Error Transaction Sent", err.message);
} }

View File

@ -40,11 +40,13 @@ export const droppedTagsDefaultField: DroppedTagsDefaultFieldType = {
} }
interface DocumentContainerProps { interface DocumentContainerProps {
transactionSaving: boolean;
setTransactionSaving: React.Dispatch<React.SetStateAction<boolean>>;
isSend: boolean | null; isSend: boolean | null;
setIsSend: React.Dispatch<React.SetStateAction<boolean | null>>; setIsSend: React.Dispatch<React.SetStateAction<boolean | null>>;
} }
const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => { const DocumentContainer: React.FC<DocumentContainerProps> = ({ transactionSaving, setTransactionSaving, isSend }) => {
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 }>();
@ -75,8 +77,6 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
selectedDocuments.length === 0 && dispatch(fetchDocuments({ accountId, transactionId })); selectedDocuments.length === 0 && dispatch(fetchDocuments({ accountId, transactionId }));
}, []) }, [])
console.log(droppedItems, "line 78")
// FETCHING TAG - START // FETCHING TAG - START
useEffect(() => { useEffect(() => {
if (selectedRecipients.length === 0) return; if (selectedRecipients.length === 0) return;
@ -165,8 +165,8 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
updatedData[recipientId] = updateTags updatedData[recipientId] = updateTags
} }
const requests = Object.entries(updatedData).filter(([recipientId, tags]) => {
const requests = Object.entries(updatedData).map(([recipientId, tags]) => { if (tags.length === 0) return false;
return api.put( return api.put(
`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}/recipients/${recipientId}/tags`, `/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}/recipients/${recipientId}/tags`,
tags tags
@ -192,7 +192,7 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
const handleTransactionProcess = async (save: boolean = false) => { const handleTransactionProcess = async (save: boolean = false) => {
console.log(droppedItems, "called Line 189"); console.log(droppedItems, "called Line 189");
if (Object.keys(droppedItems).length === 0) return;
if (!save && isSend === null) return; if (!save && isSend === null) return;
!save && dispatch(showLoader("Loading ...")) !save && dispatch(showLoader("Loading ..."))
@ -293,28 +293,21 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
} }
} }
// for(const recipient of selectedRecipients) {
// const recrecipient
// }
tagsData = groupByRecipientId(tagsData); tagsData = groupByRecipientId(tagsData);
console.log(tagsData, "Line 302");
console.log("Hefre is the line 299", tagsData);
await sendTagsToRecipients(tagsData, accountId, transactionId); await sendTagsToRecipients(tagsData, accountId, transactionId);
// SENDING Transaction - START // SENDING Transaction - START
// if (!save) { if (!save) {
// const res = await api.put(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`, { status: "SENT" }) const res = await api.put(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`, { status: "SENT" })
// // const res = await api.put(`/api/accounts/${accountId}/transactions/${transactionId}`, { status: "SENT" }) // const res = await api.put(`/api/accounts/${accountId}/transactions/${transactionId}`, { status: "SENT" })
// console.log(res, "Check123") console.log(res, "Check123")
// dispatch(hideLoader()) dispatch(hideLoader())
// } }
// SENDING Transaction - END // SENDING Transaction - END
} }
// Save Tags - START // Save Tags - START
@ -323,13 +316,24 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
}, [isSend]) }, [isSend])
// Save Tags - END // Save Tags - END
// useEffect(() => { useEffect(() => {
// setTimeout(() => { // setTimeout(() => {
// setInterval(async () => { const interval = setInterval(async () => {
// await handleTransactionProcess(true); // debugger
setTransactionSaving(true)
handleTransactionProcess(true);
}, 8000)
// }, 8000) // }, 8000)
// }, 8000) return () => clearInterval(interval);
// }, []) }, [droppedItems])
useEffect(() => {
if (transactionSaving) {
setTimeout(() => {
setTransactionSaving(false)
}, 1000)
}
}, [transactionSaving])
const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => { const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault(); // Allows the drop event to work event.preventDefault(); // Allows the drop event to work
@ -1020,6 +1024,8 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
}); });
}; };
console.log(droppedItems, "Line 1022")
return ( return (
<> <>
{/* Center Doc Container - START */} {/* Center Doc Container - START */}

View File

@ -14,6 +14,8 @@ import { useNavigate, useParams } from 'react-router-dom'
import { Bounce, toast } from 'react-toastify' import { Bounce, toast } from 'react-toastify'
interface NavTwoProps { interface NavTwoProps {
transactionSaving: boolean;
// setTransactionSaving: React.Dispatch<React.SetStateAction<boolean>>
isFields: boolean; isFields: boolean;
setIsFields: React.Dispatch<React.SetStateAction<boolean>> setIsFields: React.Dispatch<React.SetStateAction<boolean>>
isSend: boolean | null; isSend: boolean | null;
@ -45,7 +47,7 @@ const fitObj = [
}, },
] ]
const NavTwo: React.FC<NavTwoProps> = ({ isFields, setIsFields, isSend, setIsSend }) => { const NavTwo: React.FC<NavTwoProps> = ({ transactionSaving, isFields, setIsFields, isSend, setIsSend }) => {
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 }>();
@ -61,7 +63,7 @@ const NavTwo: React.FC<NavTwoProps> = ({ isFields, setIsFields, isSend, setIsSen
return null; return null;
} }
const [transactionSaving, setTransactionSaving] = useState<boolean>(false); // const [transactionSaving, setTransactionSaving] = useState<boolean>(false);
const [dotCount, setDotCount] = useState(0); const [dotCount, setDotCount] = useState(0);
const [isFitDd, setIsFitDd] = useState<boolean>(false) const [isFitDd, setIsFitDd] = useState<boolean>(false)

View File

@ -8,6 +8,7 @@ import { useDispatch, useSelector } from 'react-redux';
import { RootState } from '../../../store/store'; import { RootState } from '../../../store/store';
import Loader from '../../dashboard/Loader'; import Loader from '../../dashboard/Loader';
import { hideLoader } from '../../../store/slices/loaderSlice'; import { hideLoader } from '../../../store/slices/loaderSlice';
import { useNavigate } from 'react-router-dom';
export interface IsSendInterface { export interface IsSendInterface {
send: boolean | null; send: boolean | null;
@ -19,9 +20,12 @@ const ProcessStepTwo = () => {
const [isFields, setIsFields] = useState(true); const [isFields, setIsFields] = useState(true);
const [selectedRecipient, setSelectedRecipient] = useState(0); const [selectedRecipient, setSelectedRecipient] = useState(0);
const [transactionSaving, setTransactionSaving] = useState<boolean>(false);
const [isSend, setIsSend] = useState<boolean | null>(null); const [isSend, setIsSend] = useState<boolean | null>(null);
const globalLoader = useSelector((state: RootState) => state.loader) const globalLoader = useSelector((state: RootState) => state.loader)
const dispatch = useDispatch(); const dispatch = useDispatch();
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
setTimeout(() => { setTimeout(() => {
@ -29,13 +33,14 @@ const ProcessStepTwo = () => {
}, 800) }, 800)
}, []) }, [])
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 isFields={isFields} setIsFields={setIsFields} isSend={isSend} setIsSend={setIsSend} /> <NavTwo transactionSaving={transactionSaving} isFields={isFields} setIsFields={setIsFields} isSend={isSend} setIsSend={setIsSend} />
<div className='grid grid-cols-12 gap-1 mt-1 h-[calc(100vh-46px)] overflow-hidden'> <div className='grid grid-cols-12 gap-1 mt-1 h-[calc(100vh-46px)] overflow-hidden'>
<LeftSideBar isFields={isFields} selectedRecipientIndx={selectedRecipient} setSelectedRecipient={setSelectedRecipient} /> <LeftSideBar isFields={isFields} selectedRecipientIndx={selectedRecipient} setSelectedRecipient={setSelectedRecipient} />
<DocumentContainer isSend={isSend} setIsSend={setIsSend} /> <DocumentContainer transactionSaving={transactionSaving} setTransactionSaving={setTransactionSaving} isSend={isSend} setIsSend={setIsSend} />
</div> </div>
{globalLoader.isLoading && <Loader />} {globalLoader.isLoading && <Loader />}

View File

@ -60,6 +60,23 @@
touch-action: none; touch-action: none;
} }
@keyframes slowPing {
0% {
transform: scale(1);
opacity: 1;
}
75%, 100% {
transform: scale(2.2);
opacity: 0;
}
}
.custom-ping {
animation: slowPing 2.5s cubic-bezier(0.4, 0, 0.2, 1) infinite;
transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out;
}
canvas { canvas {
touch-action: none; touch-action: none;
-ms-touch-action: none; -ms-touch-action: none;