jai #16
|
|
@ -94,7 +94,8 @@ const App = () => {
|
|||
{/* Links work wothout Login */}
|
||||
<Route path="/login" element={<Login />} />
|
||||
<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 />} />
|
||||
|
||||
{/* Links work wothout Login */}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 92 KiB |
|
|
@ -3,7 +3,6 @@ import { PiDotsThreeOutlineVerticalFill } from 'react-icons/pi';
|
|||
import api from '../../config/api';
|
||||
import { Transaction } from '../transactions/Transactions';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { FaCheck } from 'react-icons/fa';
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
|
|||
|
||||
import axios from "axios"
|
||||
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 Loader from "../dashboard/Loader";
|
||||
|
|
@ -24,6 +24,7 @@ import DocumentPages from "./DocumentPages";
|
|||
import FieldList from "../process/processStepTwo/FieldList";
|
||||
import typeToIconMap from "../../helper/iconMap";
|
||||
import { droppedTagsDefaultField } from "../process/processStepTwo/DocumentContainer";
|
||||
import SignCompletionScreen from "./SignCompletionScreen";
|
||||
|
||||
|
||||
|
||||
|
|
@ -173,6 +174,7 @@ const SignDocument = () => {
|
|||
const [transparentTags, setTransparentTags] = useState<boolean>(false);
|
||||
|
||||
const [provideTags, setProvideTags] = useState(false)
|
||||
const [showCompletionScreen, setShowCompletionScreen] = useState(false)
|
||||
|
||||
const [saved, setSaved] = useState<SaveType>({
|
||||
saveType: null,
|
||||
|
|
@ -181,6 +183,7 @@ const SignDocument = () => {
|
|||
initial: null,
|
||||
});
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
|
||||
const [signConfObj, setSignConfObj] = useState<SignConfTypeObj | {}>({});
|
||||
|
|
@ -314,6 +317,10 @@ const SignDocument = () => {
|
|||
setProvideTags(true)
|
||||
}
|
||||
|
||||
if (res.data.status ==="COMPLETED" ) {
|
||||
setShowCompletionScreen(true)
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
dispatch(hideLoader());
|
||||
}, 600);
|
||||
|
|
@ -466,7 +473,10 @@ const SignDocument = () => {
|
|||
theme: "light",
|
||||
transition: Bounce,
|
||||
});
|
||||
// Completion Sign Screen Modal and download file
|
||||
setShowCompletionScreen(true)
|
||||
}, 800)
|
||||
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
|
|
@ -766,7 +776,7 @@ const SignDocument = () => {
|
|||
<div className={`w-full h-screen overflow-hidden relative ${(globalLoader.isLoading) ? 'pointer-events-none overflow-hidden' : ''}`}>
|
||||
<>
|
||||
{/* <TermsModal showTerms={showTerms} setShowTerms={setShowTerms} recipientId={recipientId || ""} /> */}
|
||||
|
||||
{showCompletionScreen && <SignCompletionScreen />}
|
||||
<form className="bg-slate-100"
|
||||
onSubmit={(e: React.FormEvent<HTMLFormElement>) => handleFormSubmit(e)}
|
||||
>
|
||||
|
|
@ -1329,6 +1339,9 @@ const SignDocument = () => {
|
|||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{/* <SignatureCon recipientId={recipientId as string} openSign={openSign} setOpenSign={setOpenSign} savedSignature={savedSignature} setSavedSignature={setSavedSignature} />
|
||||
<InitialCon openInitial={openInitial} setOpenInitial={setOpenInitial} savedInitial={savedInitial} setSavedInitial={setSavedInitial} /> */}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import ContactFormModal, { ContactData } from './ContactsFormModal';
|
|||
import { Bounce, toast } from 'react-toastify';
|
||||
import { IoMdAdd } from 'react-icons/io';
|
||||
import LoaderUi from '../../helper/LoaderUi';
|
||||
import logoRecord from '../../assets/record.svg'
|
||||
|
||||
type ContactSchema = [{
|
||||
id: number,
|
||||
|
|
@ -121,7 +122,10 @@ const Contacts = () => {
|
|||
<div className='px-1.5'>
|
||||
<div className='flex justify-end my-2 cursor-pointer'>
|
||||
<div
|
||||
onClick={() => setShowModal((prev) => !prev)}
|
||||
onClick={() => {
|
||||
setShowModal((prev) => !prev);
|
||||
setActionStatus("Add")
|
||||
}}
|
||||
className="flex items-center gap-2 bg-[var(--primary)] px-3 py-1.5 rounded-sm hover:opacity-90 ">
|
||||
<IoMdAdd className="text-white" />
|
||||
<button
|
||||
|
|
@ -143,11 +147,19 @@ const Contacts = () => {
|
|||
<tbody className="divide-y divide-gray-200">
|
||||
{loading ? (
|
||||
<tr>
|
||||
<td colSpan="4" className="relative h-100"><LoaderUi/></td>
|
||||
<td colSpan="4" className="relative h-100"><LoaderUi /></td>
|
||||
</tr>
|
||||
) : contacts.length === 0 ? (
|
||||
<tr>
|
||||
<td colSpan="4" className="text-center py-4">No contacts found.</td>
|
||||
<td colSpan="4" className="text-center py-10 text-gray-500">
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<img
|
||||
src={logoRecord}
|
||||
alt="Record Not Found"
|
||||
className="w-70 h-70 mb-4 opacity-70" // adjust size and appearance
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
contacts.map((contact) => (
|
||||
|
|
|
|||
|
|
@ -167,11 +167,13 @@ const ContactFormModal = ({
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-white/5 backdrop-blur-sm bg-opacity-50">
|
||||
<div className="bg-white rounded-md p-6 max-w-[700px] w-full shadow-lg relative">
|
||||
<div className="ms-2 space-y-2 max-w-[60vw]">
|
||||
<h2 className="text-lg font-medium text-slate-500">Add Contact</h2>
|
||||
<h2 className="text-lg font-medium text-slate-500">{`${actionStatus} Contact`}</h2>
|
||||
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
{[
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ const Cards: React.FC<CardsProps> = ({ type = 'dashboard', onOpenModal, onDateRa
|
|||
</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) => (
|
||||
<div
|
||||
key={card.title}
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ const ProcessStepOne = () => {
|
|||
try {
|
||||
const res = await api.put(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`, { status: "SENT" })
|
||||
console.log(res, "Check123");
|
||||
navigate(`/sign/${recipientId}`);
|
||||
navigate(`/sign/${recipientId}/self_sign`);
|
||||
} catch (err) {
|
||||
console.log("Error Transaction Sent", err.message);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { FiEdit, FiTrash } from "react-icons/fi";
|
|||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
|
||||
|
||||
interface ContactType {
|
||||
id: string;
|
||||
email: string;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { useDispatch, useSelector } from 'react-redux';
|
|||
import { RootState } from '../../../store/store';
|
||||
import Loader from '../../dashboard/Loader';
|
||||
import { hideLoader } from '../../../store/slices/loaderSlice';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
export interface IsSendInterface {
|
||||
send: boolean | null;
|
||||
|
|
@ -24,6 +25,7 @@ const ProcessStepTwo = () => {
|
|||
const [isSend, setIsSend] = useState<boolean | null>(null);
|
||||
const globalLoader = useSelector((state: RootState) => state.loader)
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
|
|
@ -31,6 +33,7 @@ const ProcessStepTwo = () => {
|
|||
}, 800)
|
||||
}, [])
|
||||
|
||||
|
||||
return (
|
||||
<div className={`min-w-full relative h-screen bg-slate-100 overflow-hidden ${(globalLoader.isLoading) ? 'pointer-events-none' : ''}`}>
|
||||
<NavTwo transactionSaving={transactionSaving} isFields={isFields} setIsFields={setIsFields} isSend={isSend} setIsSend={setIsSend} />
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ const SignatureManager: React.FC = () => {
|
|||
<div className="max-w-[84vw] mx-auto">
|
||||
<>
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<div>
|
||||
<h1 className="text-[17px] font-medium text-gray-500 mb-2">Signatures</h1>
|
||||
<p className="text-gray-300 text-sm">Add or update your name and signature styles.</p>
|
||||
|
|
@ -126,7 +126,7 @@ const SignatureManager: React.FC = () => {
|
|||
</div>
|
||||
|
||||
{/* Table Card */}
|
||||
<div className="bg-white rounded-md shadow-md overflow-hidden border border-gray-100">
|
||||
<div className="bg-white rounded-md overflow-hidden border border-gray-100">
|
||||
{/* Table Header */}
|
||||
<div className="bg-gray-50 border-b border-gray-200">
|
||||
<div className="grid grid-cols-12 gap-4 px-6 py-4">
|
||||
|
|
@ -206,7 +206,7 @@ const SignatureManager: React.FC = () => {
|
|||
|
||||
{/* Dropdown Menu */}
|
||||
{activeDropdown === signature.id && (
|
||||
<div className="absolute right-0 mt-0.5 w-28 bg-white rounded-lg shadow-xl border border-gray-200 z-10 py-1">
|
||||
<div className="absolute right-0 mt-0.5 w-28 bg-white rounded-lg border border-gray-200 z-10 py-1">
|
||||
<button
|
||||
onClick={() => handleEdit(signature.id)}
|
||||
className="w-full px-4 py-1 text-left text-gray-500 hover:bg-blue-50 hover:text-blue-700 flex items-center gap-3 text-sm transition-colors duration-150"
|
||||
|
|
@ -232,7 +232,7 @@ const SignatureManager: React.FC = () => {
|
|||
|
||||
{/* Empty State (if no signatures) */}
|
||||
{signatures.length === 0 && (
|
||||
<div className=" rounded-xl shadow-lg p-12 text-center mt-8">
|
||||
<div className=" rounded-xl p-12 text-center mt-8">
|
||||
<div className="text-gray-400 mb-4">
|
||||
<FiEdit3 className="w-16 h-16 mx-auto" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ const UserProfile: React.FC<UserProfileProps> = ({ userData }) => {
|
|||
<div className="bg-white rounded-md shadow-sm flex w-full p-6">
|
||||
{/* Profile Picture */}
|
||||
<div className="flex-shrink-0 text-center">
|
||||
<div className="w-20 h-20 bg-green-800 text-white font-bold text-2xl rounded-full flex items-center justify-center shadow-lg">
|
||||
<div className="w-20 h-20 bg-[var(--primary)] text-white font-bold text-2xl rounded-full flex items-center justify-center shadow-lg">
|
||||
{userData.name.slice(0,2).toUpperCase()}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { useNavigate } from "react-router-dom";
|
|||
import { useSelector } from "react-redux";
|
||||
import { FaSpinner } from "react-icons/fa";
|
||||
import LoaderUi from "../../helper/LoaderUi";
|
||||
import logoRecord from '../../assets/record.svg';
|
||||
|
||||
|
||||
|
||||
|
|
@ -209,9 +210,16 @@ const Templates = () => {
|
|||
<tbody>
|
||||
<tr>
|
||||
<td colSpan="6" className="text-center py-10 text-gray-500">
|
||||
No templates found.
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<img
|
||||
src={logoRecord}
|
||||
alt="Record Not Found"
|
||||
className="w-70 h-70 mb-4 opacity-70" // adjust size and appearance
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ const TransactionView = () => {
|
|||
<div className='mt-2'>
|
||||
{/* new Date(transactionDetails?.transaction?.lastModifiedAt * 1000) */}
|
||||
<p className='text-slate-600'>From <span className='text-blue-600'>{transactionDetails?.transaction.createdBy.firstName + " " + transactionDetails?.transaction.createdBy.lastName}</span></p>
|
||||
<p className=''><span className='text-slate-600 font-semibold'>Last Change on</span> <span className='text-slate-400'>{new Date(transactionDetails?.transaction?.lastModifiedAt * 1000).toISOString()}</span></p>
|
||||
<p className='text-slate-600'>Created at <span>{new Date(transactionDetails?.transaction?.createdAt * 1000).toISOString()}</span></p>
|
||||
<p className=''><span className='text-slate-600 font-semibold'>Last Change on</span> <span className='text-slate-400'>{(transactionDetails?.transaction?.lastModifiedAt)}</span></p>
|
||||
<p className='text-slate-600'>Created at <span>{(transactionDetails?.transaction?.createdAt)}</span></p>
|
||||
</div>
|
||||
|
||||
<p className='text-slate-600 text-[0.98rem] mt-2 font-semibold'>{transactionDetails?.transaction.status}</p>
|
||||
|
|
|
|||
|
|
@ -60,6 +60,23 @@
|
|||
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 {
|
||||
touch-action: none;
|
||||
-ms-touch-action: none;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
declare module '*.png' {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
Loading…
Reference in New Issue