Compare commits

..

2 Commits

Author SHA1 Message Date
Mythie
0eff336175 v1.8.0-rc.4 2024-11-19 16:44:25 +11:00
Ephraim Duncan
9bdd5c31cc fix: sort recipients for template with signing order (#1468) 2024-11-18 15:54:51 +07:00
18 changed files with 121 additions and 107 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@documenso/marketing",
"version": "1.8.0-rc.3",
"version": "1.8.0-rc.4",
"private": true,
"license": "AGPL-3.0",
"scripts": {

View File

@@ -1,6 +1,6 @@
{
"name": "@documenso/web",
"version": "1.8.0-rc.3",
"version": "1.8.0-rc.4",
"private": true,
"license": "AGPL-3.0",
"scripts": {

View File

@@ -99,9 +99,7 @@ export const DocumentLogsDataTable = ({ documentId }: DocumentLogsDataTableProps
{
header: _(msg`Action`),
accessorKey: 'type',
cell: ({ row }) => (
<span>{uppercaseFistLetter(formatDocumentAuditLogAction(row.original).description)}</span>
),
cell: ({ row }) => <span>{formatDocumentAuditLogAction(_, row.original).description}</span>,
},
{
header: 'IP Address',

View File

@@ -193,6 +193,7 @@ export const SignDirectTemplateForm = ({
field={field}
recipient={directRecipient}
onSignField={onSignField}
onUnsignField={onUnsignField}
/>
))
.with(FieldType.NAME, () => (
@@ -201,6 +202,7 @@ export const SignDirectTemplateForm = ({
field={field}
recipient={directRecipient}
onSignField={onSignField}
onUnsignField={onUnsignField}
/>
))
.with(FieldType.DATE, () => (
@@ -211,6 +213,7 @@ export const SignDirectTemplateForm = ({
dateFormat={template.templateMeta?.dateFormat ?? DEFAULT_DOCUMENT_DATE_FORMAT}
timezone={template.templateMeta?.timezone ?? DEFAULT_DOCUMENT_TIME_ZONE}
onSignField={onSignField}
onUnsignField={onUnsignField}
/>
))
.with(FieldType.EMAIL, () => (
@@ -219,6 +222,7 @@ export const SignDirectTemplateForm = ({
field={field}
recipient={directRecipient}
onSignField={onSignField}
onUnsignField={onUnsignField}
/>
))
.with(FieldType.TEXT, () => {

View File

@@ -1,6 +1,6 @@
'use client';
import { useEffect, useTransition } from 'react';
import { useTransition } from 'react';
import { useRouter } from 'next/navigation';
@@ -25,7 +25,6 @@ import type {
} from '@documenso/trpc/server/field-router/schema';
import { useToast } from '@documenso/ui/primitives/use-toast';
import { useRequiredDocumentAuthContext } from './document-auth-provider';
import { SigningFieldContainer } from './signing-field-container';
export type DateFieldProps = {
@@ -43,6 +42,7 @@ export const DateField = ({
dateFormat = DEFAULT_DOCUMENT_DATE_FORMAT,
timezone = DEFAULT_DOCUMENT_TIME_ZONE,
onSignField,
onUnsignField,
}: DateFieldProps) => {
const router = useRouter();
@@ -54,13 +54,13 @@ export const DateField = ({
const { mutateAsync: signFieldWithToken, isLoading: isSignFieldWithTokenLoading } =
trpc.field.signFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION);
const { isLoading: isRemoveSignedFieldWithTokenLoading } =
trpc.field.removeSignedFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION);
const {
mutateAsync: removeSignedFieldWithToken,
isLoading: isRemoveSignedFieldWithTokenLoading,
} = trpc.field.removeSignedFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION);
const isLoading = isSignFieldWithTokenLoading || isRemoveSignedFieldWithTokenLoading || isPending;
const { executeActionAuthProcedure } = useRequiredDocumentAuthContext();
const localDateString = convertToLocalSystemFormat(field.customText, dateFormat, timezone);
const isDifferentTime = field.inserted && localDateString !== field.customText;
@@ -103,18 +103,37 @@ export const DateField = ({
}
};
useEffect(() => {
if (!field.inserted) {
void executeActionAuthProcedure({
onReauthFormSubmit: async (authOptions) => await onSign(authOptions),
actionTarget: field.type,
const onRemove = async () => {
try {
const payload: TRemovedSignedFieldWithTokenMutationSchema = {
token: recipient.token,
fieldId: field.id,
};
if (onUnsignField) {
await onUnsignField(payload);
return;
}
await removeSignedFieldWithToken(payload);
startTransition(() => router.refresh());
} catch (err) {
console.error(err);
toast({
title: _(msg`Error`),
description: _(msg`An error occurred while removing the signature.`),
variant: 'destructive',
});
}
}, [field]);
};
return (
<SigningFieldContainer
field={field}
onSign={onSign}
onRemove={onRemove}
type="Date"
tooltipText={isDifferentTime ? tooltipText : undefined}
>

View File

@@ -1,6 +1,6 @@
'use client';
import { useEffect, useTransition } from 'react';
import { useTransition } from 'react';
import { useRouter } from 'next/navigation';
@@ -14,10 +14,12 @@ import type { TRecipientActionAuth } from '@documenso/lib/types/document-auth';
import type { Recipient } from '@documenso/prisma/client';
import type { FieldWithSignature } from '@documenso/prisma/types/field-with-signature';
import { trpc } from '@documenso/trpc/react';
import type { TSignFieldWithTokenMutationSchema } from '@documenso/trpc/server/field-router/schema';
import type {
TRemovedSignedFieldWithTokenMutationSchema,
TSignFieldWithTokenMutationSchema,
} from '@documenso/trpc/server/field-router/schema';
import { useToast } from '@documenso/ui/primitives/use-toast';
import { useRequiredDocumentAuthContext } from './document-auth-provider';
import { useRequiredSigningContext } from './provider';
import { SigningFieldContainer } from './signing-field-container';
@@ -25,9 +27,10 @@ export type EmailFieldProps = {
field: FieldWithSignature;
recipient: Recipient;
onSignField?: (value: TSignFieldWithTokenMutationSchema) => Promise<void> | void;
onUnsignField?: (value: TRemovedSignedFieldWithTokenMutationSchema) => Promise<void> | void;
};
export const EmailField = ({ field, recipient, onSignField }: EmailFieldProps) => {
export const EmailField = ({ field, recipient, onSignField, onUnsignField }: EmailFieldProps) => {
const router = useRouter();
const { _ } = useLingui();
@@ -40,13 +43,13 @@ export const EmailField = ({ field, recipient, onSignField }: EmailFieldProps) =
const { mutateAsync: signFieldWithToken, isLoading: isSignFieldWithTokenLoading } =
trpc.field.signFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION);
const { isLoading: isRemoveSignedFieldWithTokenLoading } =
trpc.field.removeSignedFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION);
const {
mutateAsync: removeSignedFieldWithToken,
isLoading: isRemoveSignedFieldWithTokenLoading,
} = trpc.field.removeSignedFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION);
const isLoading = isSignFieldWithTokenLoading || isRemoveSignedFieldWithTokenLoading || isPending;
const { executeActionAuthProcedure } = useRequiredDocumentAuthContext();
const onSign = async (authOptions?: TRecipientActionAuth) => {
try {
const value = providedEmail ?? '';
@@ -84,17 +87,34 @@ export const EmailField = ({ field, recipient, onSignField }: EmailFieldProps) =
}
};
useEffect(() => {
if (!field.inserted) {
void executeActionAuthProcedure({
onReauthFormSubmit: async (authOptions) => await onSign(authOptions),
actionTarget: field.type,
const onRemove = async () => {
try {
const payload: TRemovedSignedFieldWithTokenMutationSchema = {
token: recipient.token,
fieldId: field.id,
};
if (onUnsignField) {
await onUnsignField(payload);
return;
}
await removeSignedFieldWithToken(payload);
startTransition(() => router.refresh());
} catch (err) {
console.error(err);
toast({
title: _(msg`Error`),
description: _(msg`An error occurred while removing the signature.`),
variant: 'destructive',
});
}
}, [field]);
};
return (
<SigningFieldContainer field={field} type="Email">
<SigningFieldContainer field={field} onSign={onSign} onRemove={onRemove} type="Email">
{isLoading && (
<div className="bg-background absolute inset-0 flex items-center justify-center rounded-md">
<Loader className="text-primary h-5 w-5 animate-spin md:h-8 md:w-8" />

View File

@@ -1,6 +1,6 @@
'use client';
import { useEffect, useTransition } from 'react';
import { useTransition } from 'react';
import { useRouter } from 'next/navigation';
@@ -8,7 +8,6 @@ import { Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { Loader } from 'lucide-react';
import { useDebouncedValue } from '@documenso/lib/client-only/hooks/use-debounced-value';
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import type { TRecipientActionAuth } from '@documenso/lib/types/document-auth';
@@ -22,7 +21,6 @@ import type {
} from '@documenso/trpc/server/field-router/schema';
import { useToast } from '@documenso/ui/primitives/use-toast';
import { useRequiredDocumentAuthContext } from './document-auth-provider';
import { useRequiredSigningContext } from './provider';
import { SigningFieldContainer } from './signing-field-container';
@@ -46,12 +44,8 @@ export const InitialsField = ({
const { fullName } = useRequiredSigningContext();
const initials = extractInitials(fullName);
const debouncedInitials = useDebouncedValue(initials, 2000);
const [isPending, startTransition] = useTransition();
const { executeActionAuthProcedure } = useRequiredDocumentAuthContext();
const { mutateAsync: signFieldWithToken, isLoading: isSignFieldWithTokenLoading } =
trpc.field.signFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION);
@@ -64,7 +58,7 @@ export const InitialsField = ({
const onSign = async (authOptions?: TRecipientActionAuth) => {
try {
const value = debouncedInitials ?? '';
const value = initials ?? '';
const payload: TSignFieldWithTokenMutationSchema = {
token: recipient.token,
@@ -125,15 +119,6 @@ export const InitialsField = ({
}
};
useEffect(() => {
if (!field.inserted && debouncedInitials) {
void executeActionAuthProcedure({
onReauthFormSubmit: async (authOptions) => await onSign(authOptions),
actionTarget: field.type,
});
}
}, [field, debouncedInitials, field.inserted]);
return (
<SigningFieldContainer field={field} onSign={onSign} onRemove={onRemove} type="Initials">
{isLoading && (

View File

@@ -1,6 +1,6 @@
'use client';
import { useEffect, useState, useTransition } from 'react';
import { useState, useTransition } from 'react';
import { useRouter } from 'next/navigation';
@@ -8,7 +8,6 @@ import { Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { Loader } from 'lucide-react';
import { useDebouncedValue } from '@documenso/lib/client-only/hooks/use-debounced-value';
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import type { TRecipientActionAuth } from '@documenso/lib/types/document-auth';
@@ -45,8 +44,6 @@ export const NameField = ({ field, recipient, onSignField, onUnsignField }: Name
const { fullName: providedFullName, setFullName: setProvidedFullName } =
useRequiredSigningContext();
const debouncedProvidedFullName = useDebouncedValue(providedFullName, 2000);
const { executeActionAuthProcedure } = useRequiredDocumentAuthContext();
const [isPending, startTransition] = useTransition();
@@ -154,15 +151,6 @@ export const NameField = ({ field, recipient, onSignField, onUnsignField }: Name
}
};
useEffect(() => {
if (!field.inserted && providedFullName) {
void executeActionAuthProcedure({
onReauthFormSubmit: async (authOptions) => await onSign(authOptions),
actionTarget: field.type,
});
}
}, [field, debouncedProvidedFullName]);
return (
<SigningFieldContainer
field={field}

View File

@@ -68,8 +68,6 @@ export const SigningFieldContainer = ({
const parsedFieldMeta = field.fieldMeta ? ZFieldMetaSchema.parse(field.fieldMeta) : undefined;
const readOnlyField = parsedFieldMeta?.readOnly || false;
const automatedFields = ['Email', 'Date'].includes(type ?? '');
const handleInsertField = async () => {
if (field.inserted || !onSign) {
return;
@@ -148,7 +146,7 @@ export const SigningFieldContainer = ({
</button>
)}
{field.inserted && !automatedFields && !loading && !readOnlyField && (
{type === 'Date' && field.inserted && !loading && !readOnlyField && (
<Tooltip delayDuration={0}>
<TooltipTrigger asChild>
<button
@@ -174,16 +172,12 @@ export const SigningFieldContainer = ({
</button>
)}
{type !== 'Checkbox' &&
!automatedFields &&
field.inserted &&
!loading &&
!readOnlyField && (
{type !== 'Date' && type !== 'Checkbox' && field.inserted && !loading && !readOnlyField && (
<button
className="text-destructive bg-background/50 absolute inset-0 z-10 flex h-full w-full items-center justify-center rounded-md text-sm opacity-0 duration-200 group-hover:opacity-100"
onClick={onRemoveSignedFieldClick}
>
Remove
<Trans>Remove</Trans>
</button>
)}

8
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@documenso/root",
"version": "1.8.0-rc.3",
"version": "1.8.0-rc.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@documenso/root",
"version": "1.8.0-rc.3",
"version": "1.8.0-rc.4",
"workspaces": [
"apps/*",
"packages/*"
@@ -80,7 +80,7 @@
},
"apps/marketing": {
"name": "@documenso/marketing",
"version": "1.8.0-rc.3",
"version": "1.8.0-rc.4",
"license": "AGPL-3.0",
"dependencies": {
"@documenso/assets": "*",
@@ -441,7 +441,7 @@
},
"apps/web": {
"name": "@documenso/web",
"version": "1.8.0-rc.3",
"version": "1.8.0-rc.4",
"license": "AGPL-3.0",
"dependencies": {
"@documenso/api": "*",

View File

@@ -1,6 +1,6 @@
{
"private": true,
"version": "1.8.0-rc.3",
"version": "1.8.0-rc.4",
"scripts": {
"build": "turbo run build",
"build:web": "turbo run build --filter=@documenso/web",

View File

@@ -5,11 +5,7 @@ import { getToken } from 'next-auth/jwt';
import { LOCAL_FEATURE_FLAGS } from '@documenso/lib/constants/feature-flags';
import PostHogServerClient from '@documenso/lib/server-only/feature-flags/get-post-hog-server-client';
import {
NEXT_PRIVATE_INTERNAL_WEBAPP_URL,
NEXT_PUBLIC_MARKETING_URL,
NEXT_PUBLIC_WEBAPP_URL,
} from '../../constants/app';
import { NEXT_PUBLIC_MARKETING_URL, NEXT_PUBLIC_WEBAPP_URL, NEXT_PRIVATE_INTERNAL_WEBAPP_URL } from '../../constants/app';
import { extractDistinctUserId, mapJwtToFlagProperties } from './get';
/**

View File

@@ -7,11 +7,7 @@ import { getToken } from 'next-auth/jwt';
import { LOCAL_FEATURE_FLAGS, extractPostHogConfig } from '@documenso/lib/constants/feature-flags';
import PostHogServerClient from '@documenso/lib/server-only/feature-flags/get-post-hog-server-client';
import {
NEXT_PRIVATE_INTERNAL_WEBAPP_URL,
NEXT_PUBLIC_MARKETING_URL,
NEXT_PUBLIC_WEBAPP_URL,
} from '../../constants/app';
import { NEXT_PUBLIC_MARKETING_URL, NEXT_PUBLIC_WEBAPP_URL, NEXT_PRIVATE_INTERNAL_WEBAPP_URL } from '../../constants/app';
/**
* Evaluate a single feature flag based on the current user if possible.

View File

@@ -518,8 +518,10 @@ msgid "An error occurred while removing the field."
msgstr "Ein Fehler ist beim Entfernen des Feldes aufgetreten."
#: apps/web/src/app/(signing)/sign/[token]/checkbox-field.tsx:152
#: apps/web/src/app/(signing)/sign/[token]/date-field.tsx:126
#: apps/web/src/app/(signing)/sign/[token]/dropdown-field.tsx:137
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:151
#: apps/web/src/app/(signing)/sign/[token]/email-field.tsx:110
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:148
#: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:195
#: apps/web/src/app/(signing)/sign/[token]/radio-field.tsx:129
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:173
@@ -715,7 +717,7 @@ msgstr "Avatar aktualisiert"
msgid "Awaiting email confirmation"
msgstr "Warte auf E-Mail-Bestätigung"
#: apps/web/src/app/(recipient)/d/[token]/sign-direct-template.tsx:365
#: apps/web/src/app/(recipient)/d/[token]/sign-direct-template.tsx:369
#: apps/web/src/components/(dashboard)/settings/layout/activity-back.tsx:20
#: apps/web/src/components/forms/v2/signup.tsx:509
msgid "Back"
@@ -1801,6 +1803,7 @@ msgstr "Geben Sie hier Ihren Text ein"
#: apps/web/src/app/(signing)/sign/[token]/checkbox-field.tsx:151
#: apps/web/src/app/(signing)/sign/[token]/checkbox-field.tsx:212
#: apps/web/src/app/(signing)/sign/[token]/date-field.tsx:99
#: apps/web/src/app/(signing)/sign/[token]/date-field.tsx:125
#: apps/web/src/app/(signing)/sign/[token]/dropdown-field.tsx:105
#: apps/web/src/app/(signing)/sign/[token]/dropdown-field.tsx:136
#: apps/web/src/app/(signing)/sign/[token]/email-field.tsx:83
@@ -2358,7 +2361,7 @@ msgstr "Meine Vorlagen"
#: apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx:287
#: apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx:294
#: apps/web/src/app/(signing)/sign/[token]/complete/claim-account.tsx:119
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:182
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:170
#: apps/web/src/components/(teams)/dialogs/add-team-email-dialog.tsx:153
#: apps/web/src/components/(teams)/dialogs/update-team-email-dialog.tsx:141
#: apps/web/src/components/forms/signup.tsx:164
@@ -2806,7 +2809,7 @@ msgstr "Öffentlicher Profil-Benutzername"
msgid "Public templates are connected to your public profile. Any modifications to public templates will also appear in your public profile."
msgstr "Öffentliche Vorlagen sind mit Ihrem öffentlichen Profil verbunden. Änderungen an öffentlichen Vorlagen erscheinen auch in Ihrem öffentlichen Profil."
#: apps/web/src/app/(signing)/sign/[token]/signing-field-container.tsx:146
#: apps/web/src/app/(signing)/sign/[token]/signing-field-container.tsx:144
msgid "Read only field"
msgstr "Nur-Lese-Feld"
@@ -3185,7 +3188,7 @@ msgstr "Unterzeichnen"
msgid "Sign as {0} <0>({1})</0>"
msgstr "Unterzeichnen als {0} <0>({1})</0>"
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:195
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:183
msgid "Sign as<0>{0} <1>({1})</1></0>"
msgstr "Unterzeichnen als<0>{0} <1>({1})</1></0>"

View File

@@ -513,8 +513,10 @@ msgid "An error occurred while removing the field."
msgstr "An error occurred while removing the field."
#: apps/web/src/app/(signing)/sign/[token]/checkbox-field.tsx:152
#: apps/web/src/app/(signing)/sign/[token]/date-field.tsx:126
#: apps/web/src/app/(signing)/sign/[token]/dropdown-field.tsx:137
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:151
#: apps/web/src/app/(signing)/sign/[token]/email-field.tsx:110
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:148
#: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:195
#: apps/web/src/app/(signing)/sign/[token]/radio-field.tsx:129
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:173
@@ -710,7 +712,7 @@ msgstr "Avatar Updated"
msgid "Awaiting email confirmation"
msgstr "Awaiting email confirmation"
#: apps/web/src/app/(recipient)/d/[token]/sign-direct-template.tsx:365
#: apps/web/src/app/(recipient)/d/[token]/sign-direct-template.tsx:369
#: apps/web/src/components/(dashboard)/settings/layout/activity-back.tsx:20
#: apps/web/src/components/forms/v2/signup.tsx:509
msgid "Back"
@@ -1796,6 +1798,7 @@ msgstr "Enter your text here"
#: apps/web/src/app/(signing)/sign/[token]/checkbox-field.tsx:151
#: apps/web/src/app/(signing)/sign/[token]/checkbox-field.tsx:212
#: apps/web/src/app/(signing)/sign/[token]/date-field.tsx:99
#: apps/web/src/app/(signing)/sign/[token]/date-field.tsx:125
#: apps/web/src/app/(signing)/sign/[token]/dropdown-field.tsx:105
#: apps/web/src/app/(signing)/sign/[token]/dropdown-field.tsx:136
#: apps/web/src/app/(signing)/sign/[token]/email-field.tsx:83
@@ -2353,7 +2356,7 @@ msgstr "My templates"
#: apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx:287
#: apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx:294
#: apps/web/src/app/(signing)/sign/[token]/complete/claim-account.tsx:119
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:182
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:170
#: apps/web/src/components/(teams)/dialogs/add-team-email-dialog.tsx:153
#: apps/web/src/components/(teams)/dialogs/update-team-email-dialog.tsx:141
#: apps/web/src/components/forms/signup.tsx:164
@@ -2801,7 +2804,7 @@ msgstr "Public profile username"
msgid "Public templates are connected to your public profile. Any modifications to public templates will also appear in your public profile."
msgstr "Public templates are connected to your public profile. Any modifications to public templates will also appear in your public profile."
#: apps/web/src/app/(signing)/sign/[token]/signing-field-container.tsx:146
#: apps/web/src/app/(signing)/sign/[token]/signing-field-container.tsx:144
msgid "Read only field"
msgstr "Read only field"

View File

@@ -1,6 +1,6 @@
'use client';
import React, { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';
import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';
import type { DropResult, SensorAPI } from '@hello-pangea/dnd';
import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd';
@@ -94,7 +94,7 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({
];
}
return recipients.map((recipient, index) => ({
let mappedRecipients = recipients.map((recipient, index) => ({
nativeId: recipient.id,
formId: String(recipient.id),
name: recipient.name,
@@ -103,6 +103,14 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({
actionAuth: ZRecipientAuthOptionsSchema.parse(recipient.authOptions)?.actionAuth ?? undefined,
signingOrder: recipient.signingOrder ?? index + 1,
}));
if (signingOrder === DocumentSigningOrder.SEQUENTIAL) {
mappedRecipients = mappedRecipients.sort(
(a, b) => (a.signingOrder ?? 0) - (b.signingOrder ?? 0),
);
}
return mappedRecipients;
};
const form = useForm<TAddTemplatePlacholderRecipientsFormSchema>({