feat: add/update title of the document (#663)

This commit is contained in:
Tanay
2023-11-28 09:26:50 +05:30
committed by GitHub
parent 8048c29480
commit adc97802ea
9 changed files with 221 additions and 9 deletions

View File

@ -4,7 +4,7 @@ import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { DocumentData, Field, Recipient, User } from '@documenso/prisma/client';
import { DocumentData, DocumentStatus, Field, Recipient, User } from '@documenso/prisma/client';
import { DocumentWithData } from '@documenso/prisma/types/document-with-data';
import { cn } from '@documenso/ui/lib/utils';
import { Card, CardContent } from '@documenso/ui/primitives/card';
@ -14,6 +14,8 @@ import { AddSignersFormPartial } from '@documenso/ui/primitives/document-flow/ad
import { TAddSignersFormSchema } from '@documenso/ui/primitives/document-flow/add-signers.types';
import { AddSubjectFormPartial } from '@documenso/ui/primitives/document-flow/add-subject';
import { TAddSubjectFormSchema } from '@documenso/ui/primitives/document-flow/add-subject.types';
import { AddTitleFormPartial } from '@documenso/ui/primitives/document-flow/add-title';
import { TAddTitleFormSchema } from '@documenso/ui/primitives/document-flow/add-title.types';
import {
DocumentFlowFormContainer,
DocumentFlowFormContainerHeader,
@ -25,6 +27,7 @@ import { useToast } from '@documenso/ui/primitives/use-toast';
import { addFields } from '~/components/forms/edit-document/add-fields.action';
import { addSigners } from '~/components/forms/edit-document/add-signers.action';
import { completeDocument } from '~/components/forms/edit-document/add-subject.action';
import { addTitle } from '~/components/forms/edit-document/add-title.action';
export type EditDocumentFormProps = {
className?: string;
@ -35,7 +38,7 @@ export type EditDocumentFormProps = {
documentData: DocumentData;
};
type EditDocumentStep = 'signers' | 'fields' | 'subject';
type EditDocumentStep = 'title' | 'signers' | 'fields' | 'subject';
export const EditDocumentForm = ({
className,
@ -48,30 +51,60 @@ export const EditDocumentForm = ({
const { toast } = useToast();
const router = useRouter();
const [step, setStep] = useState<EditDocumentStep>('signers');
const [step, setStep] = useState<EditDocumentStep>(
document.status === DocumentStatus.DRAFT ? 'title' : 'signers',
);
const documentFlow: Record<EditDocumentStep, DocumentFlowStep> = {
title: {
title: 'Add Title',
description: 'Add the title to the document.',
stepIndex: 1,
},
signers: {
title: 'Add Signers',
description: 'Add the people who will sign the document.',
stepIndex: 1,
stepIndex: 2,
onBackStep: () => document.status === DocumentStatus.DRAFT && setStep('title'),
},
fields: {
title: 'Add Fields',
description: 'Add all relevant fields for each recipient.',
stepIndex: 2,
stepIndex: 3,
onBackStep: () => setStep('signers'),
},
subject: {
title: 'Add Subject',
description: 'Add the subject and message you wish to send to signers.',
stepIndex: 3,
stepIndex: 4,
onBackStep: () => setStep('fields'),
},
};
const currentDocumentFlow = documentFlow[step];
const onAddTitleFormSubmit = async (data: TAddTitleFormSchema) => {
try {
// Custom invocation server action
await addTitle({
documentId: document.id,
title: data.title,
});
router.refresh();
setStep('signers');
} catch (err) {
console.error(err);
toast({
title: 'Error',
description: 'An error occurred while updating title.',
variant: 'destructive',
});
}
};
const onAddSignersFormSubmit = async (data: TAddSignersFormSchema) => {
try {
// Custom invocation server action
@ -164,10 +197,23 @@ export const EditDocumentForm = ({
description={currentDocumentFlow.description}
/>
{step === 'title' && (
<AddTitleFormPartial
key={recipients.length}
documentFlow={documentFlow.title}
recipients={recipients}
fields={fields}
document={document}
numberOfSteps={Object.keys(documentFlow).length}
onSubmit={onAddTitleFormSubmit}
/>
)}
{step === 'signers' && (
<AddSignersFormPartial
key={recipients.length}
documentFlow={documentFlow.signers}
document={document}
recipients={recipients}
fields={fields}
numberOfSteps={Object.keys(documentFlow).length}

View File

@ -0,0 +1,21 @@
'use server';
import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session';
import { updateTitle } from '@documenso/lib/server-only/document/update-title';
import type { TAddTitleFormSchema } from '@documenso/ui/primitives/document-flow/add-title.types';
export type AddTitleActionInput = TAddTitleFormSchema & {
documentId: number;
};
export const addTitle = async ({ documentId, title }: AddTitleActionInput) => {
'use server';
const { user } = await getRequiredServerComponentSession();
await updateTitle({
documentId,
userId: user.id,
title: title,
});
};

View File

@ -0,0 +1,21 @@
'use server';
import { prisma } from '@documenso/prisma';
export type UpdateTitleOptions = {
userId: number;
documentId: number;
title: string;
};
export const updateTitle = async ({ userId, documentId, title }: UpdateTitleOptions) => {
return await prisma.document.update({
where: {
id: documentId,
userId,
},
data: {
title,
},
});
};

View File

@ -8,6 +8,7 @@ import { getDocumentById } from '@documenso/lib/server-only/document/get-documen
import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document/get-document-by-token';
import { resendDocument } from '@documenso/lib/server-only/document/resend-document';
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
import { updateTitle } from '@documenso/lib/server-only/document/update-title';
import { setFieldsForDocument } from '@documenso/lib/server-only/field/set-fields-for-document';
import { setRecipientsForDocument } from '@documenso/lib/server-only/recipient/set-recipients-for-document';
@ -21,6 +22,7 @@ import {
ZSendDocumentMutationSchema,
ZSetFieldsForDocumentMutationSchema,
ZSetRecipientsForDocumentMutationSchema,
ZSetTitleForDocumentMutationSchema,
} from './schema';
export const documentRouter = router({
@ -113,6 +115,20 @@ export const documentRouter = router({
}
}),
setTitleForDocument: authenticatedProcedure
.input(ZSetTitleForDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {
const { documentId, title } = input;
const userId = ctx.user.id;
return await updateTitle({
title,
userId,
documentId,
});
}),
setRecipientsForDocument: authenticatedProcedure
.input(ZSetRecipientsForDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {

View File

@ -21,6 +21,13 @@ export const ZCreateDocumentMutationSchema = z.object({
export type TCreateDocumentMutationSchema = z.infer<typeof ZCreateDocumentMutationSchema>;
export const ZSetTitleForDocumentMutationSchema = z.object({
documentId: z.number(),
title: z.string().min(1),
});
export type TSetTitleForDocumentMutationSchema = z.infer<typeof ZSetTitleForDocumentMutationSchema>;
export const ZSetRecipientsForDocumentMutationSchema = z.object({
documentId: z.number(),
recipients: z.array(

View File

@ -9,7 +9,8 @@ import { Controller, useFieldArray, useForm } from 'react-hook-form';
import { useLimits } from '@documenso/ee/server-only/limits/provider/client';
import { nanoid } from '@documenso/lib/universal/id';
import { Field, Recipient, SendStatus } from '@documenso/prisma/client';
import { DocumentStatus, Field, Recipient, SendStatus } from '@documenso/prisma/client';
import { DocumentWithData } from '@documenso/prisma/types/document-with-data';
import { Button } from '@documenso/ui/primitives/button';
import { FormErrorMessage } from '@documenso/ui/primitives/form/form-error-message';
import { Input } from '@documenso/ui/primitives/input';
@ -29,6 +30,7 @@ export type AddSignersFormProps = {
documentFlow: DocumentFlowStep;
recipients: Recipient[];
fields: Field[];
document: DocumentWithData;
numberOfSteps: number;
onSubmit: (_data: TAddSignersFormSchema) => void;
};
@ -37,6 +39,7 @@ export const AddSignersFormPartial = ({
documentFlow,
numberOfSteps,
recipients,
document,
fields: _fields,
onSubmit,
}: AddSignersFormProps) => {
@ -223,6 +226,7 @@ export const AddSignersFormPartial = ({
/>
<DocumentFlowFormContainerActions
canGoBack={document.status === DocumentStatus.DRAFT}
loading={isSubmitting}
disabled={isSubmitting}
onGoBackClick={documentFlow.onBackStep}

View File

@ -0,0 +1,88 @@
'use client';
import { useForm } from 'react-hook-form';
import type { Field, Recipient } from '@documenso/prisma/client';
import type { DocumentWithData } from '@documenso/prisma/types/document-with-data';
import { FormErrorMessage } from '@documenso/ui/primitives/form/form-error-message';
import { Input } from '@documenso/ui/primitives/input';
import { Label } from '@documenso/ui/primitives/label';
import type { TAddTitleFormSchema } from './add-title.types';
import {
DocumentFlowFormContainerActions,
DocumentFlowFormContainerContent,
DocumentFlowFormContainerFooter,
DocumentFlowFormContainerStep,
} from './document-flow-root';
import type { DocumentFlowStep } from './types';
export type AddTitleFormProps = {
documentFlow: DocumentFlowStep;
recipients: Recipient[];
fields: Field[];
document: DocumentWithData;
numberOfSteps: number;
onSubmit: (_data: TAddTitleFormSchema) => void;
};
export const AddTitleFormPartial = ({
documentFlow,
recipients: _recipients,
fields: _fields,
document,
numberOfSteps,
onSubmit,
}: AddTitleFormProps) => {
const {
register,
handleSubmit,
formState: { errors, isSubmitting },
} = useForm<TAddTitleFormSchema>({
defaultValues: {
title: document.title,
},
});
const onFormSubmit = handleSubmit(onSubmit);
return (
<>
<DocumentFlowFormContainerContent>
<div className="flex flex-col">
<div className="flex flex-col gap-y-4">
<div>
<Label htmlFor="title">
Title<span className="text-destructive ml-1 inline-block font-medium">*</span>
</Label>
<Input
id="title"
className="bg-background mt-2"
disabled={isSubmitting}
{...register('title', { required: "Title can't be empty" })}
/>
<FormErrorMessage className="mt-2" error={errors.title} />
</div>
</div>
</div>
</DocumentFlowFormContainerContent>
<DocumentFlowFormContainerFooter>
<DocumentFlowFormContainerStep
title={documentFlow.title}
step={documentFlow.stepIndex}
maxStep={numberOfSteps}
/>
<DocumentFlowFormContainerActions
loading={isSubmitting}
disabled={isSubmitting}
onGoBackClick={documentFlow.onBackStep}
onGoNextClick={() => void onFormSubmit()}
/>
</DocumentFlowFormContainerFooter>
</>
);
};

View File

@ -0,0 +1,7 @@
import { z } from 'zod';
export const ZAddTitleFormSchema = z.object({
title: z.string().min(1),
});
export type TAddTitleFormSchema = z.infer<typeof ZAddTitleFormSchema>;

View File

@ -3,6 +3,8 @@ import { z } from 'zod';
import { FieldType } from '@documenso/prisma/client';
export const ZDocumentFlowFormSchema = z.object({
title: z.string().min(1),
signers: z
.array(
z.object({
@ -52,6 +54,6 @@ export interface DocumentFlowStep {
title: string;
description: string;
stepIndex: number;
onBackStep?: () => void;
onNextStep?: () => void;
onBackStep?: () => unknown;
onNextStep?: () => unknown;
}