template&assessment-self-sign-first-form #14
|
|
@ -204,7 +204,7 @@ const Cards: React.FC<CardsProps> = ({ type = 'dashboard', onOpenModal, onDateRa
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full px-4 py-3 mt-2 rounded-md">
|
<div className="w-full px-3 rounded-md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex flex-col lg:flex-row items-start lg:items-center justify-between mb-2 gap-4">
|
<div className="flex flex-col lg:flex-row items-start lg:items-center justify-between mb-2 gap-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
|
|
@ -212,12 +212,12 @@ const Cards: React.FC<CardsProps> = ({ type = 'dashboard', onOpenModal, onDateRa
|
||||||
<FaFilter className="text-white text-lg" />
|
<FaFilter className="text-white text-lg" />
|
||||||
</div> */}
|
</div> */}
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-semibold text-gray-800">Overview</h2>
|
{/* <h2 className="text-lg font-semibold text-gray-800">Overview</h2> */}
|
||||||
{/* <p className="text-gray-600 text-sm">Monitor performance metrics</p> */}
|
{/* <p className="text-gray-600 text-sm">Monitor performance metrics</p> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Cards */}
|
{/* Cards */}
|
||||||
|
|
@ -231,11 +231,11 @@ const Cards: React.FC<CardsProps> = ({ type = 'dashboard', onOpenModal, onDateRa
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> :
|
</div> :
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4">
|
<div className="flex flex-wrap gap-2 justify-between">
|
||||||
{cards.map((card, index) => (
|
{cards.map((card, index) => (
|
||||||
<div
|
<div
|
||||||
key={card.title}
|
key={card.title}
|
||||||
className={`group relative overflow-hidden rounded-xl ${card.gradient} border border-white/40 p-4 transition-all duration-300 hover:scale-105 hover:shadow-lg ${card.shadowColor} cursor-pointer backdrop-blur-sm`}
|
className={`group relative overflow-hidden rounded-lg ${card.gradient} border border-white/40 px-3 py-1 transition-all duration-300 hover:scale-105 hover:shadow-lg ${card.shadowColor} cursor-pointer backdrop-blur-sm min-w-[200px] max-w-[220px]`}
|
||||||
style={{
|
style={{
|
||||||
animationDelay: `${index * 100}ms`
|
animationDelay: `${index * 100}ms`
|
||||||
}}
|
}}
|
||||||
|
|
@ -247,24 +247,20 @@ const Cards: React.FC<CardsProps> = ({ type = 'dashboard', onOpenModal, onDateRa
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className="relative z-10">
|
<div className="relative flex justify-between items-center z-10">
|
||||||
<div className="flex items-center justify-between mb-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className={`p-2 rounded-lg border ${card.iconBg} group-hover:scale-110 transition-transform duration-200`}>
|
<div className={`p-2 rounded-lg border ${card.iconBg} group-hover:scale-110 transition-transform duration-200`}>
|
||||||
{card.icon}
|
{card.icon}
|
||||||
</div>
|
</div>
|
||||||
{renderTrendIndicator(card.trend, card.percentage)}
|
<h3 className="text-sm font-medium text-gray-600 group-hover:text-gray-700 transition-colors">
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-1">
|
|
||||||
<h3 className="text-xs font-medium text-gray-600 group-hover:text-gray-700 transition-colors">
|
|
||||||
{card.title}
|
{card.title}
|
||||||
</h3>
|
</h3>
|
||||||
<div className="flex items-baseline gap-1">
|
</div>
|
||||||
<p className={`text-xl font-bold ${card.textColor} group-hover:scale-105 transition-transform duration-200`}>
|
|
||||||
{card.count}
|
<div className="flex items-center">
|
||||||
</p>
|
<p className={`text-xl font-bold ${card.textColor} group-hover:scale-105 transition-transform duration-200 leading-none mb-1`}>
|
||||||
<span className="text-[10px] text-gray-500">items</span>
|
{card.count}
|
||||||
</div>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ const Home = () => {
|
||||||
{
|
{
|
||||||
title: 'Action Needed',
|
title: 'Action Needed',
|
||||||
count: data.actionNeeded || 0,
|
count: data.actionNeeded || 0,
|
||||||
icon: <FaTasks size={18} className="text-indigo-600" />,
|
icon: <FaTasks size={15} className="text-indigo-600" />,
|
||||||
gradient: 'bg-gradient-to-br from-indigo-50 to-indigo-100',
|
gradient: 'bg-gradient-to-br from-indigo-50 to-indigo-100',
|
||||||
shadowColor: 'shadow-indigo-200/50',
|
shadowColor: 'shadow-indigo-200/50',
|
||||||
iconBg: 'bg-indigo-100 border-indigo-200',
|
iconBg: 'bg-indigo-100 border-indigo-200',
|
||||||
|
|
@ -43,7 +43,7 @@ const Home = () => {
|
||||||
{
|
{
|
||||||
title: 'Expiring Soon',
|
title: 'Expiring Soon',
|
||||||
count: data.expiring || 0,
|
count: data.expiring || 0,
|
||||||
icon: <FaHourglassHalf size={18} className="text-rose-600" />,
|
icon: <FaHourglassHalf size={15} className="text-rose-600" />,
|
||||||
gradient: 'bg-gradient-to-br from-rose-50 to-rose-100',
|
gradient: 'bg-gradient-to-br from-rose-50 to-rose-100',
|
||||||
shadowColor: 'shadow-rose-200/50',
|
shadowColor: 'shadow-rose-200/50',
|
||||||
iconBg: 'bg-rose-100 border-rose-200',
|
iconBg: 'bg-rose-100 border-rose-200',
|
||||||
|
|
@ -53,7 +53,7 @@ const Home = () => {
|
||||||
{
|
{
|
||||||
title: 'Completed',
|
title: 'Completed',
|
||||||
count: data.completed || 0,
|
count: data.completed || 0,
|
||||||
icon: <FaCheckCircle size={18} className="text-teal-600" />,
|
icon: <FaCheckCircle size={15} className="text-teal-600" />,
|
||||||
gradient: 'bg-gradient-to-br from-teal-50 to-teal-100',
|
gradient: 'bg-gradient-to-br from-teal-50 to-teal-100',
|
||||||
shadowColor: 'shadow-teal-200/50',
|
shadowColor: 'shadow-teal-200/50',
|
||||||
iconBg: 'bg-teal-100 border-teal-200',
|
iconBg: 'bg-teal-100 border-teal-200',
|
||||||
|
|
@ -63,7 +63,7 @@ const Home = () => {
|
||||||
{
|
{
|
||||||
title: 'Draft',
|
title: 'Draft',
|
||||||
count: data.draft || 0,
|
count: data.draft || 0,
|
||||||
icon: <FaClock size={18} className="text-stone-600" />,
|
icon: <FaClock size={15} className="text-stone-600" />,
|
||||||
gradient: 'bg-gradient-to-br from-blue-50 to-blue-100',
|
gradient: 'bg-gradient-to-br from-blue-50 to-blue-100',
|
||||||
shadowColor: 'shadow-blue-200/50',
|
shadowColor: 'shadow-blue-200/50',
|
||||||
iconBg: 'bg-blue-100 border-blue-200',
|
iconBg: 'bg-blue-100 border-blue-200',
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,17 @@ import api from "../../../config/api";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { RootState } from "../../../store/store";
|
import { RootState } from "../../../store/store";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
|
||||||
import { setImages } from "../../../store/slices/selectedDocsSlice";
|
import { setImages } from "../../../store/slices/selectedDocsSlice";
|
||||||
import { addRecipient, addRecipientAsync, fetchRecipients, recipientType, resetRecipients, toggleToTemplates, TRANSACTION_TEMPLATE_TOGGLE, updateRecipientIds } from "../../../store/slices/selectedRecipientsSlice";
|
import { addRecipient, addRecipientAsync, fetchRecipients, recipientType, removeAllRecipients, removeRecipientAsync, resetRecipients, toggleToTemplates, TRANSACTION_TEMPLATE_TOGGLE, updateRecipientIds } from "../../../store/slices/selectedRecipientsSlice";
|
||||||
import { setTransactionId, TRANSACTION_STATUS_ENUMS, updateTransactionStatus } from "../../../store/slices/transactionSlice";
|
import { setTransactionId, TRANSACTION_STATUS_ENUMS, updateTransactionStatus } from "../../../store/slices/transactionSlice";
|
||||||
import { hideLoader, showLoader } from "../../../store/slices/loaderSlice";
|
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";
|
import { SignTypeEnum } from "../../../utlity/types";
|
||||||
|
import { RiPencilFill } from "react-icons/ri";
|
||||||
|
import SelfSignWarnModal from "./SelfSignWarnModal";
|
||||||
|
|
||||||
const ProcessStepOne = () => {
|
const ProcessStepOne = () => {
|
||||||
interface EmailDtls {
|
interface EmailDtls {
|
||||||
|
|
@ -28,6 +30,9 @@ const ProcessStepOne = () => {
|
||||||
const signType = useParams<{ signType: string }>().signType;
|
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 }>();
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
console.log("searchParams", searchParams.get('useTemplate'))
|
||||||
|
const isTamplate = searchParams.get('useTemplate')
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
@ -54,10 +59,29 @@ 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 [showSelfSignWarnModal, setShowSelfSignWarnModal] = useState(false)
|
||||||
|
|
||||||
|
console.log()
|
||||||
const userData = useSelector((state: RootState) => state.user)
|
const userData = useSelector((state: RootState) => state.user)
|
||||||
// ProcessStepOne.tsx
|
// ProcessStepOne.tsx
|
||||||
const topRef = useRef<HTMLDivElement | null>(null);
|
const topRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
|
const [templateName, setTemplateName] = useState('Untitled');
|
||||||
|
const [isTyping, setIsTyping] = useState(false);
|
||||||
|
|
||||||
|
// Optional: use a timer to detect pause in typing
|
||||||
|
let typingTimeout = null;
|
||||||
|
|
||||||
|
const handleChange = (e) => {
|
||||||
|
setTemplateName(e.target.value);
|
||||||
|
setIsTyping(true);
|
||||||
|
|
||||||
|
clearTimeout(typingTimeout);
|
||||||
|
typingTimeout = setTimeout(() => {
|
||||||
|
setIsTyping(false);
|
||||||
|
}, 5000); // hide icon while typing, show it again after 500ms of no input
|
||||||
|
};
|
||||||
|
|
||||||
// const userData = useSelector((state: RootState) => state.user)
|
// const userData = useSelector((state: RootState) => state.user)
|
||||||
|
|
||||||
const [transactionDetails, setTransactionDetails] = useState<any>([]);
|
const [transactionDetails, setTransactionDetails] = useState<any>([]);
|
||||||
|
|
@ -71,6 +95,7 @@ const ProcessStepOne = () => {
|
||||||
try {
|
try {
|
||||||
const res = await api.get(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`);
|
const res = await api.get(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`);
|
||||||
setTransactionDetails(res.data)
|
setTransactionDetails(res.data)
|
||||||
|
// console.log("setTransactionDetails",res.data)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Error - transactions details")
|
console.log("Error - transactions details")
|
||||||
}
|
}
|
||||||
|
|
@ -111,38 +136,41 @@ const ProcessStepOne = () => {
|
||||||
subject: false
|
subject: false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selectedDocuments.length) {
|
if (transactionTemplateToggle !== TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES) {
|
||||||
formError.documents = true
|
if (!selectedDocuments.length) {
|
||||||
}
|
formError.documents = true
|
||||||
if (!selectedRecipients.length) {
|
}
|
||||||
formError.recipients = true
|
if (!selectedRecipients.length) {
|
||||||
}
|
formError.recipients = true
|
||||||
if (!emailDtls.subject.length) {
|
}
|
||||||
formError.subject = true
|
if (!emailDtls.subject.length) {
|
||||||
|
formError.subject = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SignTypeEnum.selfSign === signType) formError.recipients = false;
|
||||||
|
|
||||||
|
if (formError.documents || formError.recipients || formError.subject) {
|
||||||
|
console.log(selectedDocuments, 'line 193')
|
||||||
|
toast.dismiss();
|
||||||
|
toast.error(`${formError.documents ? "Add Document" : ""}
|
||||||
|
${(formError.documents && formError.recipients) ? " | " : ""}
|
||||||
|
${formError.recipients ? "Add Recipient" : ""}
|
||||||
|
${(formError.documents || formError.recipients) ? " | " : ""}
|
||||||
|
${formError.subject ? "Add Subject" : ""}`, {
|
||||||
|
position: "top-center",
|
||||||
|
autoClose: 5000,
|
||||||
|
hideProgressBar: false,
|
||||||
|
closeOnClick: false,
|
||||||
|
pauseOnHover: true,
|
||||||
|
draggable: true,
|
||||||
|
progress: undefined,
|
||||||
|
theme: "light",
|
||||||
|
transition: Bounce,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SignTypeEnum.selfSign === signType) formError.recipients = false;
|
|
||||||
|
|
||||||
if (formError.documents || formError.recipients || formError.subject) {
|
|
||||||
console.log(selectedDocuments, 'line 193')
|
|
||||||
toast.dismiss();
|
|
||||||
toast.error(`${formError.documents ? "Add Document" : ""}
|
|
||||||
${(formError.documents && formError.recipients) ? " | " : ""}
|
|
||||||
${formError.recipients ? "Add Recipient" : ""}
|
|
||||||
${(formError.documents || formError.recipients) ? " | " : ""}
|
|
||||||
${formError.subject ? "Add Subject" : ""}`, {
|
|
||||||
position: "top-center",
|
|
||||||
autoClose: 5000,
|
|
||||||
hideProgressBar: false,
|
|
||||||
closeOnClick: false,
|
|
||||||
pauseOnHover: true,
|
|
||||||
draggable: true,
|
|
||||||
progress: undefined,
|
|
||||||
theme: "light",
|
|
||||||
transition: Bounce,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dispatch(showLoader("Processing Documents..."));
|
dispatch(showLoader("Processing Documents..."));
|
||||||
|
|
@ -193,6 +221,17 @@ const ProcessStepOne = () => {
|
||||||
let recipientId = null;
|
let recipientId = null;
|
||||||
|
|
||||||
if (signType === SignTypeEnum.selfSign) {
|
if (signType === SignTypeEnum.selfSign) {
|
||||||
|
dispatch(removeAllRecipients());
|
||||||
|
await Promise.all(
|
||||||
|
selectedRecipients.map((recipient) => dispatch(removeRecipientAsync({
|
||||||
|
recipientId: recipient.id,
|
||||||
|
email: recipient.email,
|
||||||
|
accountId,
|
||||||
|
transactionId,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
recipientsDataTemp = [{
|
recipientsDataTemp = [{
|
||||||
id: null,
|
id: null,
|
||||||
routingOrder: 1,
|
routingOrder: 1,
|
||||||
|
|
@ -232,6 +271,7 @@ const ProcessStepOne = () => {
|
||||||
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}`, {
|
||||||
|
name: templateName,
|
||||||
subject: emailDtls.subject, message: emailDtls.message,
|
subject: emailDtls.subject, message: emailDtls.message,
|
||||||
status: "CREATED"
|
status: "CREATED"
|
||||||
})
|
})
|
||||||
|
|
@ -250,7 +290,7 @@ const ProcessStepOne = () => {
|
||||||
dispatch(hideLoader());
|
dispatch(hideLoader());
|
||||||
if (transactionTemplateToggle === TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES) {
|
if (transactionTemplateToggle === TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES) {
|
||||||
console.log(`/process-step-two/${accountId}/template/${transactionId}`)
|
console.log(`/process-step-two/${accountId}/template/${transactionId}`)
|
||||||
if(!saveAndClose) {
|
if (!saveAndClose) {
|
||||||
navigate(`/process-step-two/${accountId}/template/${transactionId}`)
|
navigate(`/process-step-two/${accountId}/template/${transactionId}`)
|
||||||
} else {
|
} else {
|
||||||
navigate(`/templates`)
|
navigate(`/templates`)
|
||||||
|
|
@ -299,6 +339,7 @@ const ProcessStepOne = () => {
|
||||||
const handleSelfSignCb = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleSelfSignCb = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
if (e.currentTarget.checked) {
|
if (e.currentTarget.checked) {
|
||||||
navigate("self_sign");
|
navigate("self_sign");
|
||||||
|
setShowSelfSignWarnModal((prev) => !prev)
|
||||||
} else {
|
} else {
|
||||||
navigate("./../");
|
navigate("./../");
|
||||||
}
|
}
|
||||||
|
|
@ -317,7 +358,21 @@ const ProcessStepOne = () => {
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
className='text-2xl text-slate-500 cursor-pointer hover:text-[var(--primary)] transition'
|
className='text-2xl text-slate-500 cursor-pointer hover:text-[var(--primary)] transition'
|
||||||
/>
|
/>
|
||||||
<p className="text-base font-normal text-gray-700 border-l pl-4">Add Recipient and Message</p>
|
<p className="text-base font-normal text-gray-700 border-l pl-4 relative">
|
||||||
|
{transactionTemplateToggle === TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES ?
|
||||||
|
<>
|
||||||
|
<input
|
||||||
|
value={templateName}
|
||||||
|
onChange={handleChange}
|
||||||
|
className="w-full px-4 py-1.5 border-2 border-dashed rounded-md text-sm focus:outline-none transition border-gray-300 focus:ring-2 focus:border-dashed focus:ring-[var(--primary)]"
|
||||||
|
/>
|
||||||
|
{!isTyping && (
|
||||||
|
<RiPencilFill className="absolute top-2.5 right-2 text-[17px]" />
|
||||||
|
)}
|
||||||
|
</> :
|
||||||
|
"Add Recipient and Message"
|
||||||
|
}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
@ -354,7 +409,7 @@ const ProcessStepOne = () => {
|
||||||
{/* Recipients */}
|
{/* Recipients */}
|
||||||
<section className="mt-8">
|
<section className="mt-8">
|
||||||
|
|
||||||
{
|
{!isTamplate &&
|
||||||
transactionTemplateToggle !== TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES &&
|
transactionTemplateToggle !== TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES &&
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<h2 className="text-lg font-medium mb-4 pt-6 border-t text-[var(--processStepOneTextHead)]">Signers</h2>
|
<h2 className="text-lg font-medium mb-4 pt-6 border-t text-[var(--processStepOneTextHead)]">Signers</h2>
|
||||||
|
|
@ -370,9 +425,9 @@ const ProcessStepOne = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
signType !== SignTypeEnum.selfSign &&
|
(signType !== SignTypeEnum.selfSign || showSelfSignWarnModal) &&
|
||||||
<div className="flex flex-col gap-4 align-start">
|
<div className="flex flex-col gap-4 align-start">
|
||||||
<RecipientCards transactionTemplateToggle={transactionTemplateToggle} setEditRecipient={setEditRecipient} setEditCase={setEditCase} />
|
<RecipientCards transactionTemplateToggle={transactionTemplateToggle} setEditRecipient={setEditRecipient} setEditCase={setEditCase} />
|
||||||
{/* {signType !== "self-sign" && <RecipientAddCard />} */}
|
{/* {signType !== "self-sign" && <RecipientAddCard />} */}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
@ -420,6 +475,7 @@ const ProcessStepOne = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{globalLoader.isLoading && <Loader />}
|
{globalLoader.isLoading && <Loader />}
|
||||||
|
{showSelfSignWarnModal && <SelfSignWarnModal setShowSelfSignWarnModal={setShowSelfSignWarnModal} />}
|
||||||
</div >
|
</div >
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { FaPlus } from "react-icons/fa";
|
import { FaPlus } from "react-icons/fa";
|
||||||
import { addRecipient, Recipient, recipientType, TRANSACTION_TEMPLATE_TOGGLE, updateRecipient } from "../../../store/slices/selectedRecipientsSlice";
|
import { addRecipient, Recipient, recipientType, TRANSACTION_TEMPLATE_TOGGLE, updateRecipient } from "../../../store/slices/selectedRecipientsSlice";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { AppDispatch } from "../../../store/store";
|
import { AppDispatch, RootState } from "../../../store/store";
|
||||||
import api from "../../../config/api";
|
import api from "../../../config/api";
|
||||||
import ContactModal from "./ContactModal";
|
import ContactModal from "./ContactModal";
|
||||||
import useDebouncedEffect from "../../../utlity/useDebounce";
|
import useDebouncedEffect from "../../../utlity/useDebounce";
|
||||||
|
|
@ -29,6 +29,8 @@ const RecipientAddCard = ({ transactionTemplateToggle, editRecipient, editCase,
|
||||||
JSON.parse(sessionStorage.getItem('activeAccountId') || 'null')
|
JSON.parse(sessionStorage.getItem('activeAccountId') || 'null')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const recipients = useSelector((state: RootState) => state.selectedRecipients.recipients);
|
||||||
|
console.log("recipients.length in AddCase", recipients)
|
||||||
|
|
||||||
const [contactData, setContactData] = useState<ContactTypeObj>({ type: "", contacts: [] });
|
const [contactData, setContactData] = useState<ContactTypeObj>({ type: "", contacts: [] });
|
||||||
const [openContactModal, setOpenContactModal] = useState(false);
|
const [openContactModal, setOpenContactModal] = useState(false);
|
||||||
|
|
@ -47,6 +49,14 @@ const RecipientAddCard = ({ transactionTemplateToggle, editRecipient, editCase,
|
||||||
const [lastQuery, setLastQuery] = useState<string | null>(null);
|
const [lastQuery, setLastQuery] = useState<string | null>(null);
|
||||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||||
const [manualFocusTriggered, setManualFocusTriggered] = useState(false);
|
const [manualFocusTriggered, setManualFocusTriggered] = useState(false);
|
||||||
|
const [errors, setErrors] = useState({
|
||||||
|
roleName: false,
|
||||||
|
lastName: false,
|
||||||
|
email: false,
|
||||||
|
emailFormat: false,
|
||||||
|
type: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
console.log(recipient)
|
console.log(recipient)
|
||||||
|
|
@ -62,7 +72,37 @@ const RecipientAddCard = ({ transactionTemplateToggle, editRecipient, editCase,
|
||||||
}, [openContactModal]);
|
}, [openContactModal]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Check if the recipient exists in the list (using uuid or id or email)
|
||||||
|
const exists = recipients.some((r) => {
|
||||||
|
return (
|
||||||
|
(r.uuid && r.uuid === editRecipient?.uuid) ||
|
||||||
|
(r.id && r.id === editRecipient?.id) ||
|
||||||
|
(r.email && r.email === editRecipient?.email)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
console.log("Line 83", exists)
|
||||||
if (editCase === "Edit" && editRecipient) {
|
if (editCase === "Edit" && editRecipient) {
|
||||||
|
console.log("editRecipientAdd", editRecipient)
|
||||||
|
if (!exists) {
|
||||||
|
// Recipient was deleted -> reset
|
||||||
|
setEditCase('');
|
||||||
|
setEditRecipient(null);
|
||||||
|
setRecipients({
|
||||||
|
firstName: "",
|
||||||
|
lastName: "",
|
||||||
|
email: "",
|
||||||
|
hostName: "",
|
||||||
|
hostEmail: "",
|
||||||
|
roleName: "",
|
||||||
|
type: recipientType.SIGNER,
|
||||||
|
allowSenderToEdit: true,
|
||||||
|
allowSenderToDelete: true,
|
||||||
|
uuid: "",
|
||||||
|
newOne: false,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setRecipients({
|
setRecipients({
|
||||||
// id:editRecipient.id,
|
// id:editRecipient.id,
|
||||||
firstName: editRecipient.firstName || "",
|
firstName: editRecipient.firstName || "",
|
||||||
|
|
@ -78,104 +118,135 @@ const RecipientAddCard = ({ transactionTemplateToggle, editRecipient, editCase,
|
||||||
newOne: editRecipient.newOne ?? false
|
newOne: editRecipient.newOne ?? false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [editCase, editRecipient]);
|
}, [editCase, editRecipient, recipients]);
|
||||||
|
|
||||||
|
|
||||||
const handleRecipientAdd = (e: React.FormEvent<HTMLFormElement>) => {
|
const handleRecipientAdd = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
console.log("recipientrecipient", recipient)
|
const newErrors = {
|
||||||
|
roleName: false,
|
||||||
|
lastName: false,
|
||||||
|
email: false,
|
||||||
|
emailFormat: false,
|
||||||
|
type: false,
|
||||||
|
};
|
||||||
|
|
||||||
if(transactionTemplateToggle === TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS) {
|
const roleNameFilled = recipient.roleName.trim();
|
||||||
if (!recipient.lastName || !recipient.email || !recipient.type) return;
|
const lastNameFilled = recipient.lastName.trim();
|
||||||
|
const emailFilled = recipient.email.trim();
|
||||||
|
const firstNameFilled = recipient.firstName.trim()
|
||||||
|
|
||||||
// ✅ Email format validation
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(recipient.email)) {
|
// 🔹 Check if we're in TRANSACTIONS mode
|
||||||
console.log("Invalid email format");
|
if (transactionTemplateToggle === TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS) {
|
||||||
|
if (lastNameFilled || emailFilled) {
|
||||||
|
if (lastNameFilled && !emailFilled) {
|
||||||
|
setErrors({ ...newErrors, email: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lastNameFilled && emailFilled) {
|
||||||
|
setErrors({ ...newErrors, lastName: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!emailRegex.test(emailFilled)) {
|
||||||
|
setErrors({ ...newErrors, emailFormat: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
submitForm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Neither lastName nor email is filled — treat as invalid
|
||||||
|
setErrors({ ...newErrors, lastName: true, email: true });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (editCase === 'Edit') {
|
|
||||||
dispatch(updateRecipient(recipient));
|
// // 1. If either lastName or email is filled, validate their presence mutually
|
||||||
} else {
|
// if ( emailFilled) {
|
||||||
dispatch(addRecipient({
|
|
||||||
...recipient,
|
// // if (lastNameFilled && !emailFilled) {
|
||||||
uuid: uuidv4(),
|
// // setErrors({ ...newErrors, email: true });
|
||||||
newOne: true
|
// // return;
|
||||||
}));
|
// // }
|
||||||
|
|
||||||
|
// // if (!lastNameFilled && emailFilled) {
|
||||||
|
// // setErrors({ ...newErrors, lastName: true });
|
||||||
|
// // return;
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// // // Both lastName and email are filled — check email format
|
||||||
|
// if (!emailRegex.test(emailFilled)) {
|
||||||
|
// setErrors({ ...newErrors, emailFormat: true });
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Passed validation, submit
|
||||||
|
// submitForm();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
if (roleNameFilled || lastNameFilled || emailFilled || firstNameFilled) {
|
||||||
|
submitForm()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
setRecipients({
|
// 2. If both lastName and email empty, validate roleName only
|
||||||
firstName: "",
|
if (!roleNameFilled) {
|
||||||
lastName: "",
|
setErrors({ ...newErrors, roleName: true });
|
||||||
email: "",
|
return;
|
||||||
hostName: "",
|
}
|
||||||
hostEmail: "",
|
|
||||||
roleName: "",
|
|
||||||
type: recipientType.SIGNER,
|
|
||||||
allowSenderToEdit: true,
|
|
||||||
allowSenderToDelete: true,
|
|
||||||
uuid: "",
|
|
||||||
newOne: false
|
|
||||||
});
|
|
||||||
|
|
||||||
// setRecipients(null),
|
// roleName filled, submit immediately
|
||||||
setEditCase("")
|
submitForm();
|
||||||
setManualFocusTriggered(false)
|
|
||||||
formRef.current?.reset();
|
function submitForm() {
|
||||||
|
if (editCase === 'Edit') {
|
||||||
|
dispatch(updateRecipient(recipient));
|
||||||
|
} else {
|
||||||
|
dispatch(addRecipient({
|
||||||
|
...recipient,
|
||||||
|
uuid: uuidv4(),
|
||||||
|
newOne: true,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
setRecipients({
|
||||||
|
firstName: "",
|
||||||
|
lastName: "",
|
||||||
|
email: "",
|
||||||
|
hostName: "",
|
||||||
|
hostEmail: "",
|
||||||
|
roleName: "",
|
||||||
|
type: recipientType.SIGNER,
|
||||||
|
allowSenderToEdit: true,
|
||||||
|
allowSenderToDelete: true,
|
||||||
|
uuid: "",
|
||||||
|
newOne: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
setErrors({
|
||||||
|
roleName: false,
|
||||||
|
lastName: false,
|
||||||
|
email: false,
|
||||||
|
emailFormat: false,
|
||||||
|
type: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
setEditCase("");
|
||||||
|
setManualFocusTriggered(false);
|
||||||
|
formRef.current?.reset();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (!recipient.firstName.length) return;
|
|
||||||
|
|
||||||
// const handler = setTimeout(() => {
|
|
||||||
// api.get(`/api/contact?firstName=${recipient.firstName}`)
|
|
||||||
// .then(res => {
|
|
||||||
// setContactData({ type: "firstName", contacts: res.data.content });
|
|
||||||
// })
|
|
||||||
// .catch(err => console.log(err));
|
|
||||||
// }, 500); // wait 500ms after the last change
|
|
||||||
|
|
||||||
// return () => {
|
|
||||||
// clearTimeout(handler); // cancel previous timeout if effect runs again
|
|
||||||
// };
|
|
||||||
|
|
||||||
// }, [recipient.firstName]);
|
|
||||||
|
|
||||||
// useDebouncedEffect(() => {
|
|
||||||
// if (!recipient.firstName.length) return;
|
|
||||||
// api.get(`/api/contact?firstName=${recipient.firstName}`)
|
|
||||||
// .then(res => {
|
|
||||||
// setContactData({ type: "firstName", contacts: res.data.content });
|
|
||||||
// })
|
|
||||||
// .catch(err => console.log(err));
|
|
||||||
// }, [recipient.firstName], 500);
|
|
||||||
|
|
||||||
// useDebouncedEffect(() => {
|
|
||||||
// if (!recipient.lastName.length) return
|
|
||||||
// api.get(`/api/contact?lastName=${recipient.lastName}`)
|
|
||||||
// .then(res => {
|
|
||||||
// setContactData({ type: "lastName", contacts: res.data.content });
|
|
||||||
// })
|
|
||||||
// .catch(err => console.log(err))
|
|
||||||
// }, [recipient.lastName], 500);
|
|
||||||
|
|
||||||
// useDebouncedEffect(() => {
|
|
||||||
// if (!recipient.email.length) return
|
|
||||||
// api.get(`/api/contact?email=${recipient.email}`)
|
|
||||||
// .then(res => {
|
|
||||||
// setContactData({ type: "email", contacts: res.data.content });
|
|
||||||
// })
|
|
||||||
// .catch(err => console.log(err))
|
|
||||||
// }, [recipient.email], 500);
|
|
||||||
|
|
||||||
const handleContactModalBlur = () => {
|
const handleContactModalBlur = () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setOpenContactModal(false)
|
setOpenContactModal(false)
|
||||||
|
|
@ -249,131 +320,138 @@ setManualFocusTriggered(false)
|
||||||
}
|
}
|
||||||
}, [recipient.firstName, recipient.lastName, recipient.email], 300);
|
}, [recipient.firstName, recipient.lastName, recipient.email], 300);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (e: MouseEvent | FocusEvent) => {
|
const handleClickOutside = (e: MouseEvent | FocusEvent) => {
|
||||||
if (
|
if (
|
||||||
containerRef.current &&
|
containerRef.current &&
|
||||||
!containerRef.current.contains(e.target as Node)
|
!containerRef.current.contains(e.target as Node)
|
||||||
) {
|
) {
|
||||||
setOpenContactModal(false);
|
setOpenContactModal(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener("mousedown", handleClickOutside);
|
document.addEventListener("mousedown", handleClickOutside);
|
||||||
document.addEventListener("focusin", handleClickOutside); // Also handles tabbing out
|
document.addEventListener("focusin", handleClickOutside); // Also handles tabbing out
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener("mousedown", handleClickOutside);
|
document.removeEventListener("mousedown", handleClickOutside);
|
||||||
document.removeEventListener("focusin", handleClickOutside);
|
document.removeEventListener("focusin", handleClickOutside);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={containerRef}>
|
<div ref={containerRef}>
|
||||||
<form
|
<form
|
||||||
ref={formRef}
|
ref={formRef}
|
||||||
onSubmit={handleRecipientAdd}
|
onSubmit={handleRecipientAdd}
|
||||||
id="add-recipient-step-one"
|
id="add-recipient-step-one"
|
||||||
className="w-full bg-white border border-gray-200 rounded-lg shadow-md px-6 py-4 space-y-3 relative"
|
className="w-full bg-white border border-gray-200 rounded-lg shadow-md px-6 py-4 space-y-3 relative"
|
||||||
>
|
>
|
||||||
{transactionTemplateToggle === TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES && (
|
{transactionTemplateToggle === TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES && (
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
{/* Top Row: Role Input + Settings */}
|
{/* Top Row: Role Input + Settings */}
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
{/* Role Name Input */}
|
{/* Role Name Input */}
|
||||||
<input
|
{/* Role Name Input */}
|
||||||
required={recipient.firstName === "" && recipient.lastName === "" && recipient.email === ""}
|
<div className="w-64">
|
||||||
type="text"
|
<input
|
||||||
onFocus={() => setOpenContactModal(true)}
|
type="text"
|
||||||
onBlur={handleContactModalBlur}
|
value={recipient.roleName}
|
||||||
value={recipient.roleName}
|
placeholder="Role name"
|
||||||
placeholder="Role name"
|
className={`w-full px-3 py-2 border rounded-md text-sm focus:outline-none transition
|
||||||
className="w-64 px-3 py-2 me-3 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-[var(--primary)] transition"
|
${errors.roleName ? 'border-red-500 ring-2 ring-red-300' : 'border-gray-300 focus:ring-2 focus:ring-[var(--primary)]'}`}
|
||||||
onChange={(e) => setRecipients({ ...recipient, roleName: e.target.value })}
|
onChange={(e) => {
|
||||||
/>
|
setRecipients({ ...recipient, roleName: e.target.value });
|
||||||
|
setErrors(prev => ({ ...prev, roleName: false }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{errors.roleName && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">Role is required.</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Settings + Permissions */}
|
|
||||||
<div className="flex items-center">
|
{/* Settings + Permissions */}
|
||||||
<div className="flex justify-between">
|
<div className="flex items-center">
|
||||||
{/* Permission Status Text - Always Visible when settings open */}
|
<div className="flex justify-between w-full">
|
||||||
<div
|
{/* Permission Status Text - Always Visible */}
|
||||||
className={`transition-all duration-600 ease-in-out ${showAdvanceSettings ? 'max-h-10 opacity-100 me-3' : 'max-h-0 opacity-0 '
|
<div className="max-h-10 opacity-100 me-3 overflow-hidden">
|
||||||
} overflow-hidden`}
|
<div className="text-sm text-gray-600 pt-0.5">
|
||||||
>
|
{/* {recipient.allowSenderToEdit && recipient.allowSenderToDelete && "Full permissions granted"}
|
||||||
<div className="text-sm text-gray-600">
|
{recipient.allowSenderToEdit && !recipient.allowSenderToDelete && "Edit permission granted"}
|
||||||
{recipient.allowSenderToEdit && recipient.allowSenderToDelete && "Full permissions granted"}
|
{!recipient.allowSenderToEdit && recipient.allowSenderToDelete && "Delete permission granted"}
|
||||||
{recipient.allowSenderToEdit && !recipient.allowSenderToDelete && "Edit permission granted"}
|
{!recipient.allowSenderToEdit && !recipient.allowSenderToDelete && "No permissions granted"} */}
|
||||||
{!recipient.allowSenderToEdit && recipient.allowSenderToDelete && "Delete permission granted"}
|
Permissions granted :
|
||||||
{!recipient.allowSenderToEdit && !recipient.allowSenderToDelete && "No permissions granted"}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{/* Animated Permission Controls */}
|
{/* Permission Controls - Always Visible */}
|
||||||
<div className={`overflow-visible transition-all duration-900 ease-in-out ${showAdvanceSettings ? 'max-w-80 opacity-100' : 'max-w-0 opacity-0'
|
<div className="max-w-80 opacity-100 overflow-visible">
|
||||||
}`}>
|
<div className="flex items-center space-x-3 pr-1.5">
|
||||||
<div className="flex items-center space-x-3 pr-1.5">
|
{/* Edit Permission */}
|
||||||
{/* Edit Permission */}
|
<div className="relative group">
|
||||||
<div className="relative group">
|
<label
|
||||||
<label
|
className={`relative flex items-center justify-center w-12 h-7 border-2 rounded-lg cursor-pointer transition-all duration-300 transform hover:scale-105 ${recipient.allowSenderToEdit
|
||||||
className={`relative flex items-center justify-center w-6 h-6 border-2 rounded-lg cursor-pointer transition-all duration-300 transform hover:scale-105 ${recipient.allowSenderToEdit
|
? 'bg-blue-100 border-blue-500 shadow-md'
|
||||||
? 'bg-blue-100 border-blue-500 shadow-lg'
|
: 'bg-white border-gray-300 hover:border-blue-400 text-gray-400'
|
||||||
: 'bg-white border-gray-300 hover:border-blue-400'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={recipient.allowSenderToEdit}
|
|
||||||
onChange={(e) =>
|
|
||||||
setRecipients({ ...recipient, allowSenderToEdit: e.target.checked })
|
|
||||||
}
|
|
||||||
onFocus={() => setOpenContactModal(true)}
|
|
||||||
onBlur={handleContactModalBlur}
|
|
||||||
className="absolute w-full h-full opacity-0 cursor-pointer"
|
|
||||||
/>
|
|
||||||
<FiEdit
|
|
||||||
className={`w-3 h-3 pointer-events-none transition-all duration-300 ${recipient.allowSenderToEdit ? 'text-blue-600' : 'text-gray-400'
|
|
||||||
}`}
|
}`}
|
||||||
/>
|
>
|
||||||
</label>
|
<input
|
||||||
{/* Tooltip */}
|
type="checkbox"
|
||||||
<div className="absolute bottom-0 -translate-y-full left-1/2 transform -translate-x-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none z-20">
|
checked={recipient.allowSenderToEdit}
|
||||||
<div className="bg-gray-800 text-white text-xs rounded-lg py-2 px-3 whitespace-nowrap">
|
onChange={(e) =>
|
||||||
Allow Edit Permission
|
setRecipients({ ...recipient, allowSenderToEdit: e.target.checked })
|
||||||
<div className="absolute bottom-[-5px] left-1/2 transform -translate-x-1/2 border-4 border-transparent border-b-gray-800"></div>
|
}
|
||||||
|
onFocus={() => setOpenContactModal(true)}
|
||||||
|
onBlur={handleContactModalBlur}
|
||||||
|
className="absolute w-full h-full opacity-0 cursor-pointer"
|
||||||
|
/>
|
||||||
|
<FiEdit
|
||||||
|
className={`w-2.5 h-2.5 pointer-events-none transition-all duration-300 ${recipient.allowSenderToEdit ? 'text-blue-600' : 'text-gray-400'
|
||||||
|
}`}
|
||||||
|
/><span className="ms-0.5 text-[12px]">Edit</span>
|
||||||
|
</label>
|
||||||
|
{/* Tooltip */}
|
||||||
|
<div className="absolute bottom-0 -translate-y-full left-1/2 transform -translate-x-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none z-20">
|
||||||
|
<div className="bg-gray-800 text-white text-xs rounded-lg py-2 px-3 whitespace-nowrap">
|
||||||
|
Edit Permission
|
||||||
|
<div className="absolute bottom-[-5px] left-1/2 transform -translate-x-1/2 border-4 border-transparent border-b-gray-800"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Delete Permission */}
|
{/* Delete Permission */}
|
||||||
<div className="relative group">
|
<div className="relative group">
|
||||||
<label
|
<label
|
||||||
className={`relative flex items-center justify-center w-6 h-6 border-2 rounded-lg cursor-pointer transition-all duration-300 transform hover:scale-105 ${recipient.allowSenderToDelete
|
className={`relative flex items-center justify-center w-15 h-7 border-2 rounded-lg cursor-pointer transition-all duration-300 transform hover:scale-105 ${recipient.allowSenderToDelete
|
||||||
? 'bg-red-100 border-red-500 shadow-lg'
|
? 'bg-red-100 border-red-500 shadow-md'
|
||||||
: 'bg-white border-gray-300 hover:border-red-400'
|
: 'bg-white border-gray-300 hover:border-red-400 text-gray-400'
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={recipient.allowSenderToDelete}
|
|
||||||
onChange={(e) =>
|
|
||||||
setRecipients({ ...recipient, allowSenderToDelete: e.target.checked })
|
|
||||||
}
|
|
||||||
onFocus={() => setOpenContactModal(true)}
|
|
||||||
onBlur={handleContactModalBlur}
|
|
||||||
className="absolute w-full h-full opacity-0 cursor-pointer"
|
|
||||||
/>
|
|
||||||
<FiTrash
|
|
||||||
className={`w-3 h-3 pointer-events-none transition-all duration-300 ${recipient.allowSenderToDelete ? 'text-red-600' : 'text-gray-400'
|
|
||||||
}`}
|
}`}
|
||||||
/>
|
>
|
||||||
</label>
|
<input
|
||||||
{/* Tooltip */}
|
type="checkbox"
|
||||||
<div className="absolute bottom-0 -translate-y-full left-1/2 transform -translate-x-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none z-20">
|
checked={recipient.allowSenderToDelete}
|
||||||
<div className="bg-gray-800 text-white text-xs rounded-lg py-2 px-3 whitespace-nowrap">
|
onChange={(e) =>
|
||||||
Allow Delete Permission
|
setRecipients({ ...recipient, allowSenderToDelete: e.target.checked })
|
||||||
<div className="absolute bottom-[-5px] left-1/2 transform -translate-x-1/2 border-4 border-transparent border-b-gray-800"></div>
|
}
|
||||||
|
onFocus={() => setOpenContactModal(true)}
|
||||||
|
onBlur={handleContactModalBlur}
|
||||||
|
className="absolute w-full h-full opacity-0 cursor-pointer"
|
||||||
|
/>
|
||||||
|
<FiTrash
|
||||||
|
className={`w-3 h-3 pointer-events-none transition-all duration-300 ${recipient.allowSenderToDelete ? 'text-red-600' : 'text-gray-400'
|
||||||
|
}`}
|
||||||
|
/><span className="ms-0.5 text-[12px]">Delete</span>
|
||||||
|
</label>
|
||||||
|
{/* Tooltip */}
|
||||||
|
<div className="absolute bottom-0 -translate-y-full left-1/2 transform -translate-x-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none z-20">
|
||||||
|
<div className="bg-gray-800 text-white text-xs rounded-lg py-2 px-3 whitespace-nowrap">
|
||||||
|
Delete Permission
|
||||||
|
<div className="absolute bottom-[-5px] left-1/2 transform -translate-x-1/2 border-4 border-transparent border-b-gray-800"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -381,137 +459,142 @@ useEffect(() => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Settings Icon */}
|
|
||||||
<div className="relative group">
|
|
||||||
<p
|
|
||||||
className="text-blue-600 hover:text-blue-700 cursor-pointer transition-colors duration-200 p-2 rounded-full hover:bg-blue-50"
|
|
||||||
onClick={() => setShowAdvanceSettings((prev) => !prev)}
|
|
||||||
>
|
|
||||||
<IoIosSettings
|
|
||||||
className={`h-6 w-6 transition-transform duration-300 ${showAdvanceSettings ? 'rotate-90' : 'rotate-0'
|
|
||||||
}`}
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
{/* Tooltip */}
|
|
||||||
<div className="absolute top-0 -translate-y-full left-1/2 transform -translate-x-1/2 mb-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none z-20">
|
|
||||||
<div className="bg-gray-800 text-white text-xs rounded-lg py-2 px-3 whitespace-nowrap">
|
|
||||||
Advanced Settings
|
|
||||||
<div className="absolute bottom-[-6px] left-1/2 transform -translate-x-1/2 border-4 border-transparent border-b-gray-800"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Name Inputs */}
|
||||||
|
<div className="grid grid-cols-12 gap-4 mt-3">
|
||||||
|
<div className="col-span-4">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
onFocus={() => handleFocus("firstName")}
|
||||||
|
onBlur={handleContactModalBlur}
|
||||||
|
value={recipient.firstName}
|
||||||
|
placeholder="First Name"
|
||||||
|
className={` w-full px-4 py-2 border rounded-md text-sm focus:outline-none transition
|
||||||
|
${errors.firstName ? 'border-red-500 ring-2 ring-red-300' : 'border-gray-300 focus:ring-2 focus:ring-[var(--primary)]'}`}
|
||||||
|
onChange={(e) => {
|
||||||
|
setRecipients({ ...recipient, firstName: e.target.value });
|
||||||
|
// setErrors((prev) => ({ ...prev, firstName: false }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/* {errors.firstName && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">First Name is required</p>
|
||||||
|
)} */}
|
||||||
|
<div className="col-span-4">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
onFocus={() => handleFocus("lastName")}
|
||||||
|
onBlur={handleContactModalBlur}
|
||||||
|
value={recipient.lastName}
|
||||||
|
placeholder="Last Name"
|
||||||
|
className={` w-full px-4 py-2 border rounded-md text-sm focus:outline-none transition
|
||||||
|
${errors.lastName ? 'border-red-500 ring-2 ring-red-300' : 'border-gray-300 focus:ring-2 focus:ring-[var(--primary)]'}`}
|
||||||
|
onChange={(e) => {
|
||||||
|
setRecipients({ ...recipient, lastName: e.target.value });
|
||||||
|
setErrors((prev) => ({ ...prev, lastName: false }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{errors.lastName && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">Last Name is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="col-span-4">
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
onFocus={() => handleFocus("email")}
|
||||||
|
onBlur={handleContactModalBlur}
|
||||||
|
value={recipient.email}
|
||||||
|
placeholder="Recipient Email"
|
||||||
|
className={`w-full px-4 py-2 border rounded-md text-sm focus:outline-none transition
|
||||||
|
${errors.email ? 'border-red-500 ring-2 ring-red-300' : 'border-gray-300 focus:ring-2 focus:ring-[var(--primary)]'}`}
|
||||||
|
onChange={(e) => {
|
||||||
|
setRecipients({ ...recipient, email: e.target.value });
|
||||||
|
setErrors((prev) => ({ ...prev, email: false }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{errors.email && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">Email is required</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Name Inputs */}
|
|
||||||
<div className="grid grid-cols-12 gap-4 mt-3">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
onFocus={() => handleFocus("firstName")}
|
|
||||||
onBlur={handleContactModalBlur}
|
|
||||||
value={recipient.firstName}
|
|
||||||
placeholder="First Name"
|
|
||||||
className="col-span-4 w-full px-4 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-[var(--primary)] transition"
|
|
||||||
onChange={(e) => setRecipients({ ...recipient, firstName: e.target.value })}
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
required={transactionTemplateToggle !== TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES}
|
|
||||||
type="text"
|
|
||||||
onFocus={() => handleFocus("lastName")}
|
|
||||||
onBlur={handleContactModalBlur}
|
|
||||||
value={recipient.lastName}
|
|
||||||
placeholder="Last Name"
|
|
||||||
className="col-span-4 w-full px-4 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-[var(--primary)] transition"
|
|
||||||
onChange={(e) => setRecipients({ ...recipient, lastName: e.target.value })}
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
required={transactionTemplateToggle !== TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES}
|
|
||||||
type="email"
|
|
||||||
onFocus={() => handleFocus("email")}
|
|
||||||
onBlur={handleContactModalBlur}
|
|
||||||
value={recipient.email}
|
|
||||||
placeholder="Recipient Email"
|
|
||||||
className="col-span-4 w-full px-4 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-[var(--primary)] transition"
|
|
||||||
onChange={(e) => setRecipients({ ...recipient, email: e.target.value })}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
{recipient.type === recipientType.INPERSONSIGNER && <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
{recipient.type === recipientType.INPERSONSIGNER && <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||||
<input
|
<input
|
||||||
required={transactionTemplateToggle !== TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES}
|
required={transactionTemplateToggle !== TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES}
|
||||||
type="text"
|
type="text"
|
||||||
onFocus={() => setOpenContactModal(true)}
|
onFocus={() => setOpenContactModal(true)}
|
||||||
onBlur={handleContactModalBlur}
|
onBlur={handleContactModalBlur}
|
||||||
value={recipient.hostName}
|
value={recipient.hostName}
|
||||||
placeholder="Host Name"
|
placeholder="Host Name"
|
||||||
className="w-full px-4 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-[var(--primary)] transition"
|
className="w-full px-4 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-[var(--primary)] transition"
|
||||||
onChange={(e) => setRecipients({ ...recipient, hostName: e.target.value })}
|
onChange={(e) => setRecipients({ ...recipient, hostName: e.target.value })}
|
||||||
/>
|
|
||||||
<input
|
|
||||||
required={transactionTemplateToggle !== TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES}
|
|
||||||
type="email"
|
|
||||||
onFocus={() => setOpenContactModal(true)}
|
|
||||||
onBlur={handleContactModalBlur}
|
|
||||||
value={recipient.hostEmail}
|
|
||||||
placeholder="Host Email"
|
|
||||||
className="w-full px-4 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-[var(--primary)] transition"
|
|
||||||
onChange={(e) => setRecipients({ ...recipient, hostEmail: e.target.value })}
|
|
||||||
/>
|
|
||||||
</div>}
|
|
||||||
|
|
||||||
{/* Contact Modal */}
|
|
||||||
{openContactModal && contactData.contacts.length > 0 && (
|
|
||||||
<div className="absolute z-50 mt-1 w-2/3 max-h-[50vh] bg-white shadow-lg rounded-md p-3 border border-gray-100 overflow-y-auto no-scrollbar">
|
|
||||||
<ContactModal
|
|
||||||
contactData={contactData}
|
|
||||||
inpFirstName={recipient.firstName}
|
|
||||||
inpLastName={recipient.lastName}
|
|
||||||
inpEmail={recipient.email}
|
|
||||||
openContactModal={openContactModal}
|
|
||||||
setRecipients={setRecipients}
|
|
||||||
setOpenContactModal={setOpenContactModal}
|
|
||||||
topRef={topRef}
|
|
||||||
setManualFocusTriggered={setManualFocusTriggered}
|
|
||||||
/>
|
/>
|
||||||
|
<input
|
||||||
|
required={transactionTemplateToggle !== TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES}
|
||||||
|
type="email"
|
||||||
|
onFocus={() => setOpenContactModal(true)}
|
||||||
|
onBlur={handleContactModalBlur}
|
||||||
|
value={recipient.hostEmail}
|
||||||
|
placeholder="Host Email"
|
||||||
|
className="w-full px-4 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-[var(--primary)] transition"
|
||||||
|
onChange={(e) => setRecipients({ ...recipient, hostEmail: e.target.value })}
|
||||||
|
/>
|
||||||
|
</div>}
|
||||||
|
|
||||||
|
{/* Contact Modal */}
|
||||||
|
{openContactModal && contactData.contacts.length > 0 && (
|
||||||
|
<div className="absolute z-50 mt-1 w-2/3 max-h-[50vh] bg-white shadow-lg rounded-md p-3 border border-gray-100 overflow-y-auto no-scrollbar">
|
||||||
|
<ContactModal
|
||||||
|
contactData={contactData}
|
||||||
|
inpFirstName={recipient.firstName}
|
||||||
|
inpLastName={recipient.lastName}
|
||||||
|
inpEmail={recipient.email}
|
||||||
|
openContactModal={openContactModal}
|
||||||
|
setRecipients={setRecipients}
|
||||||
|
setOpenContactModal={setOpenContactModal}
|
||||||
|
topRef={topRef}
|
||||||
|
setManualFocusTriggered={setManualFocusTriggered}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{/* Signing options + Add button in one line */}
|
||||||
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||||
|
<div className="flex flex-wrap gap-6">
|
||||||
|
{[
|
||||||
|
{ label: "Signer", value: recipientType.SIGNER },
|
||||||
|
{ label: "In Person Signer", value: recipientType.INPERSONSIGNER },
|
||||||
|
{ label: "CC", value: recipientType.CC },
|
||||||
|
].map((option) => (
|
||||||
|
<label key={option.value} className="flex items-center gap-2 text-gray-700 text-sm cursor-pointer">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="recipient-type"
|
||||||
|
value={option.value}
|
||||||
|
defaultChecked={option.value === recipientType.SIGNER}
|
||||||
|
onClick={(e) => setRecipients({ ...recipient, type: e.target.value })}
|
||||||
|
className="accent-[var(--primary)] cursor-pointer"
|
||||||
|
/>
|
||||||
|
{option.label}
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="inline-flex items-center gap-2 bg-[var(--primary)] hover:bg-[var(--primaryLight2)] text-white text-sm font-semibold px-5 py-2 rounded-md transition"
|
||||||
|
>
|
||||||
|
<FaPlus size={14} /> {editCase === "Edit" ? "Edit Recipient" : "Add Recipient"}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{/* Signing options + Add button in one line */}
|
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
|
||||||
<div className="flex flex-wrap gap-6">
|
|
||||||
{[
|
|
||||||
{ label: "Signer", value: recipientType.SIGNER },
|
|
||||||
{ label: "In Person Signer", value: recipientType.INPERSONSIGNER },
|
|
||||||
{ label: "CC", value: recipientType.CC },
|
|
||||||
].map((option) => (
|
|
||||||
<label key={option.value} className="flex items-center gap-2 text-gray-700 text-sm cursor-pointer">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="recipient-type"
|
|
||||||
value={option.value}
|
|
||||||
defaultChecked={option.value === recipientType.SIGNER}
|
|
||||||
onClick={(e) => setRecipients({ ...recipient, type: e.target.value })}
|
|
||||||
className="accent-[var(--primary)] cursor-pointer"
|
|
||||||
/>
|
|
||||||
{option.label}
|
|
||||||
</label>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="inline-flex items-center gap-2 bg-[var(--primary)] hover:bg-[var(--primaryLight2)] text-white text-sm font-semibold px-5 py-2 rounded-md transition"
|
|
||||||
>
|
|
||||||
<FaPlus size={14} /> {editCase === "Edit" ? "Edit Recipient" : "Add Recipient"}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import {
|
||||||
removeRecipientAsync,
|
removeRecipientAsync,
|
||||||
removeSelectedRecipient,
|
removeSelectedRecipient,
|
||||||
// setSigningOrder,
|
// setSigningOrder,
|
||||||
updateRecipientOrder, // 👈 You need to define this in your slice
|
updateRecipientOrder,
|
||||||
} from "../../../store/slices/selectedRecipientsSlice";
|
} from "../../../store/slices/selectedRecipientsSlice";
|
||||||
import { AppDispatch, RootState } from "../../../store/store";
|
import { AppDispatch, RootState } from "../../../store/store";
|
||||||
|
|
||||||
|
|
@ -14,6 +14,7 @@ import SigningOrderDiagram from "../../../SigningOrderDiagram ";
|
||||||
import { IoCloseOutline } from "react-icons/io5";
|
import { IoCloseOutline } from "react-icons/io5";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { FiEdit } from "react-icons/fi";
|
import { FiEdit } from "react-icons/fi";
|
||||||
|
import { RiPencilFill } from "react-icons/ri";
|
||||||
|
|
||||||
const getInitials = (name: string) => {
|
const getInitials = (name: string) => {
|
||||||
if (!name) return "";
|
if (!name) return "";
|
||||||
|
|
@ -30,7 +31,7 @@ type CardsData = {
|
||||||
transactionTemplateToggle: string
|
transactionTemplateToggle: string
|
||||||
};
|
};
|
||||||
|
|
||||||
const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateToggle }: CardsData) => {
|
const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateToggle , editRecipient ,editCase }: CardsData) => {
|
||||||
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 }>();
|
||||||
|
|
||||||
|
|
@ -59,7 +60,6 @@ const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateTogg
|
||||||
|
|
||||||
const handleRemoveRecipient = (recipient) => {
|
const handleRemoveRecipient = (recipient) => {
|
||||||
if (!accountId || !transactionId) return;
|
if (!accountId || !transactionId) return;
|
||||||
// <<<<<<< HEAD
|
|
||||||
// dispatch(removeSelectedRecipient(recipient))
|
// dispatch(removeSelectedRecipient(recipient))
|
||||||
// dispatch(removeRecipientAsync([{
|
// dispatch(removeRecipientAsync([{
|
||||||
// recipientId: recipient.id,
|
// recipientId: recipient.id,
|
||||||
|
|
@ -67,7 +67,7 @@ const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateTogg
|
||||||
// accountId: accountId,
|
// accountId: accountId,
|
||||||
// transactionId: transactionId,
|
// transactionId: transactionId,
|
||||||
// }]))
|
// }]))
|
||||||
// =======
|
// =======
|
||||||
if (recipient.uuid) {
|
if (recipient.uuid) {
|
||||||
dispatch(removeSelectedRecipient(recipient))
|
dispatch(removeSelectedRecipient(recipient))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -78,7 +78,6 @@ const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateTogg
|
||||||
transactionId: transactionId,
|
transactionId: transactionId,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
// >>>>>>> origin/main
|
|
||||||
if (recipients.length === 2) {
|
if (recipients.length === 2) {
|
||||||
let leftRecipient = recipients.filter((obj) => {
|
let leftRecipient = recipients.filter((obj) => {
|
||||||
if ("id" in obj && "id" in recipient) {
|
if ("id" in obj && "id" in recipient) {
|
||||||
|
|
@ -135,24 +134,28 @@ const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateTogg
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3 min-w-0">
|
<div className="flex items-center gap-3 min-w-0">
|
||||||
{/* {signingOrder && ( */}
|
{/* {signingOrder && ( */}
|
||||||
{recipients.length > 1 ? <input
|
{recipients.length > 1 ? <div className="relative">
|
||||||
type="number"
|
<input
|
||||||
value={recipient.routingOrder || 1}
|
type="number"
|
||||||
min={1}
|
value={recipient.routingOrder || 1}
|
||||||
onChange={(e) =>
|
min={1}
|
||||||
handleOrderChange(recipient.id || recipient.email, Number(e.target.value))
|
onChange={(e) =>
|
||||||
}
|
handleOrderChange(recipient.id || recipient.email, Number(e.target.value))
|
||||||
className="w-8 text-center rounded text-sm text-gray-700 border-none focus:outline-none focus:ring-[var(--primary)]"
|
}
|
||||||
/> : <input
|
className="w-10 h-6 text-center rounded text-sm text-gray-600 focus:outline-none focus:ring-[var(--primary)] border border-dashed border-gray-400 bg-slate-100"
|
||||||
type="number"
|
/>
|
||||||
disabled
|
{/* <RiPencilFill className="absolute top-1.5 right-0 text-[14px] text-gray-500" /> */}
|
||||||
value={recipient.routingOrder || 1}
|
</div>
|
||||||
min={1}
|
: <input
|
||||||
onChange={(e) =>
|
type="number"
|
||||||
handleOrderChange(recipient.id || recipient.email, Number(e.target.value))
|
disabled
|
||||||
}
|
value={recipient.routingOrder || 1}
|
||||||
className="w-8 text-center rounded text-sm text-gray-700 border-none focus:outline-none focus:ring-[var(--primary)]"
|
min={1}
|
||||||
/>}
|
onChange={(e) =>
|
||||||
|
handleOrderChange(recipient.id || recipient.email, Number(e.target.value))
|
||||||
|
}
|
||||||
|
className="w-8 text-center rounded text-sm text-gray-700 border-none focus:outline-none focus:ring-[var(--primary)]"
|
||||||
|
/>}
|
||||||
{/* )} */}
|
{/* )} */}
|
||||||
|
|
||||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-[var(--primary)] text-white flex items-center justify-center font-semibold text-xs select-none">
|
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-[var(--primary)] text-white flex items-center justify-center font-semibold text-xs select-none">
|
||||||
|
|
@ -220,11 +223,10 @@ const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateTogg
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
{signingOrderModal.open &&
|
{signingOrderModal.open &&
|
||||||
<div className="fixed top-0 left-0 inset-0 z-50 bg-black/50 backdrop-blur-sm flex justify-center items-center">
|
<div className="fixed top-0 left-0 inset-0 z-50 bg-black/50 backdrop-blur-sm flex justify-center items-center">
|
||||||
<div className="flex-col relative justify-center items-center max-w-[80%] max-h-[60vh] h-full overflow-auto">
|
<div className="flex-col relative justify-center items-center max-w-[80%] max-h-[60vh] h-full overflow-auto">
|
||||||
<div className="pb-2 text-white flex justify-between items-center">
|
<div className="p-2 rounded-t-lg text-white flex justify-between items-center bg-[var(--primary)]">
|
||||||
<p className="font-semibold">Signing Order</p>
|
<p className="font-semibold">Signing Order</p>
|
||||||
<div
|
<div
|
||||||
onClick={() => setSigningOrderModal({ ...signingOrderModal, open: false })}
|
onClick={() => setSigningOrderModal({ ...signingOrderModal, open: false })}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
type PropsType = {
|
||||||
|
setShowSelfSignWarnModal: (val: boolean) => void;
|
||||||
|
onConfirm: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SelfSignWarnModal = ({ setShowSelfSignWarnModal }: PropsType) => {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="fixed inset-0 backdrop-blur-sm flex items-center justify-center z-50">
|
||||||
|
<div className="bg-white rounded-lg shadow-xl p-6 w-100">
|
||||||
|
<h3 className="text-lg font-medium text-gray-800 mb-4">Confirm Self Sign</h3>
|
||||||
|
<p className="text-gray-600 mb-6">
|
||||||
|
Are you sure you want to proceed with self sign? This will remove all the recipient that you added.
|
||||||
|
</p>
|
||||||
|
<div className="flex justify-end gap-3">
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setShowSelfSignWarnModal(false);
|
||||||
|
navigate("./../");
|
||||||
|
}}
|
||||||
|
|
||||||
|
className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded-md transition-colors"
|
||||||
|
>
|
||||||
|
No
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
// onConfirm();
|
||||||
|
setShowSelfSignWarnModal(false);
|
||||||
|
}}
|
||||||
|
className="px-4 py-2 bg-red-600 text-white hover:bg-red-700 rounded-md transition-colors"
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SelfSignWarnModal;
|
||||||
|
|
@ -78,7 +78,7 @@ const Templates = () => {
|
||||||
let res = await api.post(`/api/accounts/${activeAccountId}/transactions`, payload)
|
let res = await api.post(`/api/accounts/${activeAccountId}/transactions`, payload)
|
||||||
console.log("handleUseClick", res.data)
|
console.log("handleUseClick", res.data)
|
||||||
// /process-step-one/:accountId/:transactionId
|
// /process-step-one/:accountId/:transactionId
|
||||||
navigate(`/process-step-one/${activeAccountId}/${res?.data?.id}`);
|
navigate(`/process-step-one/${activeAccountId}/${res?.data?.id}?useTemplate=true`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,18 @@ canvas {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Chrome, Safari, Edge, Opera */
|
||||||
|
input::-webkit-outer-spin-button,
|
||||||
|
input::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Firefox */
|
||||||
|
input[type=number] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
/* Group Border - START */
|
/* Group Border - START */
|
||||||
.group-border {
|
.group-border {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
||||||
|
|
@ -437,6 +437,8 @@ export const removeRecipientAsync = createAsyncThunk<
|
||||||
|
|
||||||
const basePath = `/api/accounts/${accountId}/${toggle}/${transactionId}/recipients`;
|
const basePath = `/api/accounts/${accountId}/${toggle}/${transactionId}/recipients`;
|
||||||
|
|
||||||
|
console.log(`Line 440 : ${basePath}/${recipientId}`)
|
||||||
|
// return
|
||||||
if (recipientId) {
|
if (recipientId) {
|
||||||
await api.delete(`${basePath}/${recipientId}`);
|
await api.delete(`${basePath}/${recipientId}`);
|
||||||
return recipientId;
|
return recipientId;
|
||||||
|
|
@ -481,7 +483,7 @@ const selectedRecipientsSlice = createSlice({
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
addRecipient: (state, action: PayloadAction<Recipient>) => {
|
addRecipient: (state, action: PayloadAction<Recipient>) => {
|
||||||
|
|
||||||
// Checking if meail already exist - START
|
// Checking if meail already exist - START
|
||||||
// for (const recipient of state.recipients) {
|
// for (const recipient of state.recipients) {
|
||||||
// if (recipient.email === action.payload.email) {
|
// if (recipient.email === action.payload.email) {
|
||||||
|
|
@ -533,6 +535,9 @@ const selectedRecipientsSlice = createSlice({
|
||||||
removeSelectedRecipient: (state, action: PayloadAction<Recipient>) => {
|
removeSelectedRecipient: (state, action: PayloadAction<Recipient>) => {
|
||||||
state.recipients = state.recipients.filter((recipient) => recipient.uuid !== action.payload.uuid);
|
state.recipients = state.recipients.filter((recipient) => recipient.uuid !== action.payload.uuid);
|
||||||
},
|
},
|
||||||
|
removeAllRecipients: (state) => {
|
||||||
|
state.recipients = [];
|
||||||
|
},
|
||||||
addColorsToRecipient: (state) => {
|
addColorsToRecipient: (state) => {
|
||||||
for (const [index, recipient] of state.recipients.entries()) {
|
for (const [index, recipient] of state.recipients.entries()) {
|
||||||
recipient.color = colors[index];
|
recipient.color = colors[index];
|
||||||
|
|
@ -639,6 +644,7 @@ export const {
|
||||||
setSelectedRecipients,
|
setSelectedRecipients,
|
||||||
toggleToTemplates,
|
toggleToTemplates,
|
||||||
removeSelectedRecipient,
|
removeSelectedRecipient,
|
||||||
|
removeAllRecipients,
|
||||||
setSigningOrder,
|
setSigningOrder,
|
||||||
addColorsToRecipient,
|
addColorsToRecipient,
|
||||||
updateRecipientIds,
|
updateRecipientIds,
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@ const JoyrideController = () => {
|
||||||
),
|
),
|
||||||
placement: "left",
|
placement: "left",
|
||||||
disableBeacon: true,
|
disableBeacon: true,
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
target: "#start-now-upload-con",
|
target: "#start-now-upload-con",
|
||||||
|
|
@ -63,7 +62,6 @@ const JoyrideController = () => {
|
||||||
),
|
),
|
||||||
placement: "top",
|
placement: "top",
|
||||||
disableBeacon: true,
|
disableBeacon: true,
|
||||||
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
} else if (location.pathname.includes("/process-step-one")) {
|
} else if (location.pathname.includes("/process-step-one")) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue