mirror of
https://github.com/documenso/documenso.git
synced 2025-11-16 01:32:06 +10:00
chore: cleanup
This commit is contained in:
@ -37,11 +37,6 @@ export const RecipientProvider = ({
|
|||||||
recipient,
|
recipient,
|
||||||
targetSigner = null,
|
targetSigner = null,
|
||||||
}: RecipientProviderProps) => {
|
}: RecipientProviderProps) => {
|
||||||
// console.log({
|
|
||||||
// recipient,
|
|
||||||
// targetSigner,
|
|
||||||
// isAssistantMode: !!targetSigner,
|
|
||||||
// });
|
|
||||||
return (
|
return (
|
||||||
<RecipientContext.Provider
|
<RecipientContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
|||||||
@ -1,413 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { useMemo, useState } from 'react';
|
|
||||||
|
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
|
||||||
import { Trans } from '@lingui/macro';
|
|
||||||
import { ArrowRight } from 'lucide-react';
|
|
||||||
import { useForm } from 'react-hook-form';
|
|
||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import { fieldsContainUnsignedRequiredField } from '@documenso/lib/utils/advanced-fields-helpers';
|
|
||||||
import type { Field } from '@documenso/prisma/client';
|
|
||||||
import { RecipientRole } from '@documenso/prisma/client';
|
|
||||||
import { cn } from '@documenso/ui/lib/utils';
|
|
||||||
import { Button } from '@documenso/ui/primitives/button';
|
|
||||||
import {
|
|
||||||
Dialog,
|
|
||||||
DialogClose,
|
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
DialogTitle,
|
|
||||||
DialogTrigger,
|
|
||||||
} from '@documenso/ui/primitives/dialog';
|
|
||||||
import {
|
|
||||||
Form,
|
|
||||||
FormControl,
|
|
||||||
FormField,
|
|
||||||
FormItem,
|
|
||||||
FormLabel,
|
|
||||||
FormMessage,
|
|
||||||
} from '@documenso/ui/primitives/form/form';
|
|
||||||
import { Input } from '@documenso/ui/primitives/input';
|
|
||||||
|
|
||||||
import { SigningDisclosure } from '~/components/general/signing-disclosure';
|
|
||||||
|
|
||||||
export type StepSignDialogProps = {
|
|
||||||
isSubmitting: boolean;
|
|
||||||
documentTitle: string;
|
|
||||||
fields: Field[];
|
|
||||||
fieldsValidated: () => void | Promise<void>;
|
|
||||||
onSignatureComplete: (nextSigner?: { email: string; name: string }) => void | Promise<void>;
|
|
||||||
role: RecipientRole;
|
|
||||||
disabled?: boolean;
|
|
||||||
canModifyNextSigner?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
const formSchema = z.object({
|
|
||||||
nextSigner: z
|
|
||||||
.object({
|
|
||||||
email: z.string().email({ message: 'Please enter a valid email address' }).optional(),
|
|
||||||
name: z.string().min(1, { message: 'Name is required' }).optional(),
|
|
||||||
})
|
|
||||||
.refine(
|
|
||||||
(data) => {
|
|
||||||
if (data.name) {
|
|
||||||
return !!data.email;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
{
|
|
||||||
message: 'Email is required when name is provided',
|
|
||||||
path: ['email'],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
type TFormSchema = z.infer<typeof formSchema>;
|
|
||||||
|
|
||||||
export default function StepSignDialog({
|
|
||||||
isSubmitting,
|
|
||||||
documentTitle,
|
|
||||||
fields,
|
|
||||||
fieldsValidated,
|
|
||||||
onSignatureComplete,
|
|
||||||
role,
|
|
||||||
disabled = false,
|
|
||||||
canModifyNextSigner = false,
|
|
||||||
}: StepSignDialogProps) {
|
|
||||||
const [step, setStep] = useState(1);
|
|
||||||
const [showDialog, setShowDialog] = useState(false);
|
|
||||||
|
|
||||||
const isComplete = useMemo(() => !fieldsContainUnsignedRequiredField(fields), [fields]);
|
|
||||||
|
|
||||||
const handleOpenChange = (open: boolean) => {
|
|
||||||
if (isSubmitting || !isComplete) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setShowDialog(open);
|
|
||||||
};
|
|
||||||
|
|
||||||
const totalSteps = 2;
|
|
||||||
|
|
||||||
const handleContinue = () => {
|
|
||||||
if (step < totalSteps) {
|
|
||||||
setStep(step + 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const form = useForm<TFormSchema>({
|
|
||||||
resolver: zodResolver(formSchema),
|
|
||||||
defaultValues: {
|
|
||||||
nextSigner: {
|
|
||||||
email: '',
|
|
||||||
name: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const onFormSubmit = async (data: TFormSchema) => {
|
|
||||||
try {
|
|
||||||
await fieldsValidated();
|
|
||||||
|
|
||||||
if (!canModifyNextSigner || !data.nextSigner.email) {
|
|
||||||
await onSignatureComplete();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await onSignatureComplete({
|
|
||||||
email: data.nextSigner.email.trim().toLowerCase(),
|
|
||||||
name: data.nextSigner.name?.trim() ?? '',
|
|
||||||
});
|
|
||||||
|
|
||||||
setShowDialog(false);
|
|
||||||
form.reset();
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{!canModifyNextSigner ? (
|
|
||||||
<Dialog open={showDialog} onOpenChange={handleOpenChange}>
|
|
||||||
<DialogTrigger asChild>
|
|
||||||
<Button
|
|
||||||
className="w-full"
|
|
||||||
type="button"
|
|
||||||
size="lg"
|
|
||||||
onClick={fieldsValidated}
|
|
||||||
loading={isSubmitting}
|
|
||||||
disabled={disabled}
|
|
||||||
>
|
|
||||||
{isComplete ? <Trans>Complete</Trans> : <Trans>Next field</Trans>}
|
|
||||||
</Button>
|
|
||||||
</DialogTrigger>
|
|
||||||
|
|
||||||
<DialogContent>
|
|
||||||
<DialogTitle>
|
|
||||||
<div className="text-foreground text-xl font-semibold">
|
|
||||||
{role === RecipientRole.VIEWER && <Trans>Complete Viewing</Trans>}
|
|
||||||
{role === RecipientRole.SIGNER && <Trans>Complete Signing</Trans>}
|
|
||||||
{role === RecipientRole.APPROVER && <Trans>Complete Approval</Trans>}
|
|
||||||
</div>
|
|
||||||
</DialogTitle>
|
|
||||||
|
|
||||||
<div className="text-muted-foreground max-w-[50ch]">
|
|
||||||
{role === RecipientRole.VIEWER && (
|
|
||||||
<span>
|
|
||||||
<Trans>
|
|
||||||
<span className="inline-flex flex-wrap">
|
|
||||||
You are about to complete viewing "
|
|
||||||
<span className="inline-block max-w-[11rem] truncate align-baseline">
|
|
||||||
{documentTitle}
|
|
||||||
</span>
|
|
||||||
".
|
|
||||||
</span>
|
|
||||||
<br /> Are you sure?
|
|
||||||
</Trans>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{role === RecipientRole.SIGNER && (
|
|
||||||
<span>
|
|
||||||
<Trans>
|
|
||||||
<span className="inline-flex flex-wrap">
|
|
||||||
You are about to complete signing "
|
|
||||||
<span className="inline-block max-w-[11rem] truncate align-baseline">
|
|
||||||
{documentTitle}
|
|
||||||
</span>
|
|
||||||
".
|
|
||||||
</span>
|
|
||||||
<br /> Are you sure?
|
|
||||||
</Trans>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{role === RecipientRole.APPROVER && (
|
|
||||||
<span>
|
|
||||||
<Trans>
|
|
||||||
<span className="inline-flex flex-wrap">
|
|
||||||
You are about to complete approving{' '}
|
|
||||||
<span className="inline-block max-w-[11rem] truncate align-baseline">
|
|
||||||
"{documentTitle}"
|
|
||||||
</span>
|
|
||||||
.
|
|
||||||
</span>
|
|
||||||
<br /> Are you sure?
|
|
||||||
</Trans>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<SigningDisclosure className="mt-4" />
|
|
||||||
|
|
||||||
<DialogFooter>
|
|
||||||
<div className="flex w-full flex-1 flex-nowrap gap-4">
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
className="dark:bg-muted dark:hover:bg-muted/80 flex-1 bg-black/5 hover:bg-black/10"
|
|
||||||
variant="secondary"
|
|
||||||
onClick={() => {
|
|
||||||
setShowDialog(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Trans>Cancel</Trans>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
className="flex-1"
|
|
||||||
disabled={!isComplete}
|
|
||||||
loading={isSubmitting}
|
|
||||||
onClick={async (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
await onSignatureComplete();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{role === RecipientRole.VIEWER && <Trans>Mark as Viewed</Trans>}
|
|
||||||
{role === RecipientRole.SIGNER && <Trans>Sign</Trans>}
|
|
||||||
{role === RecipientRole.APPROVER && <Trans>Approve</Trans>}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</DialogFooter>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
) : (
|
|
||||||
<Dialog
|
|
||||||
onOpenChange={(open) => {
|
|
||||||
if (open) setStep(1);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<DialogTrigger asChild>
|
|
||||||
<Button
|
|
||||||
className="w-full"
|
|
||||||
type="button"
|
|
||||||
size="lg"
|
|
||||||
onClick={fieldsValidated}
|
|
||||||
loading={isSubmitting}
|
|
||||||
disabled={disabled}
|
|
||||||
>
|
|
||||||
{isComplete ? <Trans>Complete</Trans> : <Trans>Next field</Trans>}
|
|
||||||
</Button>
|
|
||||||
</DialogTrigger>
|
|
||||||
<DialogContent>
|
|
||||||
<DialogTitle>
|
|
||||||
{step === 1 && (
|
|
||||||
<div className="text-foreground text-xl font-semibold">
|
|
||||||
<Trans>Modify Next Signer</Trans>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 2 && (
|
|
||||||
<div className="text-foreground text-xl font-semibold">
|
|
||||||
{role === RecipientRole.VIEWER && <Trans>Complete Viewing</Trans>}
|
|
||||||
{role === RecipientRole.SIGNER && <Trans>Complete Signing</Trans>}
|
|
||||||
{role === RecipientRole.APPROVER && <Trans>Complete Approval</Trans>}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</DialogTitle>
|
|
||||||
|
|
||||||
{step === 1 && (
|
|
||||||
<Form {...form}>
|
|
||||||
<form onSubmit={form.handleSubmit(onFormSubmit)} className="flex flex-col gap-y-4">
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="nextSigner.email"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
<Trans>Next Signer Email</Trans>
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input type="email" {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="nextSigner.name"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
<Trans>Next Signer Name</Trans>
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
</Form>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 2 && (
|
|
||||||
<>
|
|
||||||
<div className="text-muted-foreground max-w-[50ch]">
|
|
||||||
{role === RecipientRole.VIEWER && (
|
|
||||||
<span>
|
|
||||||
<Trans>
|
|
||||||
<span className="inline-flex flex-wrap">
|
|
||||||
You are about to complete viewing "
|
|
||||||
<span className="inline-block max-w-[11rem] truncate align-baseline">
|
|
||||||
{documentTitle}
|
|
||||||
</span>
|
|
||||||
".
|
|
||||||
</span>
|
|
||||||
<br /> Are you sure?
|
|
||||||
</Trans>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{role === RecipientRole.SIGNER && (
|
|
||||||
<span>
|
|
||||||
<Trans>
|
|
||||||
<span className="inline-flex flex-wrap">
|
|
||||||
You are about to complete signing "
|
|
||||||
<span className="inline-block max-w-[11rem] truncate align-baseline">
|
|
||||||
{documentTitle}
|
|
||||||
</span>
|
|
||||||
".
|
|
||||||
</span>
|
|
||||||
<br /> Are you sure?
|
|
||||||
</Trans>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{role === RecipientRole.APPROVER && (
|
|
||||||
<span>
|
|
||||||
<Trans>
|
|
||||||
<span className="inline-flex flex-wrap">
|
|
||||||
You are about to complete approving{' '}
|
|
||||||
<span className="inline-block max-w-[11rem] truncate align-baseline">
|
|
||||||
"{documentTitle}"
|
|
||||||
</span>
|
|
||||||
.
|
|
||||||
</span>
|
|
||||||
<br /> Are you sure?
|
|
||||||
</Trans>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<SigningDisclosure className="mt-4" />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="flex flex-col justify-between gap-4 sm:flex-row sm:items-center">
|
|
||||||
<div className="flex justify-center space-x-1.5 max-sm:order-1">
|
|
||||||
{[...Array(totalSteps)].map((_, index) => (
|
|
||||||
<button
|
|
||||||
key={index}
|
|
||||||
onClick={() => setStep(index + 1)}
|
|
||||||
className={cn(
|
|
||||||
'bg-primary h-1.5 w-1.5 rounded-full',
|
|
||||||
index + 1 === step ? 'bg-primary' : 'opacity-20',
|
|
||||||
)}
|
|
||||||
type="button"
|
|
||||||
aria-label={`Go to step ${index + 1}`}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<DialogFooter>
|
|
||||||
<DialogClose asChild>
|
|
||||||
<Button type="button" variant="ghost">
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</DialogClose>
|
|
||||||
{step === 1 && (
|
|
||||||
<Button className="group" type="button" onClick={handleContinue}>
|
|
||||||
Next
|
|
||||||
<ArrowRight
|
|
||||||
className="-me-1 ms-2 opacity-60 transition-transform group-hover:translate-x-0.5"
|
|
||||||
size={16}
|
|
||||||
strokeWidth={2}
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 2 && (
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
className="flex-1"
|
|
||||||
disabled={!isComplete}
|
|
||||||
loading={isSubmitting}
|
|
||||||
onClick={form.handleSubmit(onFormSubmit)}
|
|
||||||
>
|
|
||||||
{role === RecipientRole.VIEWER && <Trans>Mark as Viewed</Trans>}
|
|
||||||
{role === RecipientRole.SIGNER && <Trans>Sign</Trans>}
|
|
||||||
{role === RecipientRole.APPROVER && <Trans>Approve</Trans>}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</DialogFooter>
|
|
||||||
</div>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -10,7 +10,6 @@ export type EmbedDocumentCompletedPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const EmbedDocumentCompleted = ({ name, signature }: EmbedDocumentCompletedPageProps) => {
|
export const EmbedDocumentCompleted = ({ name, signature }: EmbedDocumentCompletedPageProps) => {
|
||||||
console.log({ signature });
|
|
||||||
return (
|
return (
|
||||||
<div className="embed--DocumentCompleted relative mx-auto flex min-h-[100dvh] max-w-screen-lg flex-col items-center justify-center p-6">
|
<div className="embed--DocumentCompleted relative mx-auto flex min-h-[100dvh] max-w-screen-lg flex-col items-center justify-center p-6">
|
||||||
<h3 className="text-foreground text-2xl font-semibold">
|
<h3 className="text-foreground text-2xl font-semibold">
|
||||||
|
|||||||
@ -103,8 +103,6 @@ export const completeDocumentWithToken = async ({
|
|||||||
requestMetadata,
|
requestMetadata,
|
||||||
nextSigner,
|
nextSigner,
|
||||||
}: CompleteDocumentWithTokenOptions) => {
|
}: CompleteDocumentWithTokenOptions) => {
|
||||||
console.log('completeDocumentWithToken == document-router', token, documentId, nextSigner);
|
|
||||||
|
|
||||||
const document = await getDocument({ token, documentId });
|
const document = await getDocument({ token, documentId });
|
||||||
|
|
||||||
if (document.status !== DocumentStatus.PENDING) {
|
if (document.status !== DocumentStatus.PENDING) {
|
||||||
@ -166,8 +164,6 @@ export const completeDocumentWithToken = async ({
|
|||||||
document.documentMeta?.modifyNextSigner &&
|
document.documentMeta?.modifyNextSigner &&
|
||||||
document.documentMeta?.signingOrder === DocumentSigningOrder.SEQUENTIAL
|
document.documentMeta?.signingOrder === DocumentSigningOrder.SEQUENTIAL
|
||||||
) {
|
) {
|
||||||
console.log('delegateNextSigner == document-router', document.id, recipient.id, nextSigner);
|
|
||||||
|
|
||||||
await delegateNextSigner({
|
await delegateNextSigner({
|
||||||
documentId: document.id,
|
documentId: document.id,
|
||||||
currentRecipientId: recipient.id,
|
currentRecipientId: recipient.id,
|
||||||
|
|||||||
@ -439,14 +439,6 @@ export const recipientRouter = router({
|
|||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
const { token, documentId, authOptions, nextSigner } = input;
|
const { token, documentId, authOptions, nextSigner } = input;
|
||||||
|
|
||||||
console.log(
|
|
||||||
'completeDocumentWithToken == recipient-router',
|
|
||||||
token,
|
|
||||||
documentId,
|
|
||||||
authOptions,
|
|
||||||
nextSigner,
|
|
||||||
);
|
|
||||||
|
|
||||||
return await completeDocumentWithToken({
|
return await completeDocumentWithToken({
|
||||||
token,
|
token,
|
||||||
documentId,
|
documentId,
|
||||||
|
|||||||
Reference in New Issue
Block a user