import { useDispatch, useSelector } from "react-redux"; import { removeRecipientAsync, removeSelectedRecipient, updateRecipientOrder, TRANSACTION_TEMPLATE_TOGGLE, updateRecipient, recipientType, } from "../../../store/slices/selectedRecipientsSlice"; import { AppDispatch, RootState } from "../../../store/store"; import { ImBin } from "react-icons/im"; import { useState } from "react"; import SigningOrderDiagram from "../../../SigningOrderDiagram "; import { IoCloseOutline } from "react-icons/io5"; import { useParams } from "react-router-dom"; import { FiEdit } from "react-icons/fi"; import { FaUsersLine } from "react-icons/fa6"; const getInitials = (name: string) => { if (!name) return ""; return name .split(" ") .map((n) => n[0]) .join("") .toUpperCase(); }; type CardsData = { userEmail: string; getMinRoutingOrder: () => number; editRecipient: any; setEditRecipient: (recipient: any) => void; setEditCase: (string: any) => void; transactionTemplateToggle: string; editRecipientCurrentEmail: string; setEditRecipientCurrentEmail: (email: string) => void; }; const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateToggle, editRecipient, editRecipientCurrentEmail, setEditRecipientCurrentEmail, }: CardsData) => { const templateId = useParams<{ templateId: string }>().templateId; let { accountId, transactionId } = useParams<{ accountId: string; transactionId: string }>(); const dispatch = useDispatch(); if (!transactionId) { transactionId = templateId; } const recipients = useSelector((state: RootState) => state.selectedRecipients.recipients); const signType = useSelector((state: RootState) => state.selectedDocuments.signType); const [signingOrderModal, setSigningOrderModal] = useState({ open: false }); const [editingField, setEditingField] = useState<{ recipientId: string; fieldName: string } | null>(null); const [localChanges, setLocalChanges] = useState>({}); const [errors, setErrors] = useState>({}); const getRecipientIdentifier = (recipient: any) => { return recipient.id || recipient.uuid; }; const isEditable = (recipient: any) => { return transactionTemplateToggle === TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES ? true : recipient.newOne || recipient.allowSenderToEdit; }; const validateInPersonSignerFields = (recipient: any, updatedFields: any) => { if (recipient.type !== recipientType.INPERSONSIGNER) return true; const hostName = updatedFields.hostName ?? getCurrentValue(recipient, "hostName"); const hostEmail = updatedFields.hostEmail ?? getCurrentValue(recipient, "hostEmail"); const identifier = getRecipientIdentifier(recipient); const newErrors = { hostName: !hostName, hostEmail: !hostEmail }; setErrors((prev) => ({ ...prev, [identifier]: newErrors })); return !newErrors.hostName && !newErrors.hostEmail; }; const handleFieldFocus = (recipientId: string, fieldName: string) => { setEditingField({ recipientId, fieldName }); }; const handleFieldBlur = (recipient: any, fieldName: string, value: any) => { const identifier = getRecipientIdentifier(recipient); const updatedRecipient = { ...recipient, [fieldName]: value, uuid: identifier }; if (recipient.type === recipientType.INPERSONSIGNER && (fieldName === "hostName" || fieldName === "hostEmail")) { if (!validateInPersonSignerFields(recipient, { [fieldName]: value })) { return; } } dispatch(updateRecipient(updatedRecipient)); setLocalChanges((prev) => ({ ...prev, [`${identifier}_${fieldName}`]: undefined, })); setEditingField(null); setErrors((prev) => ({ ...prev, [identifier]: { hostName: false, hostEmail: false } })); }; const handleFieldChange = (recipient: any, fieldName: string, value: any) => { const identifier = getRecipientIdentifier(recipient); setLocalChanges((prev) => ({ ...prev, [`${identifier}_${fieldName}`]: value, })); }; const getCurrentValue = (recipient: any, fieldName: string) => { const identifier = getRecipientIdentifier(recipient); const localValue = localChanges[`${identifier}_${fieldName}`]; return localValue !== undefined ? localValue : recipient[fieldName]; }; const hasValue = (recipient: any, fieldName: string) => { const currentValue = getCurrentValue(recipient, fieldName); return currentValue && currentValue.toString().trim() !== ""; }; const renderEditableField = ( recipient: any, fieldName: string, placeholder: string, className = "", type = "text" ) => { const identifier = getRecipientIdentifier(recipient); const currentValue = getCurrentValue(recipient, fieldName); const isEditing = editingField?.recipientId === identifier && editingField?.fieldName === fieldName; const showValue = hasValue(recipient, fieldName); const error = errors[identifier]?.[fieldName]; const editable = isEditable(recipient); if (isEditing && editable) { return (
handleFieldFocus(identifier, fieldName)} onBlur={(e) => handleFieldBlur(recipient, fieldName, e.target.value)} onChange={(e) => handleFieldChange(recipient, fieldName, e.target.value)} onKeyPress={(e) => { if (e.key === "Enter") { e.currentTarget.blur(); } }} className={`w-full px-3 py-1 border ${error ? "border-red-500 placeholder-red-500 text-xs" : "border-gray-300" } rounded-lg text-sm focus:outline-none focus:ring-0 focus:ring-gray-300 ${className}`} /> {/* {error && ( {`${placeholder} is required`} )} */}
); } return ( handleFieldFocus(identifier, fieldName) : undefined} className={`${editable ? "cursor-pointer hover:bg-gray-100 rounded px-1 transition-colors" : "cursor-not-allowed" } ${showValue ? "text-gray-800" : "text-gray-400 italic"} ${className}`} title={editable ? "Click to edit" : "Editing disabled"} > {showValue ? currentValue : placeholder} ); }; const handleOrderChange = (id: string, value: number) => { dispatch(updateRecipientOrder({ id, routingOrder: value })); }; const handleEditRecipient = (recipient: any) => { setEditCase("Edit"); setEditRecipient(recipient); setEditRecipientCurrentEmail(recipient.id || recipient.uuid); }; const handleRemoveRecipient = (recipient: any) => { if (!accountId || !transactionId) return; if (recipient.uuid) { dispatch(removeSelectedRecipient(recipient)); } else { dispatch( removeRecipientAsync({ recipientId: recipient.id, email: recipient.email, accountId: accountId, transactionId: transactionId, }) ); } if (recipients.length === 2) { const leftRecipient = recipients.filter((obj) => { if ("id" in obj && "id" in recipient) { return obj.id !== recipient.id; } if ("email" in obj && "email" in recipient) { return obj.email !== recipient.email; } return false; }); dispatch( updateRecipientOrder({ id: leftRecipient[0].id || leftRecipient[0].email, routingOrder: 1 }) ); } }; const handleTypeChange = (recipient: any, type: string) => { const identifier = getRecipientIdentifier(recipient); const updatedRecipient = { ...recipient, type, uuid: identifier }; if (type === recipientType.SIGNER || type === recipientType.CC) { updatedRecipient.hostName = ""; updatedRecipient.hostEmail = ""; setErrors((prev) => ({ ...prev, [identifier]: { hostName: false, hostEmail: false } })); } else if (type === recipientType.INPERSONSIGNER) { if (!validateInPersonSignerFields(recipient, updatedRecipient)) { return; } } dispatch(updateRecipient(updatedRecipient)); setEditingField(null); }; return (
{recipients.length > 0 ? ( <> {recipients.length > 1 && (

Recipients ({recipients.length})

)}
{recipients.map((recipient, idx) => (
{recipients.length > 1 ? (
handleOrderChange( recipient.id || recipient.email, Number(e.target.value) ) } 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" />
) : ( 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)]" /> )}
{getInitials(`${recipient.firstName} ${recipient.lastName || ""}`)}

{renderEditableField(recipient, "firstName", "First Name")} {renderEditableField(recipient, "lastName", "Last Name")} {transactionTemplateToggle === TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES && ( | Permissions granted : dispatch( updateRecipient({ ...recipient, allowSenderToEdit: !recipient.allowSenderToEdit, uuid: getRecipientIdentifier(recipient), }) ) } /> dispatch( updateRecipient({ ...recipient, allowSenderToDelete: !recipient.allowSenderToDelete, uuid: getRecipientIdentifier(recipient), }) ) } /> )}

{renderEditableField(recipient, "email", "Recipient Email", "", "email")} | handleFieldFocus(getRecipientIdentifier(recipient), "type") : undefined } className={`${isEditable(recipient) ? "cursor-pointer hover:bg-gray-100" : "cursor-not-allowed" } rounded px-1 transition-colors`} > {recipient.type} {(hasValue(recipient, "roleName") || transactionTemplateToggle === TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES) && ( {" | Role: "} {renderEditableField(recipient, "roleName", "Role name")} )} {recipient.type === recipientType.INPERSONSIGNER && ( <> {" | Host Name: "} {renderEditableField(recipient, "hostName", "Host Name")} {" | Host Email: "} {renderEditableField(recipient, "hostEmail", "Host Email", "", "email")} )}

{editingField?.recipientId === getRecipientIdentifier(recipient) && editingField?.fieldName === "type" && isEditable(recipient) && (
)}
{signType !== "self-sign" && (
)}
))}
) : (
No Recipients Added
)} {signingOrderModal.open && (

Signing Order

setSigningOrderModal({ ...signingOrderModal, open: false })} className="text-xl cursor-pointer hover:text-gray-200 transition-all" >
)}
); }; export default RecipientCards;