SME-Web/src/components/process/processStepOne/RecipientCards.tsx

256 lines
13 KiB
TypeScript

import { useDispatch, useSelector } from "react-redux";
import {
removeRecipientAsync,
removeSelectedRecipient,
// setSigningOrder,
updateRecipientOrder,
} 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";
import { RiPencilFill } from "react-icons/ri";
const getInitials = (name: string) => {
if (!name) return "";
return name
.split(" ")
.map((n) => n[0])
.join("")
.toUpperCase();
};
type CardsData = {
editRecipient: any;
setEditRecipient: (recipient: any) => void; // Replace `any` with the actual type if known
setEditCase: (string: any) => void;
transactionTemplateToggle: string
};
const RecipientCards = ({ editRecipient, 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;
// dispatch(removeSelectedRecipient(recipient))
// dispatch(removeRecipientAsync([{
// recipientId: recipient.id,
// email: recipient.email,
// accountId: accountId,
// transactionId: transactionId,
// }]))
// =======
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) => {
// if(recipient.id === editRecipient.id) return
return (
<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 ? <div className="relative">
<input
type="number"
value={recipient.routingOrder || 1}
min={1}
onChange={(e) =>
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"
/>
{/* <RiPencilFill className="absolute top-1.5 right-0 text-[14px] text-gray-500" /> */}
</div>
: <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="p-2 rounded-t-lg text-white flex justify-between items-center bg-[var(--primary)]">
<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;