mirror of
https://github.com/documenso/documenso.git
synced 2025-11-15 01:01:49 +10:00
feat: save subject and message on blur
This commit is contained in:
@ -38,6 +38,7 @@ import {
|
||||
ZResendDocumentMutationSchema,
|
||||
ZSearchDocumentsMutationSchema,
|
||||
ZSendDocumentMutationSchema,
|
||||
ZSetDocumentEmailSettingsMutationSchema,
|
||||
ZSetPasswordForDocumentMutationSchema,
|
||||
ZSetSettingsForDocumentMutationSchema,
|
||||
ZSetTitleForDocumentMutationSchema,
|
||||
@ -275,6 +276,32 @@ export const documentRouter = router({
|
||||
}
|
||||
}),
|
||||
|
||||
setDocumentEmailSettings: authenticatedProcedure
|
||||
.input(ZSetDocumentEmailSettingsMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { documentId, subject, message } = input;
|
||||
|
||||
const userId = ctx.user.id;
|
||||
|
||||
return await upsertDocumentMeta({
|
||||
documentId,
|
||||
userId,
|
||||
subject,
|
||||
message,
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message:
|
||||
'We were unable to update the email settings for this document. Please try again later.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
setPasswordForDocument: authenticatedProcedure
|
||||
.input(ZSetPasswordForDocumentMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
|
||||
@ -139,6 +139,12 @@ export const ZSendDocumentMutationSchema = z.object({
|
||||
}),
|
||||
});
|
||||
|
||||
export const ZSetDocumentEmailSettingsMutationSchema = z.object({
|
||||
documentId: z.number(),
|
||||
subject: z.string().optional(),
|
||||
message: z.string().optional(),
|
||||
});
|
||||
|
||||
export const ZSetPasswordForDocumentMutationSchema = z.object({
|
||||
documentId: z.number(),
|
||||
password: z.string(),
|
||||
|
||||
@ -1,13 +1,21 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useForm } from 'react-hook-form';
|
||||
|
||||
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
|
||||
import type { Field, Recipient } from '@documenso/prisma/client';
|
||||
import { DocumentStatus } from '@documenso/prisma/client';
|
||||
import type { DocumentWithData } from '@documenso/prisma/types/document-with-data';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { DocumentSendEmailMessageHelper } from '@documenso/ui/components/document/document-send-email-message-helper';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
import { Button } from '../button';
|
||||
import { FormErrorMessage } from '../form/form-error-message';
|
||||
import { Input } from '../input';
|
||||
import { Label } from '../label';
|
||||
@ -44,6 +52,7 @@ export const AddSubjectFormPartial = ({
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
setValue,
|
||||
formState: { errors, isSubmitting },
|
||||
} = useForm<TAddSubjectFormSchema>({
|
||||
defaultValues: {
|
||||
@ -55,6 +64,87 @@ export const AddSubjectFormPartial = ({
|
||||
resolver: zodResolver(ZAddSubjectFormSchema),
|
||||
});
|
||||
|
||||
const [oldEmailData, setOldEmailData] = useState<{ subject: string; message: string } | null>(
|
||||
() =>
|
||||
document.documentMeta
|
||||
? {
|
||||
subject: document.documentMeta.subject ?? '',
|
||||
message: document.documentMeta.message ?? '',
|
||||
}
|
||||
: null,
|
||||
);
|
||||
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
const utils = trpc.useUtils();
|
||||
|
||||
const { mutateAsync: setEmailSettingsForDocument } =
|
||||
trpc.document.setDocumentEmailSettings.useMutation({
|
||||
...DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||
onSuccess: () => {
|
||||
const data = utils.document.getDocumentWithDetailsById.getData({
|
||||
id: document.id,
|
||||
});
|
||||
|
||||
setOldEmailData({
|
||||
subject: data?.documentMeta?.subject ?? '',
|
||||
message: data?.documentMeta?.message ?? '',
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const handleOnBlur = async (field: 'subject' | 'message', value: string) => {
|
||||
try {
|
||||
await setEmailSettingsForDocument({
|
||||
documentId: document.id,
|
||||
[field]: value,
|
||||
});
|
||||
|
||||
router.refresh();
|
||||
|
||||
toast({
|
||||
title: 'Email settings updated',
|
||||
description: `The email settings for the document have been updated.`,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: 'An error occurred while updating the email settings.',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleUndoButton = async () => {
|
||||
try {
|
||||
if (oldEmailData) {
|
||||
await setEmailSettingsForDocument({
|
||||
documentId: document.id,
|
||||
subject: oldEmailData.subject,
|
||||
message: oldEmailData.message,
|
||||
});
|
||||
|
||||
setValue('meta.subject', oldEmailData.subject);
|
||||
setValue('meta.message', oldEmailData.message);
|
||||
|
||||
setOldEmailData(null);
|
||||
router.refresh();
|
||||
|
||||
toast({
|
||||
title: 'Changes reverted',
|
||||
description: 'The latest change has been reverted to the original value.',
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: 'An error occurred while undoing the latest change.',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onFormSubmit = handleSubmit(onSubmit);
|
||||
const { currentStep, totalSteps, previousStep } = useStep();
|
||||
|
||||
@ -64,6 +154,7 @@ export const AddSubjectFormPartial = ({
|
||||
title={documentFlow.title}
|
||||
description={documentFlow.description}
|
||||
/>
|
||||
|
||||
<DocumentFlowFormContainerContent>
|
||||
<div className="flex flex-col">
|
||||
{isDocumentPdfLoaded &&
|
||||
@ -81,7 +172,11 @@ export const AddSubjectFormPartial = ({
|
||||
id="subject"
|
||||
className="bg-background mt-2"
|
||||
disabled={isSubmitting}
|
||||
{...register('meta.subject')}
|
||||
{...register('meta.subject', {
|
||||
onBlur: (event) => {
|
||||
void handleOnBlur('subject', event.target.value);
|
||||
},
|
||||
})}
|
||||
/>
|
||||
|
||||
<FormErrorMessage className="mt-2" error={errors.meta?.subject} />
|
||||
@ -96,7 +191,11 @@ export const AddSubjectFormPartial = ({
|
||||
id="message"
|
||||
className="bg-background mt-2 h-32 resize-none"
|
||||
disabled={isSubmitting}
|
||||
{...register('meta.message')}
|
||||
{...register('meta.message', {
|
||||
onBlur: (event) => {
|
||||
void handleOnBlur('message', event.target.value);
|
||||
},
|
||||
})}
|
||||
/>
|
||||
|
||||
<FormErrorMessage
|
||||
@ -105,6 +204,11 @@ export const AddSubjectFormPartial = ({
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Hide the button after 5 seconds */}
|
||||
{oldEmailData && (
|
||||
<Button onClick={() => void handleUndoButton()}>Undo latest change</Button>
|
||||
)}
|
||||
|
||||
<DocumentSendEmailMessageHelper />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user