239 lines
12 KiB
TypeScript
239 lines
12 KiB
TypeScript
import { useDispatch, useSelector } from "react-redux";
|
|
import {
|
|
removeRecipientAsync,
|
|
removeSelectedRecipient,
|
|
// setSigningOrder,
|
|
updateRecipientOrder, // 👈 You need to define this in your slice
|
|
} from "../../../store/slices/selectedRecipientsSlice";
|
|
import { AppDispatch, RootState } from "../../../store/store";
|
|
|
|
import { ImBin } from "react-icons/im";
|
|
import { FaUsersLine } from "react-icons/fa6";
|
|
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";
|
|
|
|
const getInitials = (name: string) => {
|
|
if (!name) return "";
|
|
return name
|
|
.split(" ")
|
|
.map((n) => n[0])
|
|
.join("")
|
|
.toUpperCase();
|
|
};
|
|
|
|
type CardsData = {
|
|
setEditRecipient: (recipient: any) => void; // Replace `any` with the actual type if known
|
|
setEditCase: (string: any) => void;
|
|
transactionTemplateToggle: string
|
|
};
|
|
|
|
const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateToggle }: 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);
|
|
console.log("recipients.length", recipients)
|
|
// const signingOrder = useSelector((state: RootState) => state.selectedRecipients.signingOrder);
|
|
const signType = useSelector((state: RootState) => state.selectedDocuments.signType);
|
|
|
|
const [signingOrderModal, setSigningOrderModal] = useState({ open: false });
|
|
|
|
const handleOrderChange = (id: string, value: number) => {
|
|
dispatch(updateRecipientOrder({ id, routingOrder: value }));
|
|
};
|
|
|
|
const handleEditRecipient = (recipient) => {
|
|
// alert(JSON.stringify(recipient))
|
|
setEditCase('Edit')
|
|
setEditRecipient(recipient)
|
|
}
|
|
|
|
const handleRemoveRecipient = (recipient) => {
|
|
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) {
|
|
let leftRecipient = recipients.filter((obj) => {
|
|
if ("id" in obj && "id" in recipient) {
|
|
if (obj.id !== recipient.id) return true
|
|
}
|
|
if ("email" in obj && "email" in recipient) {
|
|
if (obj.email !== recipient.email) return true
|
|
}
|
|
return false
|
|
})
|
|
dispatch(updateRecipientOrder({ id: leftRecipient[0].id || leftRecipient[0].email, routingOrder: 1 }));
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="w-full bg-white rounded-md shadow-sm border border-gray-200">
|
|
{recipients.length > 0 ? (
|
|
<>
|
|
{recipients.length > 1 && (
|
|
<div className="flex items-center justify-between px-4 py-2 border-b border-gray-300">
|
|
<h3 className="text-sm font-semibold text-gray-700">
|
|
Recipients ({recipients.length})
|
|
</h3>
|
|
{/* <label className="flex items-center cursor-pointer select-none">
|
|
<span className="mr-2 text-xs font-medium text-gray-600">Signing Order</span>
|
|
<input
|
|
type="checkbox"
|
|
checked={signingOrder}
|
|
onChange={() => dispatch(setSigningOrder(!signingOrder))}
|
|
className="sr-only peer"
|
|
/>
|
|
<div className="w-9 h-5 bg-gray-300 rounded-full peer-checked:bg-[var(--primary)] relative transition-colors duration-300">
|
|
<span
|
|
className={`absolute left-1 top-1/2 w-3.5 h-3.5 bg-white rounded-full shadow transform transition-transform duration-300 -translate-y-1/2 ${signingOrder ? "translate-x-4" : "translate-x-0"
|
|
}`}
|
|
/>
|
|
</div>
|
|
</label> */}
|
|
|
|
<label className="flex items-center gap-2 cursor-pointer select-none"
|
|
onClick={() => setSigningOrderModal({ ...signingOrderModal, open: true })}
|
|
>
|
|
<span className="text-xs font-medium text-gray-600">Signing Order</span>
|
|
<FaUsersLine className="text-[var(--primary)] mt-0.5 text-lg" />
|
|
</label>
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex flex-col divide-y divide-gray-200">
|
|
{recipients.map((recipient, idx) => (
|
|
<div
|
|
key={recipient.email + idx}
|
|
className="flex items-center justify-between px-4 py-3 hover:bg-gray-50 transition-colors"
|
|
>
|
|
<div className="flex items-center gap-3 min-w-0">
|
|
{/* {signingOrder && ( */}
|
|
{recipients.length > 1 ? <input
|
|
type="number"
|
|
value={recipient.routingOrder || 1}
|
|
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)]"
|
|
/> : <input
|
|
type="number"
|
|
disabled
|
|
value={recipient.routingOrder || 1}
|
|
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">
|
|
{getInitials(`${recipient.firstName} ${recipient.lastName || ""}`)}
|
|
</div>
|
|
|
|
<div className="min-w-0">
|
|
<p className="font-semibold text-gray-800 truncate text-sm">
|
|
{recipient.firstName} {recipient.lastName || ""}
|
|
</p>
|
|
<p className="text-xs text-gray-500 truncate">
|
|
{recipient.email} | {recipient.type} {recipient.roleName ? `| Role : ${recipient.roleName}` : ""}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{signType !== "self-sign" && (
|
|
<div className="flex justify-between gap-2 items-center">
|
|
{/* Edit Button */}
|
|
<button
|
|
type="button"
|
|
title="Edit recipient"
|
|
aria-label={`Edit recipient ${recipient.firstName}`}
|
|
onClick={() => handleEditRecipient(recipient)}
|
|
disabled={
|
|
// For templates: always enabled (never disabled)
|
|
['templates'].includes(transactionTemplateToggle)
|
|
? false
|
|
: // For transactions: disabled if not newOne AND not allowed to edit
|
|
(!recipient.newOne && !recipient.allowSenderToEdit)
|
|
}
|
|
className="text-gray-400 hover:text-blue-600 transition-colors cursor-pointer disabled:opacity-50"
|
|
>
|
|
<FiEdit size={16} />
|
|
</button>
|
|
|
|
{/* Delete Button */}
|
|
<button
|
|
type="button"
|
|
title="Remove recipient"
|
|
aria-label={`Remove recipient ${recipient.firstName}`}
|
|
onClick={() => handleRemoveRecipient(recipient)}
|
|
disabled={
|
|
// For templates: always enabled (never disabled)
|
|
['templates'].includes(transactionTemplateToggle)
|
|
? false
|
|
: // For transactions: disabled if not newOne AND not allowed to delete
|
|
(!recipient.newOne && !recipient.allowSenderToDelete)
|
|
}
|
|
className="text-gray-400 hover:text-red-600 transition-colors cursor-pointer disabled:opacity-50"
|
|
>
|
|
<ImBin size={16} />
|
|
</button>
|
|
</div>
|
|
|
|
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</>
|
|
) : (
|
|
<div className="p-6 text-center text-gray-500 font-medium text-sm">
|
|
No Recipients Added
|
|
</div>
|
|
)}
|
|
|
|
|
|
{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="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">
|
|
<p className="font-semibold">Signing Order</p>
|
|
<div
|
|
onClick={() => setSigningOrderModal({ ...signingOrderModal, open: false })}
|
|
className="text-xl cursor-pointer hover:text-gray-200 transition-all">
|
|
<IoCloseOutline />
|
|
</div>
|
|
</div>
|
|
<SigningOrderDiagram signers={recipients} />
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default RecipientCards;
|