-
Notifications
You must be signed in to change notification settings - Fork 118
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Members list and Invite list, new shadcn components (no styles)
- Loading branch information
1 parent
5393289
commit 9ffc66b
Showing
24 changed files
with
1,775 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
174 changes: 174 additions & 0 deletions
174
apps/web/src/app/[orgShortCode]/settings/org/users/invites/_components/columns.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
'use client'; | ||
|
||
import { createColumnHelper, type ColumnDef } from '@tanstack/react-table'; | ||
import type { RouterOutputs } from '@/src/lib/trpc'; | ||
import { generateAvatarUrl, getInitials } from '@/src/lib/utils'; | ||
import { | ||
Avatar, | ||
AvatarFallback, | ||
AvatarImage | ||
} from '@/src/components/shadcn-ui/avatar'; | ||
import { Badge } from '@/src/components/shadcn-ui/badge'; | ||
import { format } from 'date-fns'; | ||
import { ScrollArea } from '@radix-ui/themes'; | ||
import { Tooltip } from '@radix-ui/themes'; | ||
import CopyButton from '@/src/components/copy-button'; | ||
import { env } from 'next-runtime-env'; | ||
|
||
const WEBAPP_URL = env('NEXT_PUBLIC_WEBAPP_URL'); | ||
|
||
type Member = | ||
RouterOutputs['org']['users']['invites']['viewInvites']['invites'][number]; | ||
|
||
const columnHelper = createColumnHelper<Member>(); | ||
|
||
export const columns: ColumnDef<Member>[] = [ | ||
columnHelper.display({ | ||
id: 'status', | ||
header: 'Status', | ||
cell: ({ row }) => ( | ||
<div className="flex h-full w-full items-center"> | ||
<Badge className="uppercase"> | ||
{row.original.acceptedAt ? 'Used' : 'Pending'} | ||
</Badge> | ||
</div> | ||
) | ||
}), | ||
columnHelper.display({ | ||
id: 'user', | ||
header: 'User', | ||
cell: ({ row }) => { | ||
const { publicId, avatarTimestamp, firstName, lastName } = | ||
row.original.orgMember?.profile ?? {}; | ||
|
||
const avatarUrl = | ||
avatarTimestamp && publicId | ||
? generateAvatarUrl({ | ||
avatarTimestamp, | ||
publicId, | ||
size: 'lg' | ||
}) | ||
: null; | ||
const initials = getInitials(`${firstName} ${lastName}`); | ||
return ( | ||
<div className="flex items-center gap-2"> | ||
<Avatar className="h-8 w-8"> | ||
<AvatarImage | ||
src={avatarUrl ?? undefined} | ||
alt={firstName ?? ''} | ||
/> | ||
<AvatarFallback>{initials}</AvatarFallback> | ||
</Avatar> | ||
<span> | ||
{firstName} {lastName} | ||
</span> | ||
</div> | ||
); | ||
} | ||
}), | ||
columnHelper.display({ | ||
id: 'invite-code', | ||
header: 'Invite Code', | ||
cell: ({ row }) => { | ||
const inviteCode = row.original.inviteToken; | ||
return inviteCode ? ( | ||
<div className="flex w-fit items-center justify-between gap-2"> | ||
<ScrollArea | ||
scrollbars="horizontal" | ||
className="w-32" | ||
type="hover"> | ||
<span>{inviteCode}</span> | ||
</ScrollArea> | ||
<CopyButton | ||
text={inviteCode} | ||
size={12} | ||
/> | ||
</div> | ||
) : null; | ||
} | ||
}), | ||
columnHelper.display({ | ||
id: 'invite-link', | ||
header: 'Invite Link', | ||
cell: ({ row }) => { | ||
const inviteCode = row.original.inviteToken; | ||
return inviteCode ? ( | ||
<div className="flex w-fit items-center justify-between gap-2"> | ||
<ScrollArea | ||
scrollbars="horizontal" | ||
className="w-32" | ||
type="hover"> | ||
<span>{`${WEBAPP_URL}/join/invite/${inviteCode}`}</span> | ||
</ScrollArea> | ||
<CopyButton | ||
text={`${WEBAPP_URL}/join/invite/${inviteCode}`} | ||
size={12} | ||
/> | ||
</div> | ||
) : null; | ||
} | ||
}), | ||
columnHelper.display({ | ||
id: 'email', | ||
header: 'Email', | ||
cell: ({ row }) => { | ||
const email = row.original.email; | ||
return <div className="flex h-full items-center">{email}</div>; | ||
} | ||
}), | ||
columnHelper.display({ | ||
id: 'role', | ||
header: 'Role', | ||
cell: ({ row }) => { | ||
const role = row.original.role; | ||
return ( | ||
<div className="flex h-full items-center"> | ||
<Badge className="uppercase">{role}</Badge> | ||
</div> | ||
); | ||
} | ||
}), | ||
columnHelper.display({ | ||
id: 'admin', | ||
header: 'Admin', | ||
cell: ({ row }) => { | ||
const { publicId, avatarTimestamp, firstName, lastName } = | ||
row.original.invitedByOrgMember.profile; | ||
|
||
const avatarUrl = | ||
avatarTimestamp && publicId | ||
? generateAvatarUrl({ | ||
avatarTimestamp, | ||
publicId, | ||
size: 'lg' | ||
}) | ||
: null; | ||
const initials = getInitials(`${firstName} ${lastName}`); | ||
return ( | ||
<div className="flex items-center justify-center gap-2"> | ||
<Tooltip content={`${firstName} ${lastName}`}> | ||
<Avatar className="h-8 w-8"> | ||
<AvatarImage | ||
src={avatarUrl ?? undefined} | ||
alt={firstName ?? ''} | ||
/> | ||
<AvatarFallback>{initials}</AvatarFallback> | ||
</Avatar> | ||
</Tooltip> | ||
</div> | ||
); | ||
} | ||
}), | ||
columnHelper.display({ | ||
id: 'expiry', | ||
header: 'Expiry', | ||
cell: ({ row }) => { | ||
const expiry = row.original.expiresAt; | ||
return expiry ? ( | ||
<div className="flex h-full items-center"> | ||
{format(expiry, 'eee, do MMM yyyy')} | ||
</div> | ||
) : null; | ||
} | ||
}) | ||
]; |
Oops, something went wrong.