import { getRecipientType } from '@documenso/lib/client-only/recipient-type'; import { AppError } from '@documenso/lib/errors/app-error'; import type { TEnvelope } from '@documenso/lib/types/envelope'; import type { TEnvelopeRecipientLite } from '@documenso/lib/types/recipient'; import { recipientAbbreviation } from '@documenso/lib/utils/recipient-formatter'; import { trpc as trpcReact } from '@documenso/trpc/react'; import { cn } from '@documenso/ui/lib/utils'; import { Button } from '@documenso/ui/primitives/button'; import { Checkbox } from '@documenso/ui/primitives/checkbox'; import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from '@documenso/ui/primitives/dialog'; import { Form, FormControl, FormField, FormItem, FormLabel } from '@documenso/ui/primitives/form/form'; import { useToast } from '@documenso/ui/primitives/use-toast'; import { zodResolver } from '@hookform/resolvers/zod'; import { msg } from '@lingui/core/macro'; import { Trans, useLingui } from '@lingui/react/macro'; import { DocumentStatus, EnvelopeType, SigningStatus } from '@prisma/client'; import { useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { match } from 'ts-pattern'; import * as z from 'zod'; import { getDistributeErrorMessage } from '~/utils/toast-error-messages'; import { StackAvatar } from '../general/stack-avatar'; export type EnvelopeRedistributeDialogProps = { envelope: Pick & { recipients: TEnvelopeRecipientLite[]; }; envelopeType?: EnvelopeType; trigger?: React.ReactNode; }; export const ZEnvelopeRedistributeFormSchema = z.object({ recipients: z.array(z.number()).min(1, { message: msg`You must select at least one item`.id, }), }); export type TEnvelopeRedistributeFormSchema = z.infer; export const EnvelopeRedistributeDialog = ({ envelope, envelopeType, trigger }: EnvelopeRedistributeDialogProps) => { const recipients = envelope.recipients; const { toast } = useToast(); const { t, i18n } = useLingui(); const [isOpen, setIsOpen] = useState(false); const { mutateAsync: redistributeEnvelope } = trpcReact.envelope.redistribute.useMutation(); const form = useForm({ defaultValues: { recipients: [], }, resolver: zodResolver(ZEnvelopeRedistributeFormSchema), }); const { handleSubmit, formState: { isSubmitting }, } = form; const onFormSubmit = async ({ recipients }: TEnvelopeRedistributeFormSchema) => { try { await redistributeEnvelope({ envelopeId: envelope.id, recipients }); const successMessage = match(envelopeType) .with(EnvelopeType.DOCUMENT, () => ({ title: t`Document resent`, description: t`Your document has been resent successfully.`, })) .with(EnvelopeType.TEMPLATE, () => ({ title: t`Template resent`, description: t`Your template has been resent successfully.`, })) .otherwise(() => ({ title: t`Envelope resent`, description: t`Your envelope has been resent successfully.`, })); toast({ title: successMessage.title, description: successMessage.description, duration: 5000, }); setIsOpen(false); } catch (err) { const error = AppError.parseError(err); const errorMessage = getDistributeErrorMessage(error.code); toast({ title: i18n._(errorMessage.title), description: i18n._(errorMessage.description), variant: 'destructive', duration: 7500, }); } }; useEffect(() => { if (!isOpen) { form.reset(); } }, [isOpen]); if (envelope.status !== DocumentStatus.PENDING || envelope.type !== EnvelopeType.DOCUMENT) { return null; } return ( {trigger} Resend Document Send reminders to the following recipients
( <> {recipients .filter((recipient) => recipient.signingStatus === SigningStatus.NOT_SIGNED) .map((recipient) => ( {recipient.email} checked ? onChange([...value, recipient.id]) : onChange(value.filter((v) => v !== recipient.id)) } /> ))} )} />
); };