Files
sign/apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx

180 lines
5.1 KiB
TypeScript
Raw Normal View History

2023-08-29 14:30:57 +10:00
'use client';
2023-10-10 08:25:58 +05:30
import { useState } from 'react';
2023-08-29 14:30:57 +10:00
import Link from 'next/link';
import {
Copy,
Download,
Edit,
History,
2023-09-21 00:51:02 +00:00
Loader,
2023-08-29 14:30:57 +10:00
MoreHorizontal,
Pencil,
Share,
Trash2,
XCircle,
} from 'lucide-react';
import { useSession } from 'next-auth/react';
2023-09-14 13:21:03 +10:00
import { getFile } from '@documenso/lib/universal/upload/get-file';
import { Document, DocumentStatus, Recipient, User } from '@documenso/prisma/client';
import { DocumentWithData } from '@documenso/prisma/types/document-with-data';
2023-09-21 00:51:02 +00:00
import { trpc as trpcClient } from '@documenso/trpc/client';
import { DocumentShareButton } from '@documenso/ui/components/document/document-share-button';
2023-08-29 14:30:57 +10:00
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuTrigger,
} from '@documenso/ui/primitives/dropdown-menu';
2023-09-21 00:51:02 +00:00
2023-10-10 08:25:58 +05:30
import { DeleteDraftDocumentDialog } from './delete-draft-document-dialog';
2023-11-08 09:25:44 +00:00
import { DuplicateDocumentDialog } from './duplicate-document-dialog';
2023-10-10 08:25:58 +05:30
2023-08-29 14:30:57 +10:00
export type DataTableActionDropdownProps = {
row: Document & {
User: Pick<User, 'id' | 'name' | 'email'>;
Recipient: Recipient[];
};
};
export const DataTableActionDropdown = ({ row }: DataTableActionDropdownProps) => {
const { data: session } = useSession();
2023-10-10 08:25:58 +05:30
const [isDeleteDialogOpen, setDeleteDialogOpen] = useState(false);
2023-11-08 09:25:44 +00:00
const [isDuplicateDialogOpen, setDuplicateDialogOpen] = useState(false);
2023-10-10 08:25:58 +05:30
2023-08-29 14:30:57 +10:00
if (!session) {
return null;
}
const recipient = row.Recipient.find((recipient) => recipient.email === session.user.email);
const isOwner = row.User.id === session.user.id;
// const isRecipient = !!recipient;
const isDraft = row.status === DocumentStatus.DRAFT;
2023-08-29 14:30:57 +10:00
// const isPending = row.status === DocumentStatus.PENDING;
const isComplete = row.status === DocumentStatus.COMPLETED;
// const isSigned = recipient?.signingStatus === SigningStatus.SIGNED;
2023-10-10 08:25:58 +05:30
const isDocumentDeletable = isOwner && row.status === DocumentStatus.DRAFT;
2023-08-29 14:30:57 +10:00
const onDownloadClick = async () => {
let document: DocumentWithData | null = null;
if (!recipient) {
2023-09-21 00:51:02 +00:00
document = await trpcClient.document.getDocumentById.query({
id: row.id,
});
} else {
2023-09-21 00:51:02 +00:00
document = await trpcClient.document.getDocumentByToken.query({
token: recipient.token,
});
}
const documentData = document?.documentData;
2023-08-29 14:30:57 +10:00
if (!documentData) {
return;
2023-08-29 14:30:57 +10:00
}
2023-09-14 13:21:03 +10:00
const documentBytes = await getFile(documentData);
2023-08-29 14:30:57 +10:00
const blob = new Blob([documentBytes], {
type: 'application/pdf',
});
const link = window.document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = row.title || 'document.pdf';
link.click();
window.URL.revokeObjectURL(link.href);
};
return (
<DropdownMenu>
<DropdownMenuTrigger>
2023-09-24 14:45:50 +10:00
<MoreHorizontal className="text-muted-foreground h-5 w-5" />
2023-08-29 14:30:57 +10:00
</DropdownMenuTrigger>
<DropdownMenuContent className="w-52" align="start" forceMount>
<DropdownMenuLabel>Action</DropdownMenuLabel>
<DropdownMenuItem disabled={!recipient || isComplete} asChild>
2023-08-29 14:30:57 +10:00
<Link href={`/sign/${recipient?.token}`}>
<Pencil className="mr-2 h-4 w-4" />
Sign
</Link>
</DropdownMenuItem>
<DropdownMenuItem disabled={!isOwner || isComplete} asChild>
2023-08-29 14:30:57 +10:00
<Link href={`/documents/${row.id}`}>
<Edit className="mr-2 h-4 w-4" />
Edit
</Link>
</DropdownMenuItem>
<DropdownMenuItem disabled={!isComplete} onClick={onDownloadClick}>
<Download className="mr-2 h-4 w-4" />
Download
</DropdownMenuItem>
2023-11-08 09:25:44 +00:00
<DropdownMenuItem onClick={() => setDuplicateDialogOpen(true)}>
2023-08-29 14:30:57 +10:00
<Copy className="mr-2 h-4 w-4" />
Duplicate
</DropdownMenuItem>
<DropdownMenuItem disabled>
<XCircle className="mr-2 h-4 w-4" />
Void
</DropdownMenuItem>
2023-10-10 08:25:58 +05:30
<DropdownMenuItem onClick={() => setDeleteDialogOpen(true)} disabled={!isDocumentDeletable}>
2023-08-29 14:30:57 +10:00
<Trash2 className="mr-2 h-4 w-4" />
Delete
</DropdownMenuItem>
<DropdownMenuLabel>Share</DropdownMenuLabel>
<DropdownMenuItem disabled>
<History className="mr-2 h-4 w-4" />
Resend
</DropdownMenuItem>
<DocumentShareButton
documentId={row.id}
token={recipient?.token}
trigger={({ loading, disabled }) => (
<DropdownMenuItem disabled={disabled || isDraft} onSelect={(e) => e.preventDefault()}>
<div className="flex items-center">
{loading ? <Loader className="mr-2 h-4 w-4" /> : <Share className="mr-2 h-4 w-4" />}
Share
</div>
</DropdownMenuItem>
2023-09-21 00:51:02 +00:00
)}
/>
2023-08-29 14:30:57 +10:00
</DropdownMenuContent>
2023-10-10 08:25:58 +05:30
{isDocumentDeletable && (
<DeleteDraftDocumentDialog
id={row.id}
open={isDeleteDialogOpen}
onOpenChange={setDeleteDialogOpen}
/>
)}
2023-11-08 09:25:44 +00:00
{isDuplicateDialogOpen && (
<DuplicateDocumentDialog
id={row.id}
open={isDuplicateDialogOpen}
onOpenChange={setDuplicateDialogOpen}
/>
)}
2023-08-29 14:30:57 +10:00
</DropdownMenu>
);
};