feat: stack recipients avatars on dashboard

This commit is contained in:
Ephraim Atta-Duncan
2023-06-23 12:20:49 +00:00
committed by Mythie
parent 12d8cebd4c
commit 00a15124be
5 changed files with 111 additions and 8 deletions

View File

@ -5,6 +5,7 @@ import { Clock, File, FileCheck } from 'lucide-react';
import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-session';
import { findDocuments } from '@documenso/lib/server-only/document/find-documents';
import { getStats } from '@documenso/lib/server-only/document/get-stats';
import { Recipient } from '@documenso/prisma/client';
import {
Table,
TableBody,
@ -14,12 +15,51 @@ import {
TableRow,
} from '@documenso/ui/primitives/table';
import { StackAvatar } from '~/components/(dashboard)/avatar';
import { CardMetric } from '~/components/(dashboard)/metric-card/metric-card';
import { DocumentStatus } from '~/components/formatter/document-status';
import { LocaleDate } from '~/components/formatter/locale-date';
import { UploadDocument } from './upload-document';
const renderStackAvatars = (recipients: Recipient[]) => {
const zIndex = 50;
const itemsToRender = recipients.slice(0, 5);
const remainingItems = recipients.length - itemsToRender.length;
return itemsToRender.map((recipient: Recipient, index: number) => {
const first = index === 0 ? true : false;
const initials =
recipient.name
?.split(' ')
.map((name: string) => name.slice(0, 1).toUpperCase())
.slice(0, 2)
.join('') ?? 'UK';
const lastItemText =
index === itemsToRender.length - 1 && remainingItems > 0
? `+${remainingItems + 1}`
: undefined;
const type =
recipient.sendStatus === 'SENT' && recipient.signingStatus === 'SIGNED'
? 'completed'
: recipient.sendStatus === 'SENT' && recipient.signingStatus === 'NOT_SIGNED'
? 'waiting'
: 'unsigned';
return (
<StackAvatar
key={recipient.id}
first={first}
zIndex={String(zIndex - index * 10)}
type={index === 4 ? 'unsigned' : type}
fallbackText={lastItemText ? lastItemText : initials}
/>
);
});
};
export default async function DashboardPage() {
const session = await getRequiredServerComponentSession();
@ -60,6 +100,7 @@ export default async function DashboardPage() {
<TableRow>
<TableHead className="w-[100px]">ID</TableHead>
<TableHead>Title</TableHead>
<TableHead>Reciepient</TableHead>
<TableHead>Status</TableHead>
<TableHead className="text-right">Created</TableHead>
</TableRow>
@ -76,6 +117,11 @@ export default async function DashboardPage() {
{document.title}
</Link>
</TableCell>
<TableCell className="flex cursor-pointer">
{renderStackAvatars(document.Recipient)}
</TableCell>
<TableCell>
<DocumentStatus status={document.status} />
</TableCell>

View File

@ -0,0 +1,36 @@
import { Avatar, AvatarFallback } from '@documenso/ui/primitives/avatar';
export type StackAvatarProps = {
first?: boolean;
zIndex?: string;
fallbackText?: string;
type: 'unsigned' | 'waiting' | 'completed';
};
export const StackAvatar = ({ first, zIndex, fallbackText, type }: StackAvatarProps) => {
let classes = '';
switch (type) {
case 'unsigned':
classes = 'bg-dawn-400 text-dawn-900';
break;
case 'waiting':
classes = 'bg-water text-water-700';
break;
case 'completed':
classes = 'bg-documenso-200 text-documenso-800';
break;
default:
break;
}
return (
<Avatar
className={`
${zIndex && `z-${zIndex}`}
${!first && '-ml-3'}
h-10 w-10 border-2 border-solid border-white `}
>
<AvatarFallback className={classes}>{fallbackText ?? 'UK'}</AvatarFallback>
</Avatar>
);
};

View File

@ -1,5 +1,5 @@
import { prisma } from '@documenso/prisma';
import { Document, DocumentStatus, Prisma } from '@documenso/prisma/client';
import { Document, DocumentStatus, Prisma, Recipient } from '@documenso/prisma/client';
import { FindResultSet } from '../../types/find-result-set';
@ -15,6 +15,10 @@ export interface FindDocumentsOptions {
};
}
export type DocumentWithReciepient = Document & {
Recipient: Recipient[];
};
export const findDocuments = async ({
userId,
term,
@ -22,7 +26,7 @@ export const findDocuments = async ({
page = 1,
perPage = 10,
orderBy,
}: FindDocumentsOptions): Promise<FindResultSet<Document>> => {
}: FindDocumentsOptions): Promise<FindResultSet<DocumentWithReciepient>> => {
const orderByColumn = orderBy?.column ?? 'created';
const orderByDirection = orderBy?.direction ?? 'desc';
@ -48,6 +52,9 @@ export const findDocuments = async ({
orderBy: {
[orderByColumn]: orderByDirection,
},
include: {
Recipient: true,
},
}),
prisma.document.count({
where: {

View File

@ -1,6 +1,6 @@
generator client {
provider = "prisma-client-js"
previewFeatures = ["extendedWhereUnique", "jsonProtocol"]
provider = "prisma-client-js"
previewFeatures = ["extendedWhereUnique"]
}
datasource db {
@ -144,10 +144,10 @@ model Field {
recipientId Int?
type FieldType
page Int
positionX Decimal @default(0)
positionY Decimal @default(0)
width Decimal @default(-1)
height Decimal @default(-1)
positionX Decimal @default(0)
positionY Decimal @default(0)
width Decimal @default(-1)
height Decimal @default(-1)
customText String
inserted Boolean
Document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)

View File

@ -76,6 +76,20 @@ module.exports = {
900: '#52514a',
950: '#2a2925',
},
water: {
DEFAULT: '#d7e4f3',
50: '#f3f6fb',
100: '#e3ebf6',
200: '#d7e4f3',
300: '#abc7e5',
400: '#82abd8',
500: '#658ecc',
600: '#5175bf',
700: '#4764ae',
800: '#3e538f',
900: '#364772',
950: '#252d46',
},
},
backgroundImage: {
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',