diff --git a/apps/remix/app/components/general/envelope-editor/recipient-row.tsx b/apps/remix/app/components/general/envelope-editor/recipient-row.tsx new file mode 100644 index 000000000..338e02b35 --- /dev/null +++ b/apps/remix/app/components/general/envelope-editor/recipient-row.tsx @@ -0,0 +1,260 @@ +import type { TEditorRecipientsFormSchema } from '@documenso/lib/client-only/hooks/use-editor-recipients'; +import { useCurrentEnvelopeEditor } from '@documenso/lib/client-only/providers/envelope-editor-provider'; +import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation'; +import { isCcRecipient } from '@documenso/lib/utils/recipients'; +import { RecipientActionAuthSelect } from '@documenso/ui/components/recipient/recipient-action-auth-select'; +import { + RecipientAutoCompleteInput, + type RecipientAutoCompleteOption, +} from '@documenso/ui/components/recipient/recipient-autocomplete-input'; +import { RecipientRoleSelect } from '@documenso/ui/components/recipient/recipient-role-select'; +import { cn } from '@documenso/ui/lib/utils'; +import { Button } from '@documenso/ui/primitives/button'; +import { FormControl, FormField, FormItem, FormMessage } from '@documenso/ui/primitives/form/form'; +import { Input } from '@documenso/ui/primitives/input'; +import type { DraggableProvidedDragHandleProps } from '@hello-pangea/dnd'; +import { useLingui } from '@lingui/react/macro'; +import { EnvelopeType, type RecipientRole } from '@prisma/client'; +import { GripVerticalIcon, TrashIcon } from 'lucide-react'; +import { useFormContext } from 'react-hook-form'; + +type TEditorSigner = TEditorRecipientsFormSchema['signers'][number]; + +export type RecipientRowProps = { + signerIndex: number; + signer: TEditorSigner; + stepCount: number; + isSequential: boolean; + isGrouped: boolean; + isInputDisabled: boolean; + canBeModified: boolean; + isRemoveDisabled: boolean; + showAdvancedSettings: boolean; + dragHandleProps?: DraggableProvidedDragHandleProps | null; + recipientSuggestions: RecipientAutoCompleteOption[]; + isLoadingSuggestions: boolean; + onSigningOrderChange: (signerIndex: number, value: string) => void; + onRoleChange: (signerIndex: number, role: RecipientRole) => void; + onRemove: (signerIndex: number) => void; + onAutoCompleteSelect: (signerIndex: number, suggestion: RecipientAutoCompleteOption) => void; + onSearchQueryChange: (query: string) => void; +}; + +export const RecipientRow = ({ + signerIndex, + signer, + stepCount, + isSequential, + isGrouped, + isInputDisabled, + canBeModified, + isRemoveDisabled, + showAdvancedSettings, + dragHandleProps, + recipientSuggestions, + isLoadingSuggestions, + onSigningOrderChange, + onRoleChange, + onRemove, + onAutoCompleteSelect, + onSearchQueryChange, +}: RecipientRowProps) => { + const { t } = useLingui(); + + const { envelope, editorConfig } = useCurrentEnvelopeEditor(); + const organisation = useCurrentOrganisation(); + + const form = useFormContext(); + + const { isSubmitting } = form.formState; + + const isDirectRecipient = + envelope.type === EnvelopeType.TEMPLATE && + envelope.directLink !== null && + signer.id === envelope.directLink.directTemplateRecipientId; + + const isFieldDisabled = isInputDisabled || isSubmitting || !canBeModified; + + const rowErrors = form.formState.errors.signers?.[signerIndex]; + + return ( +
+
+ {isSequential && !isCcRecipient(signer) && ( + ( + + + + + + + { + field.onChange(e); + onSigningOrderChange(signerIndex, e.target.value); + }} + onBlur={(e) => { + field.onBlur(); + onSigningOrderChange(signerIndex, e.target.value); + }} + disabled={isFieldDisabled} + /> + + + + )} + /> + )} + + ( + + + onAutoCompleteSelect(signerIndex, suggestion)} + onSearchQueryChange={(query) => { + field.onChange(query); + onSearchQueryChange(query); + }} + loading={isLoadingSuggestions} + data-testid="signer-email-input" + maxLength={254} + /> + + + + + )} + /> + + ( + + + onAutoCompleteSelect(signerIndex, suggestion)} + onSearchQueryChange={(query) => { + field.onChange(query); + onSearchQueryChange(query); + }} + loading={isLoadingSuggestions} + maxLength={255} + /> + + + + + )} + /> + + ( + + + { + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + onRoleChange(signerIndex, value as RecipientRole); + }} + disabled={isFieldDisabled} + /> + + + + + )} + /> + + +
+ + {showAdvancedSettings && organisation.organisationClaim.flags.cfr21 && ( + ( + + + + + + + + )} + /> + )} +
+ ); +};