fix: fixed the recipients viewing issue on touch screens

This commit is contained in:
Ashraf
2023-12-20 17:08:09 +08:00
parent ff64671e49
commit 2a448fe06d
5 changed files with 127 additions and 106 deletions

View File

@ -11,7 +11,7 @@ import { DocumentStatus as InternalDocumentStatus } from '@documenso/prisma/clie
import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer';
import { EditDocumentForm } from '~/app/(dashboard)/documents/[id]/edit-document';
import { StackAvatarsWithTooltip } from '~/components/(dashboard)/avatar/stack-avatars-with-tooltip';
import { StackAvatarsWithUI } from '~/components/(dashboard)/avatar/stack-avatars-with-ui';
import { DocumentStatus } from '~/components/formatter/document-status';
export type DocumentPageProps = {
@ -71,9 +71,9 @@ export default async function DocumentPage({ params }: DocumentPageProps) {
<div className="text-muted-foreground flex items-center">
<Users2 className="mr-2 h-5 w-5" />
<StackAvatarsWithTooltip recipients={recipients} position="bottom">
<StackAvatarsWithUI recipients={recipients} position="bottom">
<span>{recipients.length} Recipient(s)</span>
</StackAvatarsWithTooltip>
</StackAvatarsWithUI>
</div>
)}
</div>

View File

