Compare commits
3 Commits
f206d54963
...
7b448558c0
| Author | SHA1 | Date |
|---|---|---|
|
|
7b448558c0 | |
|
|
1ce24675ba | |
|
|
3b08c04463 |
|
|
@ -54,6 +54,12 @@ const App = () => {
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
} />
|
} />
|
||||||
|
|
||||||
|
<Route path="/process-step-one/:accountId/:transactionId/:signType" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<ProcessStepOne />
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
|
||||||
<Route path="/process-step-one/:accountId/template/:templateId" element={
|
<Route path="/process-step-one/:accountId/template/:templateId" element={
|
||||||
<ProtectedRoute>
|
<ProtectedRoute>
|
||||||
<ProcessStepOne />
|
<ProcessStepOne />
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,10 @@ const DocumentPages = ({ selectedDocuments, setDropDownTogglePage, dropDownToggl
|
||||||
onClick={() => (`${(dropDownTogglePage === 'pageDropDown' + indx) ? '' : 'pageDropDown' + indx}`)}
|
onClick={() => (`${(dropDownTogglePage === 'pageDropDown' + indx) ? '' : 'pageDropDown' + indx}`)}
|
||||||
className={`p-2 ${(dropDownTogglePage === 'pageDropDown' + indx) ? "bg-[var(--primary)]" : "bg-slate-200"} flex flex-col justify-center items-center gap-2 rounded`}>
|
className={`p-2 ${(dropDownTogglePage === 'pageDropDown' + indx) ? "bg-[var(--primary)]" : "bg-slate-200"} flex flex-col justify-center items-center gap-2 rounded`}>
|
||||||
{
|
{
|
||||||
document.images != undefined && <img
|
document.pages != undefined && <img
|
||||||
key={indx}
|
key={indx}
|
||||||
className='rounded-sm shadow'
|
className='rounded-sm shadow'
|
||||||
src={document.images[0].src}
|
src={document.pages[0].src}
|
||||||
alt="" />
|
alt="" />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ const DocumentPages = ({ selectedDocuments, setDropDownTogglePage, dropDownToggl
|
||||||
{
|
{
|
||||||
dropDownTogglePage === 'pageDropDown' + indx &&
|
dropDownTogglePage === 'pageDropDown' + indx &&
|
||||||
<div className='my-1 flex justify-center items-center gap-1 flex-wrap'>
|
<div className='my-1 flex justify-center items-center gap-1 flex-wrap'>
|
||||||
{document.images != undefined && document.images.map((img, indx) => (
|
{document.pages != undefined && document.pages.map((img, indx) => (
|
||||||
<a
|
<a
|
||||||
href={"#" + document.documentId + indx}
|
href={"#" + document.documentId + indx}
|
||||||
className='max-w-max px-4 py-2 shadow cursor-pointer border-1 rounded-sm border-slate-200 hover:border-[var(--primary)] transition-all duration-300 bg-slate-300'
|
className='max-w-max px-4 py-2 shadow cursor-pointer border-1 rounded-sm border-slate-200 hover:border-[var(--primary)] transition-all duration-300 bg-slate-300'
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ interface RecipientType {
|
||||||
acceptedTerms: boolean;
|
acceptedTerms: boolean;
|
||||||
name: string | null;
|
name: string | null;
|
||||||
}
|
}
|
||||||
interface ImagesType {
|
interface pagesType {
|
||||||
index: number;
|
index: number;
|
||||||
type: string;
|
type: string;
|
||||||
src: string;
|
src: string;
|
||||||
|
|
@ -56,7 +56,7 @@ interface ImagesType {
|
||||||
}
|
}
|
||||||
interface DocumentType {
|
interface DocumentType {
|
||||||
documentId: string;
|
documentId: string;
|
||||||
images: ImagesType[];
|
pages: pagesType[];
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,7 +130,7 @@ const fitObj = [
|
||||||
|
|
||||||
// Functions - LIST
|
// Functions - LIST
|
||||||
// handleSignClick - Handle when sign || Initial tag got clicked
|
// handleSignClick - Handle when sign || Initial tag got clicked
|
||||||
// fetchData - Fetch document images and tags data
|
// fetchData - Fetch document pages and tags data
|
||||||
// handleFormSubmit - handle form submit and send data to server
|
// handleFormSubmit - handle form submit and send data to server
|
||||||
|
|
||||||
const SignDocument = () => {
|
const SignDocument = () => {
|
||||||
|
|
@ -144,6 +144,7 @@ const SignDocument = () => {
|
||||||
const [transaction, setTransaction] = useState<TransactionType | null>(null);
|
const [transaction, setTransaction] = useState<TransactionType | null>(null);
|
||||||
const [recSignStatus, setRecSignStatus] = useState<string | null>(null);
|
const [recSignStatus, setRecSignStatus] = useState<string | null>(null);
|
||||||
const [droppedItems, setDroppedItems] = useState([]);
|
const [droppedItems, setDroppedItems] = useState([]);
|
||||||
|
const[signTagId , setSignTagId] = useState<number>(0)
|
||||||
|
|
||||||
const [stamp, setStamp] = useState<StampTypeObj>({ open: false, blob: "" });
|
const [stamp, setStamp] = useState<StampTypeObj>({ open: false, blob: "" });
|
||||||
|
|
||||||
|
|
@ -178,8 +179,12 @@ const SignDocument = () => {
|
||||||
initial: null,
|
initial: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const [signConfObj, setSignConfObj] = useState<SignConfTypeObj | {}>({});
|
const [signConfObj, setSignConfObj] = useState<SignConfTypeObj | {}>({});
|
||||||
|
|
||||||
|
console.log("signConfObj",signConfObj)
|
||||||
|
|
||||||
const zoom = (percentage: number, contentClass: string) => {
|
const zoom = (percentage: number, contentClass: string) => {
|
||||||
const content = document.querySelector(`.${contentClass}`);
|
const content = document.querySelector(`.${contentClass}`);
|
||||||
if (content) {
|
if (content) {
|
||||||
|
|
@ -239,7 +244,9 @@ const SignDocument = () => {
|
||||||
}
|
}
|
||||||
}, [saved])
|
}, [saved])
|
||||||
|
|
||||||
const handleSignClick = (index: number) => {
|
const handleSignClick = (index: number , id:number) => {
|
||||||
|
console.log("IDNumber" , id)
|
||||||
|
setSignTagId(id)
|
||||||
if (saved.save) {
|
if (saved.save) {
|
||||||
if (index in signConfObj) {
|
if (index in signConfObj) {
|
||||||
setOpenSign(true);
|
setOpenSign(true);
|
||||||
|
|
@ -263,8 +270,11 @@ const SignDocument = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setSignConfObj({ ...newObj })
|
setSignConfObj({ ...newObj })
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleStampClick = (index: number) => {
|
const handleStampClick = (index: number) => {
|
||||||
console.log("Stamp Clicked", index)
|
console.log("Stamp Clicked", index)
|
||||||
setStamp({
|
setStamp({
|
||||||
|
|
@ -502,11 +512,12 @@ const SignDocument = () => {
|
||||||
|
|
||||||
const fetchSignatureData = async (signatureId: string) => {
|
const fetchSignatureData = async (signatureId: string) => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`${import.meta.env.VITE_BASE_URI}/api/sign/signatures/${signatureId}`, {
|
const response = await axios.get(`${import.meta.env.VITE_BASE_URI}/api/sign/signatures/${signatureId}?recipientId=${recipientId}`, {
|
||||||
headers: { "ngrok-skip-browser-warning": "69420" }
|
headers: { "ngrok-skip-browser-warning": "69420" }
|
||||||
});
|
});
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
return response.data.signature;
|
console.log("line 516" , response.data)
|
||||||
|
return response.data;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching signature data:", error);
|
console.error("Error fetching signature data:", error);
|
||||||
|
|
@ -514,18 +525,19 @@ const SignDocument = () => {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
(async () => {
|
// (async () => {
|
||||||
if (droppedItems) {
|
// if (droppedItems) {
|
||||||
for (const tag of droppedItems) {
|
// for (const tag of droppedItems) {
|
||||||
if (tag.type === "SIGNATURE" && "value" in tag) {
|
// if (tag.type === "SIGNATURE" && "value" in tag) {
|
||||||
const signatureData = await fetchSignatureData(tag.value);
|
// console.log(tag, "line 533")
|
||||||
console.log(signatureData);
|
// const signatureData = await fetchSignatureData(tag["value"]);
|
||||||
}
|
// console.log("Currnet Signature",signatureData);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})()
|
// }
|
||||||
}, [droppedItems])
|
// })()
|
||||||
|
// }, [droppedItems])
|
||||||
|
|
||||||
|
|
||||||
const handleTagUpdate = (updateIndx: number, updateValue: string) => {
|
const handleTagUpdate = (updateIndx: number, updateValue: string) => {
|
||||||
|
|
@ -879,7 +891,7 @@ const SignDocument = () => {
|
||||||
|
|
||||||
<div className='flex flex-col gap-3 max-w-max relative left-[50%] translate-x-[-50%]'>
|
<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) => {
|
doc.pages && doc.pages.length > 0 && doc.pages.map((page, indx) => {
|
||||||
const key = `${doc.documentId}_${page.index}`;
|
const key = `${doc.documentId}_${page.index}`;
|
||||||
console.log(droppedItems, "line 820")
|
console.log(droppedItems, "line 820")
|
||||||
// const tagJsonData = [...droppedItems];
|
// const tagJsonData = [...droppedItems];
|
||||||
|
|
@ -1012,7 +1024,7 @@ const SignDocument = () => {
|
||||||
<div
|
<div
|
||||||
tabIndex={1}
|
tabIndex={1}
|
||||||
id={item.id}
|
id={item.id}
|
||||||
onClick={() => handleSignClick(index)}
|
onClick={() => handleSignClick(index , item.id)}
|
||||||
className={`flex justify-center items-center h-full w-full rounded cursor-pointer ${transparentTags || hideTags ? "pointer-events-none bg-transparent" : "bg-slate-200 shadow-sm border-slate-100 opacity-80"}`}
|
className={`flex justify-center items-center h-full w-full rounded cursor-pointer ${transparentTags || hideTags ? "pointer-events-none bg-transparent" : "bg-slate-200 shadow-sm border-slate-100 opacity-80"}`}
|
||||||
// style={{ height: item.dimensions.height + "px" }}
|
// style={{ height: item.dimensions.height + "px" }}
|
||||||
>
|
>
|
||||||
|
|
@ -1028,7 +1040,9 @@ const SignDocument = () => {
|
||||||
width: `${item.dimensions.width}px`,
|
width: `${item.dimensions.width}px`,
|
||||||
height: `${item.dimensions.height}px`,
|
height: `${item.dimensions.height}px`,
|
||||||
}}
|
}}
|
||||||
src={saved.signature as string} />
|
// src={saved.signature as string} />
|
||||||
|
src={`data:image/png;base64,${saved.signature}`}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
</div>}
|
</div>}
|
||||||
{/* SIGNATURE FIELD - END */}
|
{/* SIGNATURE FIELD - END */}
|
||||||
|
|
@ -1039,7 +1053,7 @@ const SignDocument = () => {
|
||||||
<div
|
<div
|
||||||
tabIndex={1}
|
tabIndex={1}
|
||||||
id={item.id}
|
id={item.id}
|
||||||
onClick={() => handleSignClick(index)}
|
onClick={() => handleSignClick(index , item.id)}
|
||||||
className={`flex justify-center items-center h-full w-full rounded cursor-pointer ${transparentTags || hideTags ? "pointer-events-none" : "bg-slate-200 shadow-sm border-slate-100 opacity-80"}`}
|
className={`flex justify-center items-center h-full w-full rounded cursor-pointer ${transparentTags || hideTags ? "pointer-events-none" : "bg-slate-200 shadow-sm border-slate-100 opacity-80"}`}
|
||||||
// style={{ height: item.dimensions.height + "px" }}
|
// style={{ height: item.dimensions.height + "px" }}
|
||||||
>
|
>
|
||||||
|
|
@ -1052,7 +1066,9 @@ const SignDocument = () => {
|
||||||
height: `${item.dimensions.height}px`,
|
height: `${item.dimensions.height}px`,
|
||||||
}}
|
}}
|
||||||
className="w-[100%] h-full"
|
className="w-[100%] h-full"
|
||||||
src={saved.initial as string} />
|
// src={saved.initial as string}
|
||||||
|
src={`data:image/png;base64,${saved.initial}`}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
</div>}
|
</div>}
|
||||||
{/* INITIALS FIELD - END */}
|
{/* INITIALS FIELD - END */}
|
||||||
|
|
@ -1207,7 +1223,7 @@ const SignDocument = () => {
|
||||||
|
|
||||||
{/* Side details of documents Pages and document Name - START */}
|
{/* 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'>
|
<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}
|
page {indx + 1} of {doc.pages && doc.pages.length}
|
||||||
</p>
|
</p>
|
||||||
{/* Side details of documents Pages and document Name - END */}
|
{/* Side details of documents Pages and document Name - END */}
|
||||||
|
|
||||||
|
|
@ -1258,7 +1274,7 @@ const SignDocument = () => {
|
||||||
|
|
||||||
|
|
||||||
<div style={{ display: `${openSign ? 'block' : 'none'}` }}>
|
<div style={{ display: `${openSign ? 'block' : 'none'}` }}>
|
||||||
<SignCon recipientId={recipientId as string} setOpenSign={setOpenSign} saved={saved} setSaved={setSaved} />
|
<SignCon recipientId={recipientId as string} setOpenSign={setOpenSign} saved={saved} setSaved={setSaved} signTagId={signTagId}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: `${stamp.open ? 'block' : 'none'}` }}>
|
<div style={{ display: `${stamp.open ? 'block' : 'none'}` }}>
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,14 @@ import React, { useEffect, useRef } from 'react'
|
||||||
import { IoMdArrowDropdown } from "react-icons/io";
|
import { IoMdArrowDropdown } from "react-icons/io";
|
||||||
import { IoIosSend } from "react-icons/io";
|
import { IoIosSend } from "react-icons/io";
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { setSignType } from '../../store/slices/selectedDocsSlice';
|
import { setSignType, SignType } from '../../store/slices/selectedDocsSlice';
|
||||||
import { RootState } from '../../store/store';
|
import { RootState } from '../../store/store';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Bounce, toast } from 'react-toastify';
|
import { Bounce, toast } from 'react-toastify';
|
||||||
|
import api from '../../config/api';
|
||||||
|
import { StartCard } from '../home/StartSection';
|
||||||
|
import { setTransactionId, TRANSACTION_STATUS_ENUMS, updateTransactionStatus } from '../../store/slices/transactionSlice';
|
||||||
|
import { SignTypeEnum } from '../../utlity/types';
|
||||||
// import { IoMdArrowDropright } from "react-icons/io";
|
// import { IoMdArrowDropright } from "react-icons/io";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -22,32 +26,55 @@ const SendForSign: React.FC<Props> = ({ showSideBar }) => {
|
||||||
sendForSignDropdown && dropDownRef.current?.focus();
|
sendForSignDropdown && dropDownRef.current?.focus();
|
||||||
}, [sendForSignDropdown])
|
}, [sendForSignDropdown])
|
||||||
|
|
||||||
|
const user = useSelector((state: RootState) => state.user);
|
||||||
|
if (!user.account || user.account === null) {
|
||||||
|
window.location.href = "/login";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultAccountId = user.account.id;
|
||||||
|
|
||||||
const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments);
|
const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments);
|
||||||
|
|
||||||
const handleSendSignDispatch: (type: "self-sign" | "multiple-sign") => void = (signType) => {
|
const handleStartSectionClick = (signType: SignTypeEnum) => {
|
||||||
if (selectedDocuments === null || !selectedDocuments.length) {
|
|
||||||
if (selectedDocuments === null || !selectedDocuments.length) {
|
|
||||||
toast.dismiss();
|
|
||||||
toast.error("Select 📄 Documents first!", {
|
|
||||||
position: "bottom-right",
|
|
||||||
autoClose: 5000,
|
|
||||||
hideProgressBar: false,
|
|
||||||
closeOnClick: false,
|
|
||||||
pauseOnHover: true,
|
|
||||||
draggable: true,
|
|
||||||
progress: undefined,
|
|
||||||
theme: "light",
|
|
||||||
transition: Bounce,
|
|
||||||
});
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedDocuments.length) {
|
api.post(`/api/accounts/${defaultAccountId}/transactions`)
|
||||||
dispatch(setSignType(signType));
|
.then(res => {
|
||||||
}
|
if (res.status === 200 || res.status === 201) {
|
||||||
|
dispatch(updateTransactionStatus(TRANSACTION_STATUS_ENUMS.TRANSACTION_INITIATED));
|
||||||
|
dispatch(setTransactionId(res.data));
|
||||||
|
let navigateUrl = `/process-step-one/${defaultAccountId}/${res.data}`;
|
||||||
|
if (signType === SignTypeEnum.selfSign) navigateUrl = `/process-step-one/${defaultAccountId}/${res.data}/self_sign`;
|
||||||
|
setTimeout(() => navigate(navigateUrl), 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => console.log(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// const handleSendSignDispatch: (type: "self-sign" | "multiple-sign") => void = (signType) => {
|
||||||
|
// if (selectedDocuments === null || !selectedDocuments.length) {
|
||||||
|
// if (selectedDocuments === null || !selectedDocuments.length) {
|
||||||
|
// toast.dismiss();
|
||||||
|
// toast.error("Select 📄 Documents first!", {
|
||||||
|
// position: "bottom-right",
|
||||||
|
// autoClose: 5000,
|
||||||
|
// hideProgressBar: false,
|
||||||
|
// closeOnClick: false,
|
||||||
|
// pauseOnHover: true,
|
||||||
|
// draggable: true,
|
||||||
|
// progress: undefined,
|
||||||
|
// theme: "light",
|
||||||
|
// transition: Bounce,
|
||||||
|
// });
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (selectedDocuments.length) {
|
||||||
|
// dispatch(setSignType(signType));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='relative max-h-max pb-3'
|
<div className='relative max-h-max pb-3'
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
|
|
@ -73,12 +100,12 @@ const SendForSign: React.FC<Props> = ({ showSideBar }) => {
|
||||||
{
|
{
|
||||||
sendForSignDropdown &&
|
sendForSignDropdown &&
|
||||||
<div className={`w-[300px] rounded absolute z-40 bg-[var(--sendForSignDropDownBg)] shadow-lg top-[54px] text-left outline-none`}>
|
<div className={`w-[300px] rounded absolute z-40 bg-[var(--sendForSignDropDownBg)] shadow-lg top-[54px] text-left outline-none`}>
|
||||||
<div className='py-3 px-8 leading-6 rounded-t-sm hover:bg-[var(--sendForSignDropDownHover)] cursor-pointer' onClick={() => handleSendSignDispatch('self-sign')}>
|
<div className='py-3 px-8 leading-6 rounded-t-sm hover:bg-[var(--sendForSignDropDownHover)] cursor-pointer' onClick={() => handleStartSectionClick(SignTypeEnum.selfSign)}>
|
||||||
<p>Self Sign</p>
|
<p>Self Sign</p>
|
||||||
<p className='text-[var(--greyTextCol)] text-sm'>You're the only signer.</p>
|
<p className='text-[var(--greyTextCol)] text-sm'>You're the only signer.</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='w-full h-[1px] opacity-30 bg-[var(--greyTextCol)]'></div>
|
<div className='w-full h-[1px] opacity-30 bg-[var(--greyTextCol)]'></div>
|
||||||
<div className='py-3 px-8 leading-6 rounded-b-sm hover:bg-[var(--sendForSignDropDownHover)] cursor-pointer' onClick={() => handleSendSignDispatch('multiple-sign')}>
|
<div className='py-3 px-8 leading-6 rounded-b-sm hover:bg-[var(--sendForSignDropDownHover)] cursor-pointer' onClick={() => handleStartSectionClick(SignTypeEnum.multipleSign)}>
|
||||||
<p>Send for Sign</p>
|
<p>Send for Sign</p>
|
||||||
<p className='text-[var(--greyTextCol)] text-sm'>You and other need to sign.</p>
|
<p className='text-[var(--greyTextCol)] text-sm'>You and other need to sign.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import api from '../../config/api';
|
||||||
import { setTransactionId, TRANSACTION_STATUS_ENUMS, updateTransactionStatus } from '../../store/slices/transactionSlice';
|
import { setTransactionId, TRANSACTION_STATUS_ENUMS, updateTransactionStatus } from '../../store/slices/transactionSlice';
|
||||||
|
|
||||||
|
|
||||||
interface StartCard {
|
export interface StartCard {
|
||||||
icon: ReactNode;
|
icon: ReactNode;
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
|
@ -57,7 +57,7 @@ const StartSection = () => {
|
||||||
if (res.status === 200 || res.status === 201) {
|
if (res.status === 200 || res.status === 201) {
|
||||||
dispatch(updateTransactionStatus(TRANSACTION_STATUS_ENUMS.TRANSACTION_INITIATED));
|
dispatch(updateTransactionStatus(TRANSACTION_STATUS_ENUMS.TRANSACTION_INITIATED));
|
||||||
dispatch(setTransactionId(res.data));
|
dispatch(setTransactionId(res.data));
|
||||||
setTimeout(() => navigate(`/process-step-one/${defaultAccountId}/${res.data}`), 0)
|
setTimeout(() => navigate(`/process-step-one/${defaultAccountId}/${res.data.id}`), 0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => console.log(err))
|
.catch(err => console.log(err))
|
||||||
|
|
|
||||||
|
|
@ -316,7 +316,7 @@ const DocumentCompletionScreen = () => {
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="w-10 h-10 bg-blue-100 rounded-lg flex items-center justify-center">
|
<div className="w-10 h-10 bg-blue-100 rounded-lg flex items-center justify-center">
|
||||||
{/* <FaFileAlt className="text-blue-600 text-xl" /> */}
|
{/* <FaFileAlt className="text-blue-600 text-xl" /> */}
|
||||||
<img src={item.images[0].src} alt="document" className="h-10 w-10" />
|
<img src={item.pages[0].src} alt="document" className="h-10 w-10" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-md font-semibold text-gray-800">
|
<h3 className="text-md font-semibold text-gray-800">
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import { hideLoader, showLoader } from "../../../store/slices/loaderSlice";
|
||||||
import Loader from "../../dashboard/Loader";
|
import Loader from "../../dashboard/Loader";
|
||||||
import { Bounce, toast } from "react-toastify";
|
import { Bounce, toast } from "react-toastify";
|
||||||
import { fetchDocuments, resetDocuments, setDocuments, uploadDocuments } from "../../../store/slices/documentSlice";
|
import { fetchDocuments, resetDocuments, setDocuments, uploadDocuments } from "../../../store/slices/documentSlice";
|
||||||
|
import { SignTypeEnum } from "../../../utlity/types";
|
||||||
|
|
||||||
const ProcessStepOne = () => {
|
const ProcessStepOne = () => {
|
||||||
interface EmailDtls {
|
interface EmailDtls {
|
||||||
|
|
@ -23,8 +24,8 @@ const ProcessStepOne = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
let transactionTemplateToggle = TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS;
|
let transactionTemplateToggle = TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS;
|
||||||
console.log("transactionTemplateToggle1", transactionTemplateToggle)
|
|
||||||
console.log()
|
const signType = useParams<{ signType: string }>().signType;
|
||||||
const templateId = useParams<{ templateId: string }>().templateId;
|
const templateId = useParams<{ templateId: string }>().templateId;
|
||||||
let { accountId, transactionId } = useParams<{ accountId: string, transactionId: string }>();
|
let { accountId, transactionId } = useParams<{ accountId: string, transactionId: string }>();
|
||||||
|
|
||||||
|
|
@ -33,11 +34,11 @@ const ProcessStepOne = () => {
|
||||||
|
|
||||||
if (!transactionId) {
|
if (!transactionId) {
|
||||||
transactionTemplateToggle = TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES;
|
transactionTemplateToggle = TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES;
|
||||||
console.log("transactionTemplateToggle2", transactionTemplateToggle)
|
|
||||||
transactionId = templateId;
|
transactionId = templateId;
|
||||||
dispatch(toggleToTemplates());
|
dispatch(toggleToTemplates());
|
||||||
}
|
}
|
||||||
console.log("ProcessStepOne called with accountId:", accountId, "and transactionId:", transactionId);
|
|
||||||
// if (!accountId || !transactionId) {
|
// if (!accountId || !transactionId) {
|
||||||
// window.location.href = "/";
|
// window.location.href = "/";
|
||||||
// return null;
|
// return null;
|
||||||
|
|
@ -48,10 +49,10 @@ const ProcessStepOne = () => {
|
||||||
|
|
||||||
const selectedDocuments = useSelector((state: RootState) => state.documents.documents)
|
const selectedDocuments = useSelector((state: RootState) => state.documents.documents)
|
||||||
const selectedRecipients = useSelector((state: RootState) => state.selectedRecipients.recipients)
|
const selectedRecipients = useSelector((state: RootState) => state.selectedRecipients.recipients)
|
||||||
|
const userData = useSelector((state: RootState) => state.user)
|
||||||
|
|
||||||
console.log("selectedRecipients", selectedRecipients)
|
console.log("selectedRecipients", selectedRecipients)
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
selectedRecipients.length === 0 && dispatch(fetchRecipients({ accountId, transactionId }));
|
selectedRecipients.length === 0 && dispatch(fetchRecipients({ accountId, transactionId }));
|
||||||
selectedDocuments.length === 0 && dispatch(fetchDocuments({ accountId, transactionId }));
|
selectedDocuments.length === 0 && dispatch(fetchDocuments({ accountId, transactionId }));
|
||||||
|
|
@ -85,6 +86,8 @@ const ProcessStepOne = () => {
|
||||||
formError.subject = true
|
formError.subject = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(SignTypeEnum.selfSign === signType) formError.recipients = false;
|
||||||
|
|
||||||
if (formError.documents || formError.recipients || formError.subject) {
|
if (formError.documents || formError.recipients || formError.subject) {
|
||||||
console.log(selectedDocuments, 'line 193')
|
console.log(selectedDocuments, 'line 193')
|
||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
|
|
@ -149,11 +152,38 @@ const ProcessStepOne = () => {
|
||||||
roleName: recipient.roleName
|
roleName: recipient.roleName
|
||||||
}));
|
}));
|
||||||
|
|
||||||
dispatch(addRecipientAsync({ recipientsData, accountId, transactionId }));
|
let recipientsDataTemp = recipientsData;
|
||||||
|
|
||||||
|
if (signType === SignTypeEnum.selfSign) {
|
||||||
|
recipientsDataTemp = [{
|
||||||
|
id: null,
|
||||||
|
routingOrder: 1,
|
||||||
|
provideOwnTags: true,
|
||||||
|
type: recipientType.SIGNER,
|
||||||
|
firstName: userData.firstName,
|
||||||
|
lastName: userData.lastName,
|
||||||
|
authType: "NONE",
|
||||||
|
deliveryMethod: "EMAIL",
|
||||||
|
email: userData.email,
|
||||||
|
hostName: "",
|
||||||
|
hostEmail: "",
|
||||||
|
company: "",
|
||||||
|
title: "",
|
||||||
|
website: "",
|
||||||
|
phone: "",
|
||||||
|
accessCode: "",
|
||||||
|
accessCodeDelivery: true,
|
||||||
|
language: "en",
|
||||||
|
name: `${userData.firstName} ${userData.lastName}`,
|
||||||
|
roleName: ""
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(addRecipientAsync({ recipientsData: recipientsDataTemp, accountId, transactionId }));
|
||||||
dispatch(showLoader("Processing Message..."));
|
dispatch(showLoader("Processing Message..."));
|
||||||
|
|
||||||
console.log(`1/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`)
|
console.log(`1/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`)
|
||||||
|
|
||||||
let res = await api.put(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`, {
|
let res = await api.put(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`, {
|
||||||
subject: emailDtls.subject, message: emailDtls.message,
|
subject: emailDtls.subject, message: emailDtls.message,
|
||||||
status: "CREATED"
|
status: "CREATED"
|
||||||
|
|
@ -202,6 +232,15 @@ const ProcessStepOne = () => {
|
||||||
navigate('/')
|
navigate('/')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const handleSelfSignCb = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
if (e.currentTarget.checked) {
|
||||||
|
navigate("self_sign");
|
||||||
|
} else {
|
||||||
|
navigate("./../");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const globalLoader = useSelector((state: RootState) => state.loader)
|
const globalLoader = useSelector((state: RootState) => state.loader)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -219,12 +258,15 @@ const ProcessStepOne = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex items-center gap-3'>
|
<div className='flex items-center gap-3'>
|
||||||
<button
|
<div className="flex items-center" >
|
||||||
onClick={() => handleNextClick(true)}
|
<input
|
||||||
className="text-sm px-4 py-2 rounded border border-gray-300 hover:bg-gray-100 transition"
|
checked={signType === SignTypeEnum.selfSign}
|
||||||
>
|
onChange={(e) => handleSelfSignCb(e)}
|
||||||
Send Now
|
id="default-checkbox" type="checkbox" value="" className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm outline-none"
|
||||||
</button>
|
/>
|
||||||
|
|
||||||
|
<label htmlFor="default-checkbox" className="ms-2 text-sm text-slate-600">SELF SIGN</label>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleNextClick(false)}
|
onClick={() => handleNextClick(false)}
|
||||||
className="text-sm px-4 py-2 rounded bg-[var(--primary)] text-white shadow hover:bg-[var(--primaryLight2)] transition"
|
className="text-sm px-4 py-2 rounded bg-[var(--primary)] text-white shadow hover:bg-[var(--primaryLight2)] transition"
|
||||||
|
|
@ -244,14 +286,17 @@ const ProcessStepOne = () => {
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Recipients */}
|
{/* Recipients */}
|
||||||
<section className="mt-8">
|
{
|
||||||
<h2 className="text-lg font-medium mb-4 pt-6 border-t text-[var(--processStepOneTextHead)]">Signers</h2>
|
signType !== SignTypeEnum.selfSign &&
|
||||||
<div className="flex flex-col gap-4 align-start">
|
< section className="mt-8">
|
||||||
<RecipientCards />
|
<h2 className="text-lg font-medium mb-4 pt-6 border-t text-[var(--processStepOneTextHead)]">Signers</h2>
|
||||||
{/* {signType !== "self-sign" && <RecipientAddCard />} */}
|
<div className="flex flex-col gap-4 align-start">
|
||||||
<RecipientAddCard transactionTemplateToggle={transactionTemplateToggle} />
|
<RecipientCards />
|
||||||
</div>
|
{/* {signType !== "self-sign" && <RecipientAddCard />} */}
|
||||||
</section>
|
<RecipientAddCard transactionTemplateToggle={transactionTemplateToggle} />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
}
|
||||||
|
|
||||||
{/* Email */}
|
{/* Email */}
|
||||||
<section className="mt-8">
|
<section className="mt-8">
|
||||||
|
|
@ -286,7 +331,7 @@ const ProcessStepOne = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{globalLoader.isLoading && <Loader />}
|
{globalLoader.isLoading && <Loader />}
|
||||||
</div>
|
</div >
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import typeToIconMap from '../../../helper/iconMap';
|
||||||
|
|
||||||
import { IoAdd } from 'react-icons/io5';
|
import { IoAdd } from 'react-icons/io5';
|
||||||
import Loader from '../../dashboard/Loader';
|
import Loader from '../../dashboard/Loader';
|
||||||
|
// import { TRANSACTION_TEMPLATE_TOGGLE } from "../../../store/slices/selectedRecipientsSlice";
|
||||||
import { handleGroupBorderPosition } from '../../../utlity/tagGroupConUtils';
|
import { handleGroupBorderPosition } from '../../../utlity/tagGroupConUtils';
|
||||||
|
|
||||||
export interface DroppedItemsObj {
|
export interface DroppedItemsObj {
|
||||||
|
|
@ -290,7 +291,8 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
sendTagsToRecipients(tagsData, accountId, transactionId);
|
sendTagsToRecipients(tagsData, accountId, transactionId);
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const res = await api.put(`/api/accounts/${accountId}/transactions/${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" })
|
||||||
console.log(res, "Check123")
|
console.log(res, "Check123")
|
||||||
})()
|
})()
|
||||||
}, [isSend])
|
}, [isSend])
|
||||||
|
|
@ -581,15 +583,15 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
const handleAddGroupItemClicked = (key: string, item) => {
|
const handleAddGroupItemClicked = (key: string, item) => {
|
||||||
|
|
||||||
|
|
||||||
const groupId = item.group;
|
const groupId = item.group;
|
||||||
|
|
||||||
item = { ...item, dimensions: { ...item.dimensions, top: item.dimensions.top + item.dimensions.height + 20 } }
|
item = { ...item, dimensions: { ...item.dimensions, top: item.dimensions.top + item.dimensions.height + 20 } }
|
||||||
|
|
||||||
// dimensions: { ...item.dimensions, left: newLeft, top: newTop }
|
// dimensions: { ...item.dimensions, left: newLeft, top: newTop }
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
handleIGroupBorderPosition(item.group)
|
handleIGroupBorderPosition(item.group)
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
setDroppedItems({
|
setDroppedItems({
|
||||||
...droppedItems,
|
...droppedItems,
|
||||||
|
|
@ -608,325 +610,325 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
// // }],
|
// // }],
|
||||||
// // }
|
// // }
|
||||||
|
|
||||||
// // const lastRadioElemRect = e.currentTarget?.parentElement.previousSibling.getBoundingClientRect();
|
// // const lastRadioElemRect = e.currentTarget?.parentElement.previousSibling.getBoundingClientRect();
|
||||||
// // console.log(lastRadioElemRect, "lastRadioElemRect")
|
// // console.log(lastRadioElemRect, "lastRadioElemRect")
|
||||||
|
|
||||||
// const setNewData = droppedItems;
|
// const setNewData = droppedItems;
|
||||||
|
|
||||||
// if (Array.isArray(setNewData[key][index].radioGroups) && setNewData[key][index].radioGroups?.length > 0) {
|
// if (Array.isArray(setNewData[key][index].radioGroups) && setNewData[key][index].radioGroups?.length > 0) {
|
||||||
// setNewData[key][index].radioGroups?.push(setNewData[key][index].radioGroups[0])
|
// setNewData[key][index].radioGroups?.push(setNewData[key][index].radioGroups[0])
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// setDroppedItems(setNewData);
|
// setDroppedItems(setNewData);
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// const handleRadioTagMouseDown = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number, radioIndex: number) => {
|
// const handleRadioTagMouseDown = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number, radioIndex: number) => {
|
||||||
|
|
||||||
// event.preventDefault();
|
// event.preventDefault();
|
||||||
|
|
||||||
// let targetContainer = event?.currentTarget?.parentElement;
|
// let targetContainer = event?.currentTarget?.parentElement;
|
||||||
// let targetElement = event?.currentTarget;
|
// let targetElement = event?.currentTarget;
|
||||||
|
|
||||||
// if (!targetContainer || !targetElement) return;
|
// if (!targetContainer || !targetElement) return;
|
||||||
|
|
||||||
// const containerRect = targetContainer.getBoundingClientRect();
|
// const containerRect = targetContainer.getBoundingClientRect();
|
||||||
// const elementRect = targetElement.getBoundingClientRect();
|
// const elementRect = targetElement.getBoundingClientRect();
|
||||||
|
|
||||||
// // Calculate the initial offset (where the mouse was clicked inside the element)
|
// // Calculate the initial offset (where the mouse was clicked inside the element)
|
||||||
// const offsetX = event.clientX - elementRect.left;
|
// const offsetX = event.clientX - elementRect.left;
|
||||||
// const offsetY = event.clientY - elementRect.top;
|
// const offsetY = event.clientY - elementRect.top;
|
||||||
|
|
||||||
// const handleMouseMove = (event: PointerEvent) => {
|
// const handleMouseMove = (event: PointerEvent) => {
|
||||||
// // Get new X and Y positions relative to the container
|
// // Get new X and Y positions relative to the container
|
||||||
// // let x = offsetX;
|
// // let x = offsetX;
|
||||||
// // let y = offsetY;
|
// // let y = offsetY;
|
||||||
|
|
||||||
// let x = event.clientX - elementRect.left;
|
// let x = event.clientX - elementRect.left;
|
||||||
// let y = event.clientY - elementRect.top;
|
// let y = event.clientY - elementRect.top;
|
||||||
|
|
||||||
// const newData = droppedItems;
|
// const newData = droppedItems;
|
||||||
|
|
||||||
// if (newData[key][index].radioGroups && newData[key][index].radioGroups.length > 0) {
|
// 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.left = x;
|
||||||
// newData[key][index].radioGroups[radioIndex].dimensions.top = y;
|
// newData[key][index].radioGroups[radioIndex].dimensions.top = y;
|
||||||
|
|
||||||
// let topMin = Number.POSITIVE_INFINITY;
|
// let topMin = Number.POSITIVE_INFINITY;
|
||||||
// let topMax = Number.NEGATIVE_INFINITY;
|
// let topMax = Number.NEGATIVE_INFINITY;
|
||||||
// let leftMin = Number.POSITIVE_INFINITY;
|
// let leftMin = Number.POSITIVE_INFINITY;
|
||||||
// let leftMax = Number.NEGATIVE_INFINITY;
|
// let leftMax = Number.NEGATIVE_INFINITY;
|
||||||
|
|
||||||
// for (const radio of newData[key][index].radioGroups) {
|
// for (const radio of newData[key][index].radioGroups) {
|
||||||
// if (radio.dimensions.left < leftMin) {
|
// if (radio.dimensions.left < leftMin) {
|
||||||
// leftMin = radio.dimensions.left;
|
// leftMin = radio.dimensions.left;
|
||||||
// }
|
// }
|
||||||
// if (radio.dimensions.left > leftMax) {
|
// if (radio.dimensions.left > leftMax) {
|
||||||
// leftMax = radio.dimensions.left;
|
// leftMax = radio.dimensions.left;
|
||||||
// }
|
// }
|
||||||
// if (radio.dimensions.top < topMin) {
|
// if (radio.dimensions.top < topMin) {
|
||||||
// topMin = radio.dimensions.top;
|
// topMin = radio.dimensions.top;
|
||||||
// }
|
// }
|
||||||
// if (radio.dimensions.top > topMax) {
|
// if (radio.dimensions.top > topMax) {
|
||||||
// topMax = radio.dimensions.top;
|
// topMax = radio.dimensions.top;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// newData[key][index].radioPosition = {
|
// newData[key][index].radioPosition = {
|
||||||
// topMin: topMin,
|
// topMin: topMin,
|
||||||
// topMax: topMax,
|
// topMax: topMax,
|
||||||
// leftMin: leftMin,
|
// leftMin: leftMin,
|
||||||
// leftMax: leftMax,
|
// leftMax: leftMax,
|
||||||
// width: leftMax - leftMin,
|
// width: leftMax - leftMin,
|
||||||
// height: topMax - topMin
|
// height: topMax - topMin
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// newData[key][index].dimensions.left = x;
|
// newData[key][index].dimensions.left = x;
|
||||||
// newData[key][index].dimensions.top = y;
|
// newData[key][index].dimensions.top = y;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// setDroppedItems({ ...newData });
|
// setDroppedItems({ ...newData });
|
||||||
// };
|
// };
|
||||||
|
|
||||||
// const handleMouseUp = () => {
|
// const handleMouseUp = () => {
|
||||||
// document.removeEventListener("pointermove", handleMouseMove);
|
// document.removeEventListener("pointermove", handleMouseMove);
|
||||||
// document.removeEventListener("pointerup", handleMouseUp);
|
// document.removeEventListener("pointerup", handleMouseUp);
|
||||||
// };
|
// };
|
||||||
|
|
||||||
// // Add event listeners
|
// // Add event listeners
|
||||||
// document.addEventListener("pointermove", handleMouseMove);
|
// document.addEventListener("pointermove", handleMouseMove);
|
||||||
// document.addEventListener("pointerup", handleMouseUp);
|
// document.addEventListener("pointerup", handleMouseUp);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
// NEW DIRECTIONAL MOVEMENT HANDLER - START
|
// NEW DIRECTIONAL MOVEMENT HANDLER - START
|
||||||
const handleDirectionalMove = (direction: 'up' | 'down' | 'left' | 'right', stepSize: number = 5) => {
|
const handleDirectionalMove = (direction: 'up' | 'down' | 'left' | 'right', stepSize: number = 5) => {
|
||||||
if (!selectedTag) return;
|
if (!selectedTag) return;
|
||||||
|
|
||||||
const { key, index } = selectedTag;
|
const { key, index } = selectedTag;
|
||||||
const currentItem = droppedItems[key]?.[index];
|
const currentItem = droppedItems[key]?.[index];
|
||||||
|
|
||||||
if (!currentItem) return;
|
if (!currentItem) return;
|
||||||
|
|
||||||
let newLeft = currentItem.dimensions.left;
|
let newLeft = currentItem.dimensions.left;
|
||||||
let newTop = currentItem.dimensions.top;
|
let newTop = currentItem.dimensions.top;
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case 'up':
|
case 'up':
|
||||||
newTop = Math.max(0, newTop - stepSize);
|
newTop = Math.max(0, newTop - stepSize);
|
||||||
break;
|
break;
|
||||||
case 'down':
|
case 'down':
|
||||||
newTop = newTop + stepSize;
|
newTop = newTop + stepSize;
|
||||||
break;
|
break;
|
||||||
case 'left':
|
case 'left':
|
||||||
newLeft = Math.max(0, newLeft - stepSize);
|
newLeft = Math.max(0, newLeft - stepSize);
|
||||||
break;
|
break;
|
||||||
case 'right':
|
case 'right':
|
||||||
newLeft = newLeft + stepSize;
|
newLeft = newLeft + stepSize;
|
||||||
break;
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function handleIGroupBorderPosition(groupId: string) {
|
||||||
|
|
||||||
|
const groupElements: NodeListOf<HTMLElement> = document.querySelectorAll(`div[group="${groupId}"]`);
|
||||||
|
|
||||||
|
let targetContainer = groupElements[0].parentElement?.parentElement;
|
||||||
|
console.log(targetContainer, "targetContainer line 421")
|
||||||
|
let targetElement = groupElements[0].parentElement;
|
||||||
|
|
||||||
|
if (!targetContainer || !targetElement) return;
|
||||||
|
const containerRect = targetContainer.getBoundingClientRect();
|
||||||
|
|
||||||
|
handleGroupBorderPosition(groupElements, containerRect, 40, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
return (
|
||||||
const directionalControlsHandler = (direction: 'up' | 'down' | 'left' | 'right') => {
|
<>
|
||||||
handleDirectionalMove(direction, 5); // Use default stepSize of 5
|
{/* 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.pages && doc.pages.length > 0 && doc.pages.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 */}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function handleIGroupBorderPosition(groupId: string) {
|
{/* Expand Circle - STARTS */}
|
||||||
|
{item.type !== "radio" && <div
|
||||||
const groupElements: NodeListOf<HTMLElement> = document.querySelectorAll(`div[group="${groupId}"]`);
|
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'>
|
||||||
let targetContainer = groupElements[0].parentElement?.parentElement;
|
|
||||||
console.log(targetContainer, "targetContainer line 421")
|
|
||||||
let targetElement = groupElements[0].parentElement;
|
|
||||||
|
|
||||||
if (!targetContainer || !targetElement) return;
|
|
||||||
const containerRect = targetContainer.getBoundingClientRect();
|
|
||||||
|
|
||||||
handleGroupBorderPosition(groupElements, containerRect, 40, 40);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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>}
|
</div>}
|
||||||
{/* If Selected Tag Recipient Info- END */}
|
{/* Expand Circle - ENDS */}
|
||||||
|
|
||||||
|
{/* Tag - START */}
|
||||||
|
{
|
||||||
|
<div
|
||||||
{/* Expand Circle - STARTS */}
|
{...("group" in item && item.group ? { "group": item.group } : {})}
|
||||||
{item.type !== "radio" && <div
|
onPointerDown={(e) => handleTagMouseDown(e, key, index)}
|
||||||
onPointerDown={(e) => handleExpandTag(e, key, index)}
|
className='p-2 rounded-sm h-full shadow opacity-40 cursor-grab w-full'
|
||||||
className='w-2.5 h-2.5 absolute bg-red-400 rounded-full bottom-[-8px] right-[-8px] cursor-nw-resize hover:bg-blue-400'>
|
style={{ background: selectedRecipient[0]?.color }}
|
||||||
</div>}
|
|
||||||
{/* Expand Circle - ENDS */}
|
|
||||||
|
|
||||||
{/* Tag - START */}
|
|
||||||
{
|
|
||||||
<div
|
|
||||||
{...("group" in item && item.group ? { "group": item.group } : {})}
|
|
||||||
onPointerDown={(e) => handleTagMouseDown(e, key, index)}
|
|
||||||
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
|
||||||
</p>
|
className={`flex justify-center items-center w-full text-xl text-white h-full`}
|
||||||
</div>
|
// style={{ color: selectedRecipients[item.recipientIndx]?.color }}
|
||||||
|
>
|
||||||
|
{IconComponent}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
{/* Tag - END */}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{
|
||||||
|
"group" in item && item.group && "isGroupExist" in item && !item.isGroupExist &&
|
||||||
|
<>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="group-border" border-group={item.group} border-pos="top"></div>
|
||||||
|
<div className="group-border" border-group={item.group} border-pos="right"></div>
|
||||||
|
<div className="group-border bottom-border" border-group={item.group} border-pos="bottom">
|
||||||
|
<div onClick={() => handleAddGroupItemClicked(key, item)}><IoAdd /></div>
|
||||||
|
</div>
|
||||||
|
<div className="group-border" border-group={item.group} border-pos="left"></div>
|
||||||
|
</>
|
||||||
|
|
||||||
}
|
}
|
||||||
{/* Tag - END */}
|
|
||||||
|
|
||||||
</div>
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
{
|
)}
|
||||||
"group" in item && item.group && "isGroupExist" in item && !item.isGroupExist &&
|
{/* Render only the dropped items for this specific docId and page - ENDS */}
|
||||||
<>
|
|
||||||
|
|
||||||
|
<img
|
||||||
<div className="group-border" border-group={item.group} border-pos="top"></div>
|
style={{ "minWidth": page.width, "minHeight": page.height, "maxWidth": page.width, "maxHeight": page.height }}
|
||||||
<div className="group-border" border-group={item.group} border-pos="right"></div>
|
draggable="false"
|
||||||
<div className="group-border bottom-border" border-group={item.group} border-pos="bottom">
|
width={page.width}
|
||||||
<div onClick={() => handleAddGroupItemClicked(key, item)}><IoAdd /></div>
|
height={page.height}
|
||||||
</div>
|
src={page.src}
|
||||||
<div className="group-border" border-group={item.group} border-pos="left"></div>
|
loading='lazy'
|
||||||
</>
|
/>
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
)}
|
|
||||||
{/* 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 */}
|
{/* 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'>
|
<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}
|
page {indx + 1} of {doc.pages && doc.pages.length}
|
||||||
</p>
|
</p>
|
||||||
{/* <p className='absolute top-[50%] translate-y-[-50%] rotate-[-90deg] text-xs right-[-140px] text-slate-600'>
|
{/* <p className='absolute top-[50%] translate-y-[-50%] rotate-[-90deg] text-xs right-[-140px] text-slate-600'>
|
||||||
Document {indxDoc + 1} {doc.name}
|
Document {indxDoc + 1} {doc.name}
|
||||||
</p> */}
|
</p> */}
|
||||||
{/* Side details of documents Pages and document Name - END */}
|
{/* Side details of documents Pages and document Name - END */}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
}) : <Loader />
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div >
|
||||||
)
|
|
||||||
}) : <Loader />
|
|
||||||
}
|
|
||||||
|
|
||||||
|
{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 */}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
</div >
|
export default DocumentContainer;
|
||||||
|
|
||||||
{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;
|
|
||||||
|
|
|
||||||
|
|
@ -133,10 +133,10 @@ const LeftSideBar: React.FC<LeftSideBarProps> = ({ isFields, selectedRecipientIn
|
||||||
onClick={() => setDropDownTogglePage(`${(dropDownTogglePage === 'pageDropDown' + indx) ? '' : 'pageDropDown' + indx}`)}
|
onClick={() => setDropDownTogglePage(`${(dropDownTogglePage === 'pageDropDown' + indx) ? '' : 'pageDropDown' + indx}`)}
|
||||||
className={`p-2 ${(dropDownTogglePage === 'pageDropDown' + indx) ? "bg-[var(--primary)]" : "bg-slate-200"} flex flex-col justify-center items-center gap-2 rounded`}>
|
className={`p-2 ${(dropDownTogglePage === 'pageDropDown' + indx) ? "bg-[var(--primary)]" : "bg-slate-200"} flex flex-col justify-center items-center gap-2 rounded`}>
|
||||||
{
|
{
|
||||||
document.images != undefined && <img
|
document.pages != undefined && <img
|
||||||
key={indx}
|
key={indx}
|
||||||
className='rounded-sm shadow'
|
className='rounded-sm shadow'
|
||||||
src={document.images[0].src}
|
src={document.pages[0].src}
|
||||||
alt="" />
|
alt="" />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,7 +151,7 @@ const LeftSideBar: React.FC<LeftSideBarProps> = ({ isFields, selectedRecipientIn
|
||||||
{
|
{
|
||||||
dropDownTogglePage === 'pageDropDown' + indx &&
|
dropDownTogglePage === 'pageDropDown' + indx &&
|
||||||
<div className='my-1 flex justify-center items-center gap-1 flex-wrap'>
|
<div className='my-1 flex justify-center items-center gap-1 flex-wrap'>
|
||||||
{document.images != undefined && document.images.map((img, indx) => (
|
{document.pages != undefined && document.pages.map((img, indx) => (
|
||||||
<a
|
<a
|
||||||
href={"#" + document.id + indx}
|
href={"#" + document.id + indx}
|
||||||
className='max-w-max px-4 py-2 shadow cursor-pointer border-1 rounded-sm border-slate-200 hover:border-[var(--primary)] transition-all duration-300 bg-slate-300'
|
className='max-w-max px-4 py-2 shadow cursor-pointer border-1 rounded-sm border-slate-200 hover:border-[var(--primary)] transition-all duration-300 bg-slate-300'
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import { Bounce, toast } from "react-toastify";
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { SaveType } from '../client/SignDocument';
|
import { SaveType } from '../client/SignDocument';
|
||||||
import { CiSaveDown1 } from 'react-icons/ci';
|
import { CiSaveDown1 } from 'react-icons/ci';
|
||||||
|
import api from '../../config/api';
|
||||||
|
|
||||||
interface Signature {
|
interface Signature {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -54,6 +55,7 @@ interface AddSignatureModalProps {
|
||||||
setOpenSign: React.Dispatch<React.SetStateAction<boolean>>;
|
setOpenSign: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
saved: SaveType;
|
saved: SaveType;
|
||||||
setSaved: React.Dispatch<React.SetStateAction<SaveType>>;
|
setSaved: React.Dispatch<React.SetStateAction<SaveType>>;
|
||||||
|
signTagId: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Account {
|
interface Account {
|
||||||
|
|
@ -80,9 +82,12 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
setOpenSign,
|
setOpenSign,
|
||||||
recipientId,
|
recipientId,
|
||||||
saved,
|
saved,
|
||||||
setSaved
|
setSaved,
|
||||||
|
signTagId
|
||||||
}) => {
|
}) => {
|
||||||
const [activeTab, setActiveTab] = useState<'TYPED' | 'DRAW' | 'UPLOAD'>('TYPED');
|
|
||||||
|
console.log("savedModal", saved)
|
||||||
|
const [activeTab, setActiveTab] = useState<'TYPED' | 'DRAW' | 'UPLOAD' | 'SAVED'>('TYPED');
|
||||||
const [fullName, setFullName] = useState('');
|
const [fullName, setFullName] = useState('');
|
||||||
const [initials, setInitials] = useState('');
|
const [initials, setInitials] = useState('');
|
||||||
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
|
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
|
||||||
|
|
@ -100,6 +105,22 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
{ id: 6, name: 'classic', initials: 'LA', style: 'classic' },
|
{ id: 6, name: 'classic', initials: 'LA', style: 'classic' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// User data
|
||||||
|
const [user, setUser] = useState<UserData>({
|
||||||
|
id: "",
|
||||||
|
firstName: "",
|
||||||
|
lastName: "",
|
||||||
|
email: "",
|
||||||
|
language: "",
|
||||||
|
account: {
|
||||||
|
id: 0,
|
||||||
|
isDefault: false,
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("User data", user)
|
||||||
|
|
||||||
const [selectedSignature, setSelectedSignature] = useState<SelectStyle>(
|
const [selectedSignature, setSelectedSignature] = useState<SelectStyle>(
|
||||||
signatureOptions.length > 0 ? { id: signatureOptions[0].id, style: signatureOptions[0].style } : { id: 0, style: "" }
|
signatureOptions.length > 0 ? { id: signatureOptions[0].id, style: signatureOptions[0].style } : { id: 0, style: "" }
|
||||||
);
|
);
|
||||||
|
|
@ -112,21 +133,8 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
const [preview1, setPreview1] = useState<string | null>(null);
|
const [preview1, setPreview1] = useState<string | null>(null);
|
||||||
const [preview2, setPreview2] = useState<string | null>(null);
|
const [preview2, setPreview2] = useState<string | null>(null);
|
||||||
|
|
||||||
// User data
|
const [preSaveSignatures, setPreSaveSignatures] = useState([])
|
||||||
// const [user, setUser] = useState<UserData>({
|
|
||||||
// id: "",
|
|
||||||
// firstName: "",
|
|
||||||
// lastName: "",
|
|
||||||
// email: "",
|
|
||||||
// language: "",
|
|
||||||
// account: {
|
|
||||||
// id: 0,
|
|
||||||
// isDefault: false,
|
|
||||||
// name: "",
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const isEditMode = !!editingSignature;
|
|
||||||
|
|
||||||
// Navigation items
|
// Navigation items
|
||||||
const navigationItems = [
|
const navigationItems = [
|
||||||
|
|
@ -136,34 +144,6 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
{ id: 'SAVED', label: 'SAVED', icon: <CiSaveDown1 className="w-5 h-5" /> },
|
{ id: 'SAVED', label: 'SAVED', icon: <CiSaveDown1 className="w-5 h-5" /> },
|
||||||
];
|
];
|
||||||
|
|
||||||
// Initialize form with editing signature data
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (editingSignature) {
|
|
||||||
// setFullName(`${editingSignature.firstName} ${editingSignature.lastName}`);
|
|
||||||
// setInitials(`${editingSignature.firstName.slice(0, 1)}${editingSignature.lastName.slice(0, 1)}`);
|
|
||||||
// setActiveTab(editingSignature.signatureType as 'TYPED' | 'DRAW' | 'UPLOAD');
|
|
||||||
|
|
||||||
// // Set font for SELECT tab
|
|
||||||
// const fontOption = signatureOptions.find(option => option.style === editingSignature.font);
|
|
||||||
// if (fontOption) {
|
|
||||||
// setSelectedSignature({ id: fontOption.id, style: fontOption.style });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Set signature blobs for all tabs
|
|
||||||
// if (editingSignature.signatureBlob && editingSignature.initialsBlob) {
|
|
||||||
// setSignatures({
|
|
||||||
// fullSignature: `data:image/png;base64,${editingSignature.signatureBlob}`,
|
|
||||||
// initials: `data:image/png;base64,${editingSignature.initialsBlob}`
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // Set preview URLs for UPLOAD tab
|
|
||||||
// if (editingSignature.signatureType === 'UPLOAD') {
|
|
||||||
// setPreview1(`data:image/png;base64,${editingSignature.signatureBlob}`);
|
|
||||||
// setPreview2(`data:image/png;base64,${editingSignature.initialsBlob}`);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }, [editingSignature]);
|
|
||||||
|
|
||||||
const handleSignatureChange = (data: { fullSignature: string | null; initials: string | null }) => {
|
const handleSignatureChange = (data: { fullSignature: string | null; initials: string | null }) => {
|
||||||
setSignatures(data);
|
setSignatures(data);
|
||||||
|
|
@ -177,8 +157,10 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
"ngrok-skip-browser-warning": "69420"
|
"ngrok-skip-browser-warning": "69420"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if (res?.data) {
|
||||||
console.log(res, "Geting Signatures")
|
let preSavedSignatures = res?.data
|
||||||
|
setPreSaveSignatures(preSavedSignatures)
|
||||||
|
}
|
||||||
})()
|
})()
|
||||||
}, [])
|
}, [])
|
||||||
// Getting Signatures - END
|
// Getting Signatures - END
|
||||||
|
|
@ -225,7 +207,7 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
setIsSubmitting(true);
|
setIsSubmitting(true);
|
||||||
console.log("handleSubmit Called")
|
console.log("handleSubmit Called")
|
||||||
if (!signatures.fullSignature || !signatures.initials) {
|
if (!signatures.fullSignature || !signatures.initials) {
|
||||||
alert('Please provide both signature and initials');
|
alert('Please provide both signature and initials');
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
|
|
@ -234,15 +216,18 @@ console.log("handleSubmit Called")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const payload = {
|
const payload = {
|
||||||
signatureType: activeTab,
|
tagId: signTagId,
|
||||||
signatureBase64: signatures.fullSignature,
|
// signatureId: signatureId,
|
||||||
initialsBase64: signatures.initials,
|
type: activeTab,
|
||||||
firstName: fullName.split(' ')[0] || user.firstName,
|
firstName: fullName.split(' ')[0] || user.firstName,
|
||||||
lastName: fullName.split(' ')[1] || user.lastName,
|
lastName: fullName.split(' ')[1] || user.lastName,
|
||||||
|
initials: "",
|
||||||
|
initialsBase64: signatures.initials,
|
||||||
|
signatureBase64: signatures.fullSignature,
|
||||||
font: selectedSignature.style
|
font: selectedSignature.style
|
||||||
};
|
};
|
||||||
|
|
||||||
let res;
|
console.log("payload", payload)
|
||||||
// if (isEditMode && editingSignature) {
|
// if (isEditMode && editingSignature) {
|
||||||
// // Update existing signature
|
// // Update existing signature
|
||||||
// const updatePayload = {
|
// const updatePayload = {
|
||||||
|
|
@ -265,7 +250,7 @@ console.log("handleSubmit Called")
|
||||||
// });
|
// });
|
||||||
// } else {
|
// } else {
|
||||||
// Create new signature
|
// Create new signature
|
||||||
res = await axios.post(`${import.meta.env.VITE_BASE_URI}/api/user/signatures`,
|
let res = await axios.post(`${import.meta.env.VITE_BASE_URI}/api/sign/signatures?recipientId=${recipientId}`,
|
||||||
payload,
|
payload,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -288,9 +273,19 @@ console.log("handleSubmit Called")
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (res?.data) {
|
if (res?.data) {
|
||||||
await getAllSignatures();
|
setSignatures({
|
||||||
setShowAddSignature?.(false);
|
fullSignature:"",
|
||||||
|
initials:"",
|
||||||
|
})
|
||||||
|
setSaved({
|
||||||
|
saveType: res.data.signatureType ?? null,
|
||||||
|
save: true,
|
||||||
|
signature: res.data.signatureBlob ?? null,
|
||||||
|
initial: res.data.initialsBlob ?? null,
|
||||||
|
});
|
||||||
|
setOpenSign(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error submitting signature:", error);
|
console.error("Error submitting signature:", error);
|
||||||
// toast.error(isEditMode ? "Failed to update signature" : "Failed to create signature", {
|
// toast.error(isEditMode ? "Failed to update signature" : "Failed to create signature", {
|
||||||
|
|
@ -431,32 +426,105 @@ console.log("handleSubmit Called")
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
case 'SAVED':
|
||||||
|
return (
|
||||||
|
<div className="h-full flex flex-col ">
|
||||||
|
<div className="mb-6">
|
||||||
|
<h2 className="text-xl font-semibold text-gray-900 mb-2">Saved Signature's</h2>
|
||||||
|
{/* <p className="text-sm text-gray-600">Select from pre-designed signature styles</p> */}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex-1 overflow-y-auto">
|
||||||
|
<div className="space-y-4">
|
||||||
|
{preSaveSignatures.map((signature) => (
|
||||||
|
<div key={signature?.id} className="grid grid-cols-12 gap-4 px-6 py-9 hover:bg-gray-50 transition-colors duration-150">
|
||||||
|
{/* Signature Column */}
|
||||||
|
<div className="col-span-5">
|
||||||
|
<div className="flex flex-col space-y-2 relative ps-6 border-l-3 border-blue-600 rounded-bl-2xl rounded-tl-2xl">
|
||||||
|
<div className="text-sm text-gray-600 font-medium mb-1">
|
||||||
|
Signed by:
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Signature Image or Fallback Text */}
|
||||||
|
<div className="bg-white rounded-lg p-1 flex items-center justify-center">
|
||||||
|
{signature?.signatureBlob ? (
|
||||||
|
<img
|
||||||
|
src={`data:${signature?.signatureMimeType || "image/png"};base64,${signature?.signatureBlob}`}
|
||||||
|
className="h-[50px] w-[250px] object-contain"
|
||||||
|
alt="Signature"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="text-gray-400 italic text-sm">No Signature</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Name */}
|
||||||
|
<div className="text-xs text-gray-500 truncate">
|
||||||
|
{signature?.signatureHash ?? ' '}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Initial Column */}
|
||||||
|
<div className="col-span-5">
|
||||||
|
<div className="flex flex-col space-y-2 relative ps-6 border-l-3 border-green-600 rounded-bl-2xl rounded-tl-2xl">
|
||||||
|
<div className="text-sm text-gray-600 font-medium mb-1">
|
||||||
|
Initials
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Initials Image */}
|
||||||
|
<div className="bg-white rounded-lg p-1 flex items-center justify-center">
|
||||||
|
{signature?.initialsBlob ? (
|
||||||
|
<img
|
||||||
|
src={`data:image/png;base64,${signature?.initialsBlob}`}
|
||||||
|
className="h-[50px] object-contain"
|
||||||
|
alt="Initials"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="text-gray-400 italic text-sm">No Initials</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Optional initials hash or font */}
|
||||||
|
<div className="text-xs text-gray-500 truncate">
|
||||||
|
{signature?.initialsHash || " "}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// const getUserDetails = async () => {
|
const getUserDetails = async () => {
|
||||||
// try {
|
try {
|
||||||
// let res = await api.get(`/api/user/details`);
|
let res = await axios.get(`/api/user/details`, {
|
||||||
// console.log("getuser", res);
|
headers: {
|
||||||
// let currUser = res?.data;
|
"ngrok-skip-browser-warning": "69420",
|
||||||
// setUser(currUser);
|
}
|
||||||
|
});
|
||||||
|
console.log("getuser", res);
|
||||||
|
let currUser = res?.data;
|
||||||
|
setUser(currUser);
|
||||||
|
|
||||||
// // Only set default values if not in edit mode
|
setFullName(currUser.firstName + " " + currUser.lastName);
|
||||||
// if (!isEditMode) {
|
setInitials(currUser.firstName.slice(0, 1) + currUser.lastName.slice(0, 1));
|
||||||
// setFullName(currUser.firstName + " " + currUser.lastName);
|
} catch (error) {
|
||||||
// setInitials(currUser.firstName.slice(0, 1) + currUser.lastName.slice(0, 1));
|
console.error("Error fetching user details:", error);
|
||||||
// }
|
}
|
||||||
// } catch (error) {
|
};
|
||||||
// console.error("Error fetching user details:", error);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// useEffect(() => {
|
useEffect(() => {
|
||||||
// getUserDetails();
|
getUserDetails();
|
||||||
// }, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 backdrop-blur-sm bg-opacity-50 flex items-center justify-center z-50 p-4">
|
<div className="fixed inset-0 backdrop-blur-sm bg-opacity-50 flex items-center justify-center z-50 p-4">
|
||||||
|
|
@ -468,7 +536,7 @@ console.log("handleSubmit Called")
|
||||||
<div className="px-4 py-4 border-b border-gray-200">
|
<div className="px-4 py-4 border-b border-gray-200">
|
||||||
<div className="flex items-center space-x-3">
|
<div className="flex items-center space-x-3">
|
||||||
<div className='px-1 py-1'>
|
<div className='px-1 py-1'>
|
||||||
<h3 className="text-md font-semibold text-gray-900">Add Signature</h3>
|
<h3 className="text-md font-semibold text-gray-900">Add Signature Sign</h3>
|
||||||
<p className="text-xs text-gray-500">Create your digital signature</p>
|
<p className="text-xs text-gray-500">Create your digital signature</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -511,7 +579,7 @@ console.log("handleSubmit Called")
|
||||||
{navigationItems.map((item) => (
|
{navigationItems.map((item) => (
|
||||||
<button
|
<button
|
||||||
key={item.id}
|
key={item.id}
|
||||||
onClick={() => setActiveTab(item.id as 'TYPED' | 'DRAW' | 'UPLOAD')}
|
onClick={() => setActiveTab(item.id as 'TYPED' | 'DRAW' | 'UPLOAD' | 'SAVED')}
|
||||||
className={`w-full flex items-center space-x-3 px-2 py-2 text-sm font-medium rounded-lg cursor-pointer transition-colors ${activeTab === item.id
|
className={`w-full flex items-center space-x-3 px-2 py-2 text-sm font-medium rounded-lg cursor-pointer transition-colors ${activeTab === item.id
|
||||||
? 'bg-blue-50 text-blue-700 border border-blue-200'
|
? 'bg-blue-50 text-blue-700 border border-blue-200'
|
||||||
: 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'
|
: 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,7 @@ canvas {
|
||||||
|
|
||||||
/* Group Border - END */
|
/* Group Border - END */
|
||||||
|
|
||||||
|
|
||||||
/* Loader CSS */
|
/* Loader CSS */
|
||||||
/* From Uiverse.io by Juanes200122 */
|
/* From Uiverse.io by Juanes200122 */
|
||||||
.pl {
|
.pl {
|
||||||
|
|
@ -333,4 +334,13 @@ canvas {
|
||||||
stroke-width: 20;
|
stroke-width: 20;
|
||||||
stroke-dashoffset: -440;
|
stroke-dashoffset: -440;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.bottom-border>div:hover {
|
||||||
|
background-color: var(--primaryLight2) ;
|
||||||
|
opacity: 0.9;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Group Border - END */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ export interface SelectedDocument {
|
||||||
extension: string;
|
extension: string;
|
||||||
original: boolean;
|
original: boolean;
|
||||||
corrupted?: boolean;
|
corrupted?: boolean;
|
||||||
images?: Image[];
|
pages?: Image[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PayloadSelectedDocument {
|
export interface PayloadSelectedDocument {
|
||||||
|
|
@ -30,7 +30,7 @@ export interface PayloadSelectedDocument {
|
||||||
extension: string;
|
extension: string;
|
||||||
original: boolean;
|
original: boolean;
|
||||||
corrupted?: boolean;
|
corrupted?: boolean;
|
||||||
images?: Image[];
|
pages?: Image[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SelectedDocumentsState {
|
interface SelectedDocumentsState {
|
||||||
|
|
@ -87,7 +87,7 @@ const selectedDocumentsSlice = createSlice({
|
||||||
const docId = document.documentId;
|
const docId = document.documentId;
|
||||||
for (const [index, selDoc] of state.selectedDocuments.entries()) {
|
for (const [index, selDoc] of state.selectedDocuments.entries()) {
|
||||||
if (selDoc.id === docId) {
|
if (selDoc.id === docId) {
|
||||||
state.selectedDocuments[index].images = document.images;
|
state.selectedDocuments[index].pages = document.pages;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -352,6 +352,7 @@ export interface Recipient {
|
||||||
type: recipientType;
|
type: recipientType;
|
||||||
color?: string;
|
color?: string;
|
||||||
roleName:string
|
roleName:string
|
||||||
|
provideOwnTags?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelectedRecipientInt {
|
export interface SelectedRecipientInt {
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,61 @@
|
||||||
import { JSX } from "react";
|
import { JSX } from "react";
|
||||||
|
|
||||||
export interface DroppedItem {
|
export interface DroppedItem {
|
||||||
id?: string;
|
id?: string;
|
||||||
icon: JSX.Element;
|
icon: JSX.Element;
|
||||||
focusElementIndx?: number;
|
focusElementIndx?: number;
|
||||||
label?: string;
|
label?: string;
|
||||||
type: string;
|
type: string;
|
||||||
subType?: string;
|
subType?: string;
|
||||||
dimensions: {
|
dimensions: {
|
||||||
left: number;
|
left: number;
|
||||||
top: number;
|
top: number;
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
}
|
}
|
||||||
recipientId: number;
|
recipientId: number;
|
||||||
// mask?: {
|
// mask?: {
|
||||||
// type: string;
|
// type: string;
|
||||||
// character: string;
|
// character: string;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
maskType?: string;
|
maskType?: string;
|
||||||
maskCharacter?: string;
|
maskCharacter?: string;
|
||||||
|
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
format?: string;
|
format?: string;
|
||||||
radioGroups?: DroppedItem[];
|
radioGroups?: DroppedItem[];
|
||||||
// documentIndex: number;
|
// documentIndex: number;
|
||||||
documentId: string;
|
documentId: string;
|
||||||
pageIndex: number;
|
pageIndex: number;
|
||||||
options?: string[]
|
options?: string[]
|
||||||
selectedValue?: string | null;
|
selectedValue?: string | null;
|
||||||
radioPosition?: {
|
radioPosition?: {
|
||||||
topMin: number;
|
topMin: number;
|
||||||
topMax: number;
|
topMax: number;
|
||||||
leftMin: number;
|
leftMin: number;
|
||||||
leftMax: number;
|
leftMax: number;
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number
|
height?: number
|
||||||
};
|
};
|
||||||
value?: string | number;
|
value?: string | number;
|
||||||
validation?: {
|
validation?: {
|
||||||
minLength: number;
|
minLength: number;
|
||||||
maxLength: number;
|
maxLength: number;
|
||||||
error: string;
|
error: string;
|
||||||
regex: string[];
|
regex: string[];
|
||||||
};
|
};
|
||||||
isDeleted: boolean;
|
isDeleted: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DroppedItemsObj {
|
export interface DroppedItemsObj {
|
||||||
[key: string]: DroppedItem[]
|
[key: string]: DroppedItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum OpenType {
|
export enum OpenType {
|
||||||
TYPED,
|
TYPED,
|
||||||
DRAW,
|
DRAW,
|
||||||
UPLOADED
|
UPLOADED
|
||||||
}
|
}
|
||||||
|
|
||||||
// types/account.ts
|
// types/account.ts
|
||||||
|
|
@ -81,39 +81,45 @@ export interface AccountData {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TagsProperties {
|
export interface TagsProperties {
|
||||||
"editable": boolean;
|
"editable": boolean;
|
||||||
"required": boolean;
|
"required": boolean;
|
||||||
"navigationOrder": number;
|
"navigationOrder": number;
|
||||||
"type": string;
|
"type": string;
|
||||||
"lastName"?: boolean;
|
"lastName"?: boolean;
|
||||||
"firstName"?: boolean;
|
"firstName"?: boolean;
|
||||||
"maxLength"?: number;
|
"maxLength"?: number;
|
||||||
"minLength"?: number;
|
"minLength"?: number;
|
||||||
"readOnly"?: boolean;
|
"readOnly"?: boolean;
|
||||||
"multiLine"?: boolean;
|
"multiLine"?: boolean;
|
||||||
"regex"?: string[];
|
"regex"?: string[];
|
||||||
"format"?: string;
|
"format"?: string;
|
||||||
"dateFormat"?: string;
|
"dateFormat"?: string;
|
||||||
"currentTimeStamp"?: boolean;
|
"currentTimeStamp"?: boolean;
|
||||||
"decimalPlace"?: number;
|
"decimalPlace"?: number;
|
||||||
"multiSelect"?: boolean;
|
"multiSelect"?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export enum TagsTypes {
|
export enum TagsTypes {
|
||||||
TEXT= "text",
|
TEXT = "text",
|
||||||
SIGNATURE= "signature",
|
SIGNATURE = "signature",
|
||||||
INITIALS= "initials",
|
INITIALS = "initials",
|
||||||
TEMPORAL= "temporal",
|
TEMPORAL = "temporal",
|
||||||
NUMBER= "number",
|
NUMBER = "number",
|
||||||
IMAGE= "image",
|
IMAGE = "image",
|
||||||
STAMP= "stamp",
|
STAMP = "stamp",
|
||||||
CHECKBOX= "checkbox",
|
CHECKBOX = "checkbox",
|
||||||
SELECT= "select",
|
SELECT = "select",
|
||||||
FILE= "file",
|
FILE = "file",
|
||||||
ATTACHMENT= "attachment",
|
ATTACHMENT = "attachment",
|
||||||
RADIO= "radio",
|
RADIO = "radio",
|
||||||
EMAIL= "email",
|
EMAIL = "email",
|
||||||
NAME= "name",
|
NAME = "name",
|
||||||
COMPANY= "company",
|
COMPANY = "company",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export enum SignTypeEnum {
|
||||||
|
selfSign = "self_sign",
|
||||||
|
multipleSign = "multi_sign"
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue