diff --git a/packages/lib/server-only/recipient/set-template-recipients.ts b/packages/lib/server-only/recipient/set-template-recipients.ts index d4bb8cb8e..4a6bd45c8 100644 --- a/packages/lib/server-only/recipient/set-template-recipients.ts +++ b/packages/lib/server-only/recipient/set-template-recipients.ts @@ -101,13 +101,15 @@ export const setTemplateRecipients = async ({ }, }); - const removedRecipients = existingRecipients.filter( - (existingRecipient) => - !normalizedRecipients.find( - (recipient) => - recipient.id === existingRecipient.id || recipient.email === existingRecipient.email, - ), - ); + const removedRecipients = existingRecipients.filter((existingRecipient) => { + // Keep direct template recipients from being removed + if (template.directLink?.directTemplateRecipientId === existingRecipient.id) { + return false; + } + + // Check if this recipient still exists in the normalized recipients + return !normalizedRecipients.some((recipient) => recipient.id === existingRecipient.id); + }); if (template.directLink !== null) { const updatedDirectRecipient = recipients.find( @@ -132,15 +134,24 @@ export const setTemplateRecipients = async ({ } const linkedRecipients = normalizedRecipients.map((recipient) => { - const existing = existingRecipients.find( - (existingRecipient) => - existingRecipient.id === recipient.id || existingRecipient.email === recipient.email, - ); + // For direct template recipients, match by ID only + if (template.directLink?.directTemplateRecipientId === recipient.id) { + const existing = existingRecipients.find( + (existingRecipient) => existingRecipient.id === recipient.id, + ); + return { ...recipient, _persisted: existing }; + } - return { - ...recipient, - _persisted: existing, - }; + // For other recipients, match by ID if it exists + if (recipient.id) { + const existing = existingRecipients.find( + (existingRecipient) => existingRecipient.id === recipient.id, + ); + return { ...recipient, _persisted: existing }; + } + + // For new recipients, create a new entry + return { ...recipient, _persisted: undefined }; }); const persistedRecipients = await prisma.$transaction(async (tx) => { diff --git a/packages/ui/primitives/template-flow/add-template-fields.tsx b/packages/ui/primitives/template-flow/add-template-fields.tsx index a01570eaf..71d868d0b 100644 --- a/packages/ui/primitives/template-flow/add-template-fields.tsx +++ b/packages/ui/primitives/template-flow/add-template-fields.tsx @@ -204,6 +204,7 @@ export const AddTemplateFieldsFormPartial = ({ event.preventDefault(); const copiedField = structuredClone(fieldClipboard); + const signerIndex = recipients.findIndex((r) => r.id === selectedSigner?.id); append({ ...copiedField, @@ -212,12 +213,20 @@ export const AddTemplateFieldsFormPartial = ({ signerId: selectedSigner?.id ?? copiedField.signerId, recipientId: selectedSigner?.id || copiedField.recipientId || copiedField.signerId || 0, signerToken: selectedSigner?.token ?? copiedField.signerToken, + signerIndex: signerIndex >= 0 ? signerIndex : 0, pageX: copiedField.pageX + 3, pageY: copiedField.pageY + 3, }); } }, - [append, fieldClipboard, selectedSigner?.email, selectedSigner?.id, selectedSigner?.token], + [ + append, + fieldClipboard, + selectedSigner?.email, + selectedSigner?.id, + selectedSigner?.token, + recipients, + ], ); useHotkeys(['ctrl+c', 'meta+c'], (evt) => onFieldCopy(evt)); @@ -323,6 +332,8 @@ export const AddTemplateFieldsFormPartial = ({ pageX -= fieldPageWidth / 2; pageY -= fieldPageHeight / 2; + const signerIndex = recipients.findIndex((r) => r.id === selectedSigner.id); + append({ formId: nanoid(12), type: selectedField, @@ -336,13 +347,14 @@ export const AddTemplateFieldsFormPartial = ({ recipientId: selectedSigner.id || lastActiveField?.recipientId || lastActiveField?.signerId || 0, signerToken: selectedSigner.token ?? '', + signerIndex: signerIndex >= 0 ? signerIndex : 0, fieldMeta: undefined, }); setIsFieldWithinBounds(false); setSelectedField(null); }, - [append, isWithinPageBounds, selectedField, selectedSigner, getPage], + [append, isWithinPageBounds, selectedField, selectedSigner, getPage, recipients], ); const onFieldResize = useCallback( @@ -552,14 +564,15 @@ export const AddTemplateFieldsFormPartial = ({ )} {localFields.map((field, index) => { - const recipientIndex = recipients.findIndex((r) => r.email === field.signerEmail); + const recipientIndex = + field.signerIndex ?? recipients.findIndex((r) => r.id === field.signerId); return ( = 0 ? recipientIndex : 0} field={field} - disabled={selectedSigner?.email !== field.signerEmail} + disabled={selectedSigner?.id !== field.signerId} minHeight={MIN_HEIGHT_PX} minWidth={MIN_WIDTH_PX} defaultHeight={DEFAULT_HEIGHT_PX} diff --git a/packages/ui/primitives/template-flow/add-template-fields.types.ts b/packages/ui/primitives/template-flow/add-template-fields.types.ts index 7898fe731..f744457bc 100644 --- a/packages/ui/primitives/template-flow/add-template-fields.types.ts +++ b/packages/ui/primitives/template-flow/add-template-fields.types.ts @@ -18,6 +18,7 @@ export const ZAddTemplateFieldsFormSchema = z.object({ pageY: z.number().min(0), pageWidth: z.number().min(0), pageHeight: z.number().min(0), + signerIndex: z.number().min(0), fieldMeta: ZFieldMetaSchema, }), ), diff --git a/packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx b/packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx index 7312bf6ee..a99e4564d 100644 --- a/packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx +++ b/packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx @@ -92,6 +92,7 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({ actionAuth: undefined, ...generateRecipientPlaceholder(1), signingOrder: 1, + signerIndex: 0, }, ]; } @@ -104,6 +105,7 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({ role: recipient.role, actionAuth: ZRecipientAuthOptionsSchema.parse(recipient.authOptions)?.actionAuth ?? undefined, signingOrder: recipient.signingOrder ?? index + 1, + signerIndex: index, })); if (signingOrder === DocumentSigningOrder.SEQUENTIAL) { @@ -174,21 +176,35 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({ }); const onAddPlaceholderSelfRecipient = () => { + const currentSigners = form.getValues('signers'); + const nextSignerIndex = currentSigners.length; + appendSigner({ formId: nanoid(12), name: user?.name ?? '', email: user?.email ?? '', role: RecipientRole.SIGNER, - signingOrder: signers.length > 0 ? (signers[signers.length - 1]?.signingOrder ?? 0) + 1 : 1, + signingOrder: + currentSigners.length > 0 + ? (currentSigners[currentSigners.length - 1]?.signingOrder ?? 0) + 1 + : 1, + signerIndex: nextSignerIndex, }); }; const onAddPlaceholderRecipient = () => { + const currentSigners = form.getValues('signers'); + const nextSignerIndex = currentSigners.length; + appendSigner({ formId: nanoid(12), role: RecipientRole.SIGNER, ...generateRecipientPlaceholder(placeholderRecipientCount), - signingOrder: signers.length > 0 ? (signers[signers.length - 1]?.signingOrder ?? 0) + 1 : 1, + signingOrder: + currentSigners.length > 0 + ? (currentSigners[currentSigners.length - 1]?.signingOrder ?? 0) + 1 + : 1, + signerIndex: nextSignerIndex, }); setPlaceholderRecipientCount((count) => count + 1); diff --git a/packages/ui/primitives/template-flow/add-template-placeholder-recipients.types.ts b/packages/ui/primitives/template-flow/add-template-placeholder-recipients.types.ts index a0e665092..22692aba2 100644 --- a/packages/ui/primitives/template-flow/add-template-placeholder-recipients.types.ts +++ b/packages/ui/primitives/template-flow/add-template-placeholder-recipients.types.ts @@ -14,6 +14,7 @@ export const ZAddTemplatePlacholderRecipientsFormSchema = z.object({ name: z.string(), role: z.nativeEnum(RecipientRole), signingOrder: z.number().optional(), + signerIndex: z.number().min(0), actionAuth: ZMapNegativeOneToUndefinedSchema.pipe(ZRecipientActionAuthTypesSchema.optional()), }), ),