@ -12,7 +12,7 @@ import { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-documen
import { DataTable } from '@documenso/ui/primitives/data-table';
import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination';
import { StackAvatarsWithTooltip } from '~/components/(dashboard)/avatar/stack-avatars-with-tooltip';
import { StackAvatarsWithUI } from '~/components/(dashboard)/avatar/stack-avatars-with-ui';
import { DocumentStatus } from '~/components/formatter/document-status';
import { LocaleDate } from '~/components/formatter/locale-date';
@ -64,9 +64,7 @@ export const DocumentsDataTable = ({ results }: DocumentsDataTableProps) => {
{
header: 'Recipient',
accessorKey: 'recipient',
cell: ({ row }) => {
return <StackAvatarsWithTooltip recipients={row.original.Recipient} />;
},
cell: ({ row }) => <StackAvatarsWithUI recipients={row.original.Recipient} />,
},
{
header: 'Status',

View File

@ -0,0 +1,71 @@
import { getRecipientType } from '@documenso/lib/client-only/recipient-type';
import { recipientAbbreviation } from '@documenso/lib/utils/recipient-formatter';
import type { Recipient } from '@documenso/prisma/client';
import { AvatarWithRecipient } from './avatar-with-recipient';
import { StackAvatar } from './stack-avatar';
export const StackAvatarsComponent = ({ recipients }: { recipients: Recipient[] }) => {
const waitingRecipients = recipients.filter(
(recipient) => getRecipientType(recipient) === 'waiting',
);
const openedRecipients = recipients.filter(
(recipient) => getRecipientType(recipient) === 'opened',
);
const completedRecipients = recipients.filter(
(recipient) => getRecipientType(recipient) === 'completed',
);
const uncompletedRecipients = recipients.filter(
(recipient) => getRecipientType(recipient) === 'unsigned',
);
return (
<div className="flex flex-col gap-y-5 px-1">
{completedRecipients.length > 0 && (
<div>
<h1 className="text-base font-medium">Completed</h1>
{completedRecipients.map((recipient: Recipient) => (
<div key={recipient.id} className="my-1 flex items-center gap-2">
<StackAvatar
first={true}
key={recipient.id}
type={getRecipientType(recipient)}
fallbackText={recipientAbbreviation(recipient)}
/>
<span className="text-muted-foreground text-sm">{recipient.email}</span>
</div>
))}
</div>
)}
{waitingRecipients.length > 0 && (
<div>
<h1 className="text-base font-medium">Waiting</h1>
{waitingRecipients.map((recipient: Recipient) => (
<AvatarWithRecipient key={recipient.id} recipient={recipient} />
))}
</div>
)}
{openedRecipients.length > 0 && (
<div>
<h1 className="text-base font-medium">Opened</h1>
{openedRecipients.map((recipient: Recipient) => (
<AvatarWithRecipient key={recipient.id} recipient={recipient} />
))}
</div>
)}
{uncompletedRecipients.length > 0 && (
<div>
<h1 className="text-base font-medium">Uncompleted</h1>
{uncompletedRecipients.map((recipient: Recipient) => (
<AvatarWithRecipient key={recipient.id} recipient={recipient} />
))}
</div>
)}
</div>
);
};

View File

@ -1,99 +0,0 @@
import { getRecipientType } from '@documenso/lib/client-only/recipient-type';
import { recipientAbbreviation } from '@documenso/lib/utils/recipient-formatter';
import type { Recipient } from '@documenso/prisma/client';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@documenso/ui/primitives/tooltip';
import { AvatarWithRecipient } from './avatar-with-recipient';
import { StackAvatar } from './stack-avatar';
import { StackAvatars } from './stack-avatars';
export type StackAvatarsWithTooltipProps = {
recipients: Recipient[];
position?: 'top' | 'bottom';
children?: React.ReactNode;
};
export const StackAvatarsWithTooltip = ({
recipients,
position,
children,
}: StackAvatarsWithTooltipProps) => {
const waitingRecipients = recipients.filter(
(recipient) => getRecipientType(recipient) === 'waiting',
);
const openedRecipients = recipients.filter(
(recipient) => getRecipientType(recipient) === 'opened',
);
const completedRecipients = recipients.filter(
(recipient) => getRecipientType(recipient) === 'completed',
);
const uncompletedRecipients = recipients.filter(
(recipient) => getRecipientType(recipient) === 'unsigned',
);
return (
<TooltipProvider>
<Tooltip delayDuration={200}>
<TooltipTrigger className="flex cursor-pointer">
{children || <StackAvatars recipients={recipients} />}
</TooltipTrigger>
<TooltipContent side={position}>
<div className="flex flex-col gap-y-5 p-1">
{completedRecipients.length > 0 && (
<div>
<h1 className="text-base font-medium">Completed</h1>
{completedRecipients.map((recipient: Recipient) => (
<div key={recipient.id} className="my-1 flex items-center gap-2">
<StackAvatar
first={true}
key={recipient.id}
type={getRecipientType(recipient)}
fallbackText={recipientAbbreviation(recipient)}
/>
<span className="text-muted-foreground text-sm">{recipient.email}</span>
</div>
))}
</div>
)}
{waitingRecipients.length > 0 && (
<div>
<h1 className="text-base font-medium">Waiting</h1>
{waitingRecipients.map((recipient: Recipient) => (
<AvatarWithRecipient key={recipient.id} recipient={recipient} />
))}
</div>
)}
{openedRecipients.length > 0 && (
<div>
<h1 className="text-base font-medium">Opened</h1>
{openedRecipients.map((recipient: Recipient) => (
<AvatarWithRecipient key={recipient.id} recipient={recipient} />
))}
</div>
)}
{uncompletedRecipients.length > 0 && (
<div>
<h1 className="text-base font-medium">Uncompleted</h1>
{uncompletedRecipients.map((recipient: Recipient) => (
<AvatarWithRecipient key={recipient.id} recipient={recipient} />
))}
</div>
)}
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
};

View File

@ -0,0 +1,51 @@
'use client';
import { useWindowSize } from '@documenso/lib/client-only/hooks/use-window-size';
import type { Recipient } from '@documenso/prisma/client';
import { Popover, PopoverContent, PopoverTrigger } from '@documenso/ui/primitives/popover';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@documenso/ui/primitives/tooltip';
import { StackAvatars } from './stack-avatars';
import { StackAvatarsComponent } from './stack-avatars-component';
export type StackAvatarsWithUIProps = {
recipients: Recipient[];
position?: 'top' | 'bottom';
children?: React.ReactNode;
};
export const StackAvatarsWithUI = ({ recipients, position, children }: StackAvatarsWithUIProps) => {
const size = useWindowSize();
return (
<>
{size.width > 1050 ? (
<TooltipProvider>
<Tooltip delayDuration={200}>
<TooltipTrigger className="flex cursor-pointer">
{children || <StackAvatars recipients={recipients} />}
</TooltipTrigger>
<TooltipContent side={position}>
<StackAvatarsComponent recipients={recipients} />
</TooltipContent>
</Tooltip>
</TooltipProvider>
) : (
<Popover>
<PopoverTrigger className="flex cursor-pointer">
{children || <StackAvatars recipients={recipients} />}
</PopoverTrigger>
<PopoverContent side={position}>
<StackAvatarsComponent recipients={recipients} />
</PopoverContent>
</Popover>
)}
</>
);
};