diff --git a/apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx b/apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx index 1852dd147..7ddc1f90d 100644 --- a/apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx +++ b/apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx @@ -1,13 +1,15 @@ import { useRouter } from 'next/navigation'; import { zodResolver } from '@hookform/resolvers/zod'; -import { Plus } from 'lucide-react'; +import { InfoIcon, Plus } from 'lucide-react'; import { useFieldArray, useForm } from 'react-hook-form'; import * as z from 'zod'; +import { AppError } from '@documenso/lib/errors/app-error'; import type { Recipient } from '@documenso/prisma/client'; import { trpc } from '@documenso/trpc/react'; import { Button } from '@documenso/ui/primitives/button'; +import { Checkbox } from '@documenso/ui/primitives/checkbox'; import { Dialog, DialogClose, @@ -27,12 +29,15 @@ import { FormMessage, } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; +import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip'; +import type { Toast } from '@documenso/ui/primitives/use-toast'; import { useToast } from '@documenso/ui/primitives/use-toast'; import { useOptionalCurrentTeam } from '~/providers/team'; const ZAddRecipientsForNewDocumentSchema = z .object({ + sendDocument: z.boolean(), recipients: z.array( z.object({ id: z.number(), @@ -90,6 +95,7 @@ export function UseTemplateDialog({ const form = useForm({ resolver: zodResolver(ZAddRecipientsForNewDocumentSchema), defaultValues: { + sendDocument: false, recipients: recipients.map((recipient) => ({ id: recipient.id, name: recipient.name, @@ -107,6 +113,7 @@ export function UseTemplateDialog({ templateId, teamId: team?.id, recipients: data.recipients, + sendDocument: data.sendDocument, }); toast({ @@ -117,11 +124,19 @@ export function UseTemplateDialog({ router.push(`${documentRootPath}/${id}`); } catch (err) { - toast({ + const error = AppError.parseError(err); + + const toastPayload: Toast = { title: 'Error', description: 'An error occurred while creating document from template.', variant: 'destructive', - }); + }; + + if (error.code === 'DOCUMENT_SEND_FAILED') { + toastPayload.description = 'The document was created but could not be sent to recipients.'; + } + + toast(toastPayload); } }; @@ -140,8 +155,8 @@ export function UseTemplateDialog({ - Document Recipients - Add the recipients to create the template with + Create document from template + Add the recipients to create the document with
@@ -161,7 +176,7 @@ export function UseTemplateDialog({ {index === 0 && Email} - + @@ -176,7 +191,7 @@ export function UseTemplateDialog({ {index === 0 && Name} - + @@ -186,6 +201,47 @@ export function UseTemplateDialog({ ))} +
+ ( + +
+ + + +
+
+ )} + /> +
+ diff --git a/packages/trpc/server/template-router/router.ts b/packages/trpc/server/template-router/router.ts index 4ed567b2b..19f1c50f1 100644 --- a/packages/trpc/server/template-router/router.ts +++ b/packages/trpc/server/template-router/router.ts @@ -1,10 +1,14 @@ import { TRPCError } from '@trpc/server'; import { getServerLimits } from '@documenso/ee/server-only/limits/server'; +import { AppError } from '@documenso/lib/errors/app-error'; +import { sendDocument } from '@documenso/lib/server-only/document/send-document'; import { createDocumentFromTemplate } from '@documenso/lib/server-only/template/create-document-from-template'; import { createTemplate } from '@documenso/lib/server-only/template/create-template'; import { deleteTemplate } from '@documenso/lib/server-only/template/delete-template'; import { duplicateTemplate } from '@documenso/lib/server-only/template/duplicate-template'; +import { extractNextApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata'; +import type { Document } from '@documenso/prisma/client'; import { authenticatedProcedure, router } from '../trpc'; import { @@ -49,19 +53,29 @@ export const templateRouter = router({ throw new Error('You have reached your document limit.'); } - return await createDocumentFromTemplate({ + let document: Document = await createDocumentFromTemplate({ templateId, teamId, userId: ctx.user.id, recipients: input.recipients, }); + + if (input.sendDocument) { + document = await sendDocument({ + documentId: document.id, + userId: ctx.user.id, + teamId, + requestMetadata: extractNextApiRequestMetadata(ctx.req), + }).catch(() => { + throw new AppError('DOCUMENT_SEND_FAILED'); + }); + } + + return document; } catch (err) { console.error(err); - throw new TRPCError({ - code: 'BAD_REQUEST', - message: 'We were unable to create this document. Please try again later.', - }); + throw AppError.parseErrorToTRPCError(err); } }), diff --git a/packages/trpc/server/template-router/schema.ts b/packages/trpc/server/template-router/schema.ts index 3fd47791f..12e524728 100644 --- a/packages/trpc/server/template-router/schema.ts +++ b/packages/trpc/server/template-router/schema.ts @@ -16,6 +16,7 @@ export const ZCreateDocumentFromTemplateMutationSchema = z.object({ name: z.string().optional(), }), ), + sendDocument: z.boolean().optional(), }); export const ZDuplicateTemplateMutationSchema = z.object({