mirror of
https://github.com/documenso/documenso.git
synced 2025-11-14 00:32:43 +10:00
fix: add template send
This commit is contained in:
@ -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<TAddRecipientsForNewDocumentSchema>({
|
||||
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({
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-lg">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Document Recipients</DialogTitle>
|
||||
<DialogDescription>Add the recipients to create the template with</DialogDescription>
|
||||
<DialogTitle>Create document from template</DialogTitle>
|
||||
<DialogDescription>Add the recipients to create the document with</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<Form {...form}>
|
||||
@ -161,7 +176,7 @@ export function UseTemplateDialog({
|
||||
{index === 0 && <FormLabel required>Email</FormLabel>}
|
||||
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
<Input {...field} placeholder={recipients[index].email} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -176,7 +191,7 @@ export function UseTemplateDialog({
|
||||
{index === 0 && <FormLabel>Name</FormLabel>}
|
||||
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
<Input {...field} placeholder={recipients[index].name} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -186,6 +201,47 @@ export function UseTemplateDialog({
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-4 flex flex-row items-center">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="sendDocument"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<div className="flex flex-row items-center">
|
||||
<Checkbox
|
||||
id="sendDocument"
|
||||
className="h-5 w-5"
|
||||
checkClassName="dark:text-white text-primary"
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
/>
|
||||
|
||||
<label
|
||||
className="text-muted-foreground ml-2 flex items-center text-sm"
|
||||
htmlFor="sendDocument"
|
||||
>
|
||||
Send document
|
||||
<Tooltip>
|
||||
<TooltipTrigger type="button">
|
||||
<InfoIcon className="mx-1 h-4 w-4" />
|
||||
</TooltipTrigger>
|
||||
|
||||
<TooltipContent className="text-muted-foreground z-[99999] max-w-md space-y-2 p-4">
|
||||
<p>
|
||||
The document will be immediately sent to recipients if this is
|
||||
checked.
|
||||
</p>
|
||||
|
||||
<p>Otherwise, the document will be created as a draft.</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</label>
|
||||
</div>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button type="button" variant="secondary">
|
||||
@ -194,7 +250,7 @@ export function UseTemplateDialog({
|
||||
</DialogClose>
|
||||
|
||||
<Button type="submit" loading={form.formState.isSubmitting}>
|
||||
Create Document
|
||||
{form.getValues('sendDocument') ? 'Send' : 'Review'}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</fieldset>
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}),
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ export const ZCreateDocumentFromTemplateMutationSchema = z.object({
|
||||
name: z.string().optional(),
|
||||
}),
|
||||
),
|
||||
sendDocument: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export const ZDuplicateTemplateMutationSchema = z.object({
|
||||
|
||||
Reference in New Issue
Block a user