'use client'; import { useState } from 'react'; import { useRouter } from 'next/navigation'; import { zodResolver } from '@hookform/resolvers/zod'; import { Trans, msg } from '@lingui/macro'; import { useLingui } from '@lingui/react'; import { addDays, addMonths, addWeeks, format } from 'date-fns'; import { Calendar as CalendarIcon } from 'lucide-react'; import { useForm } from 'react-hook-form'; import * as z from 'zod'; import { trpc } from '@documenso/trpc/react'; import { Button } from '@documenso/ui/primitives/button'; import { Calendar } from '@documenso/ui/primitives/calendar'; import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@documenso/ui/primitives/dialog'; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from '@documenso/ui/primitives/form/form'; import { Popover, PopoverContent, PopoverTrigger } from '@documenso/ui/primitives/popover'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@documenso/ui/primitives/select'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@documenso/ui/primitives/tabs'; import { calculatePeriod } from '../../lib/calculate-period'; import { cn } from '../../lib/utils'; import { useToast } from '../use-toast'; import type { TAddSignerSchema as Signer } from './add-signers.types'; const dateFormSchema = z.object({ expiry: z.date({ required_error: 'Please select an expiry date.', }), }); const periodFormSchema = z.object({ amount: z.number().min(1, 'Please enter a number greater than 0.'), unit: z.enum(['days', 'weeks', 'months']), }); type DocumentExpiryDialogProps = { open: boolean; onOpenChange: (_open: boolean) => void; signer: Signer; documentId: number; }; export function DocumentExpiryDialog({ open, onOpenChange, signer, documentId, }: DocumentExpiryDialogProps) { const { _ } = useLingui(); const router = useRouter(); const { toast } = useToast(); const [activeTab, setActiveTab] = useState<'date' | 'period'>('date'); const dateForm = useForm>({ resolver: zodResolver(dateFormSchema), defaultValues: { expiry: signer.expiry, }, }); const periodForm = useForm>({ resolver: zodResolver(periodFormSchema), defaultValues: signer.expiry ? calculatePeriod(signer.expiry) : { amount: undefined, unit: undefined, }, }); const watchAmount = periodForm.watch('amount'); const watchUnit = periodForm.watch('unit'); const { mutateAsync: setSignerExpiry, isLoading } = trpc.recipient.setSignerExpiry.useMutation({ onSuccess: (updatedRecipient) => { router.refresh(); periodForm.reset( updatedRecipient?.expired ? calculatePeriod(updatedRecipient.expired) : { amount: undefined, unit: undefined, }, ); dateForm.reset( { expiry: updatedRecipient?.expired ?? undefined, }, { keepValues: false, }, ); toast({ title: _(msg`Signer Expiry Set`), description: _(msg`The expiry date for the signer has been set.`), duration: 5000, }); onOpenChange(false); }, onError: (error) => { toast({ title: _(msg`Error`), description: error.message || _(msg`An error occurred while setting the expiry date.`), variant: 'destructive', duration: 7500, }); }, }); const onSetExpiry = async ( values: z.infer | z.infer, ) => { if (!signer.nativeId) { return toast({ title: _(msg`Error`), description: _(msg`An error occurred while setting the expiry date.`), variant: 'destructive', duration: 7500, }); } let expiryDate: Date; if ('expiry' in values) { expiryDate = values.expiry; } else { const now = new Date(); switch (values.unit) { case 'days': expiryDate = addDays(now, values.amount); break; case 'weeks': expiryDate = addWeeks(now, values.amount); break; case 'months': expiryDate = addMonths(now, values.amount); break; } } await setSignerExpiry({ documentId, signerId: signer.nativeId, expiry: expiryDate, }); // TODO: Implement logic to update expiry when resending document // This should be handled on the server-side when a document is resent // TODO: Implement logic to mark recipients as expired // This should be a scheduled task or part of the completion process on the server }; return ( Set Document Expiry Set the expiry date for the document signing recipient. The recipient will not be able to sign the document after this date. { // eslint-disable-next-line @typescript-eslint/consistent-type-assertions return setActiveTab(value as 'date' | 'period'); }} > Specific Date Time Period
( Expiry Date date < new Date() || date < new Date('1900-01-01')} initialFocus /> The document will expire at 11:59 PM on the selected date. )} />
( Amount )} /> ( Unit )} />
The document will expire after the selected time period from now.
); }