chore: recipient helpers

This commit is contained in:
Catalin Pit
2026-06-04 14:45:37 +03:00
parent 699d7657b4
commit 48a107685a
2 changed files with 63 additions and 9 deletions
@@ -158,11 +158,8 @@ export const EnvelopeEditorRecipientForm = () => {
return watchedSigners.some((signer) => signer.role === RecipientRole.ASSISTANT);
}, [watchedSigners]);
const normalizeSigningOrders = (signers: typeof watchedSigners, options: { preserveOrder?: boolean } = {}) => {
return normalizeRecipientSigningOrders(signers, {
...options,
canUpdateRecipient: (signer) => canRecipientBeModified(signer.id),
});
const normalizeSigningOrders = (signers: typeof watchedSigners) => {
return normalizeRecipientSigningOrders(signers, (signer) => canRecipientBeModified(signer.id));
};
const activeRecipientCount = watchedSigners.filter((signer) => !isCcRecipient(signer)).length;
@@ -393,7 +390,7 @@ export const EnvelopeEditorRecipientForm = () => {
items.splice(insertIndex, 0, reorderedSigner);
const updatedSigners = normalizeSigningOrders(items, { preserveOrder: true });
const updatedSigners = normalizeSigningOrders(items);
form.setValue('signers', updatedSigners, {
shouldValidate: true,
@@ -484,9 +481,7 @@ export const EnvelopeEditorRecipientForm = () => {
const newPosition = Math.min(Math.max(0, newOrder - 1), signersWithSigningOrder.length);
signersWithSigningOrder.splice(newPosition, 0, reorderedSigner);
const updatedSigners = normalizeSigningOrders([...signersWithSigningOrder, ...signersWithoutSigningOrder], {
preserveOrder: true,
});
const updatedSigners = normalizeSigningOrders([...signersWithSigningOrder, ...signersWithoutSigningOrder]);
form.setValue('signers', updatedSigners, {
shouldValidate: true,
+59
View File
@@ -8,6 +8,15 @@ import type { TRecipientLite } from '../types/recipient';
import { extractLegacyIds } from '../universal/id';
import { zEmail } from './zod';
type RecipientWithSigningOrder = {
role: RecipientRole;
signingOrder?: number | null;
};
type CanUpdateRecipient<T extends RecipientWithSigningOrder> = (recipient: T) => boolean;
const canUpdateAnyRecipient = () => true;
/**
* Roles that require fields to be assigned before a document can be distributed.
*
@@ -15,6 +24,56 @@ import { zEmail } from './zod';
*/
export const RECIPIENT_ROLES_THAT_REQUIRE_FIELDS = [RecipientRole.SIGNER] as const;
export const isCcRecipient = (recipient: Pick<RecipientWithSigningOrder, 'role'>) => {
return recipient.role === RecipientRole.CC;
};
export const getRecipientSigningOrder = (recipient: Pick<RecipientWithSigningOrder, 'role' | 'signingOrder'>) => {
if (isCcRecipient(recipient)) {
return null;
}
return recipient.signingOrder ?? null;
};
export const sortRecipientsForSigningOrder = <T extends RecipientWithSigningOrder>(recipients: T[]): T[] => {
return [...recipients].sort((r1, r2) => {
const r1IsCcRecipient = isCcRecipient(r1);
const r2IsCcRecipient = isCcRecipient(r2);
// CC recipients always sort after non-CC recipients.
if (r1IsCcRecipient !== r2IsCcRecipient) {
return r1IsCcRecipient ? 1 : -1;
}
// Order by signing order; missing orders sort last.
const r1SigningOrder = r1.signingOrder ?? Number.MAX_SAFE_INTEGER;
const r2SigningOrder = r2.signingOrder ?? Number.MAX_SAFE_INTEGER;
return r1SigningOrder - r2SigningOrder;
});
};
export const normalizeRecipientSigningOrders = <T extends RecipientWithSigningOrder>(
recipients: T[],
canUpdateRecipient: CanUpdateRecipient<T> = canUpdateAnyRecipient,
): Array<T & { signingOrder?: number }> => {
const recipientsWithSigningOrder = recipients.filter((recipient) => !isCcRecipient(recipient));
const ccRecipients = recipients.filter((recipient) => isCcRecipient(recipient));
const normalizedRecipients = recipientsWithSigningOrder.map((recipient, index) => ({
...recipient,
signingOrder: canUpdateRecipient(recipient) ? index + 1 : (recipient.signingOrder ?? index + 1),
}));
const normalizedCcRecipients = ccRecipients.map((recipient) => ({
...recipient,
signingOrder: undefined,
}));
return [...normalizedRecipients, ...normalizedCcRecipients];
};
/**
* Returns recipients who are missing required fields for their role.
*