Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: user management table #1211

Draft
wants to merge 78 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
c94e30c
Basic component modeling and adding some style
russchristina Mar 25, 2024
9b60362
Some scaffolidng of basic table but not side panel; story for table i…
russchristina Apr 10, 2024
9cfa76f
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 10, 2024
a70843e
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 10, 2024
be541ae
define permission item
JoeKarow Apr 11, 2024
bb2fe46
add trpc api route & mock data
JoeKarow Apr 11, 2024
e55cca7
implement api in component & story
JoeKarow Apr 11, 2024
4172df5
remove old mock
JoeKarow Apr 11, 2024
05878a2
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 11, 2024
9fa0e14
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 11, 2024
4855295
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 11, 2024
4be2262
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 11, 2024
a2396f4
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 11, 2024
41cfdd3
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 11, 2024
8ab9da8
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 12, 2024
2f7addf
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 12, 2024
b68486b
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 15, 2024
4360e62
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 15, 2024
6054882
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 15, 2024
1a94a82
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 15, 2024
9a34c33
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 15, 2024
3193b46
remove overrides
JoeKarow Apr 15, 2024
0c2824c
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 15, 2024
750e854
Merge branch 'dev' into IN-857-user-management
JoeKarow Apr 15, 2024
08d0340
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 15, 2024
318907d
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 17, 2024
7179148
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 17, 2024
0b208f3
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 18, 2024
31cd00e
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 19, 2024
99d0866
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 19, 2024
5f2c7d3
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 20, 2024
ad1fcf2
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 22, 2024
49a96cf
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 22, 2024
6d548c8
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 22, 2024
ac0ab21
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 22, 2024
d7fd140
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 22, 2024
a75ddff
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 23, 2024
0306a56
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 23, 2024
a5eec53
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 23, 2024
60c379a
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 23, 2024
e273b7a
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 24, 2024
444e043
remove named import, default only
JoeKarow Apr 24, 2024
b1814c5
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 24, 2024
f70d183
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 24, 2024
ec64497
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 25, 2024
72a6fc0
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 25, 2024
ef3f7fa
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 26, 2024
467dbe0
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 26, 2024
5a2aeb0
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 29, 2024
fedf306
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 29, 2024
f8000ea
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] Apr 30, 2024
9211ca3
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 1, 2024
b65d1b1
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 2, 2024
81ff8cb
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 2, 2024
a9230db
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 3, 2024
0f024ba
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 3, 2024
e532d62
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 3, 2024
754d409
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 3, 2024
e30c725
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 6, 2024
81e5038
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 6, 2024
fb27790
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 6, 2024
2330ea5
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 6, 2024
4010821
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 7, 2024
84eef06
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 7, 2024
cac3afb
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 7, 2024
d676d9b
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 7, 2024
415baa2
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 9, 2024
85ddfe0
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 20, 2024
5493055
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 20, 2024
729fb7e
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 20, 2024
4d1df43
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 20, 2024
a59079d
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 20, 2024
d061607
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 21, 2024
f643fc1
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 22, 2024
848e5f0
Merge branch 'dev' into IN-857-user-management
JoeKarow May 28, 2024
46d52ff
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 28, 2024
4cfdd5b
Merge branch 'dev' into IN-857-user-management
JoeKarow May 29, 2024
1aa0bbb
Merge branch 'dev' into IN-857-user-management
kodiakhq[bot] May 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions apps/app/src/pages/admin/management.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ManagementTable } from '@weareinreach/ui/components/data-portal/ManagementTable'

export const Management = () => {
return <ManagementTable />
}

export default Management
1 change: 1 addition & 0 deletions apps/app/src/types/nextjs-routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ declare module "nextjs-routes" {
| StaticRoute<"/account/reviews">
| StaticRoute<"/account/saved">
| StaticRoute<"/admin">
| StaticRoute<"/admin/management">
| StaticRoute<"/admin/quicklink/email">
| StaticRoute<"/admin/quicklink">
| StaticRoute<"/admin/quicklink/phone">
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
"pnpm": {
"peerDependencyRules": {
"allowedVersions": {
"react": "18",
"react-dom": "18",
"typescript": "5",
"webpack": "5"
}
Expand Down
5 changes: 5 additions & 0 deletions packages/api/lib/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ const system = {
getDetails: ['dataPortalBasic'],
} satisfies PermissionDefs

const user = {
viewAllUsers: ['dataPortalAdmin'],
} satisfies PermissionDefs

const permissions = {
...locations,
...organizations,
Expand All @@ -77,6 +81,7 @@ const permissions = {
...orgWebsite,
...reviews,
...system,
...user,
} satisfies PermissionDefs

export const getPermissions = (procedure: PermissionedProcedure): { hasPerm: Permission | Permission[] } => ({
Expand Down
10 changes: 10 additions & 0 deletions packages/api/router/user/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
adminProcedure,
defineRouter,
importHandler,
permissionedProcedure,
protectedProcedure,
publicProcedure,
} from '~api/lib/trpc'
Expand Down Expand Up @@ -91,4 +92,13 @@ export const userRouter = defineRouter({
)
return handler({ input, ctx })
}),
forUserTable: permissionedProcedure('viewAllUsers')
.input(schema.ZForUserTableSchema)
.query(async (opts) => {
const handler = await importHandler(
namespaced('forUserTable'),
() => import('./query.forUserTable.handler')
)
return handler(opts)
}),
})
21 changes: 21 additions & 0 deletions packages/api/router/user/query.forUserTable.handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { prisma } from '@weareinreach/db'
import { type TRPCHandlerParams } from '~api/types/handler'

import { type TForUserTableSchema } from './query.forUserTable.schema'

const forUserTable = async ({ input }: TRPCHandlerParams<TForUserTableSchema>) => {
const userResults = await prisma.user.findMany({
where: input,
select: {
id: true,
name: true,
email: true,
active: true,
createdAt: true,
emailVerified: true,
updatedAt: true,
},
})
return userResults
}
export default forUserTable
9 changes: 9 additions & 0 deletions packages/api/router/user/query.forUserTable.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { z } from 'zod'

export const ZForUserTableSchema = z
.object({
active: z.boolean().default(true),
})
.partial()
.optional()
export type TForUserTableSchema = z.infer<typeof ZForUserTableSchema>
1 change: 1 addition & 0 deletions packages/api/router/user/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export * from './mutation.deleteAccount.schema'
export * from './mutation.forgotPassword.schema'
export * from './mutation.resetPassword.schema'
export * from './mutation.submitSurvey.schema'
export * from './query.forUserTable.schema'
// codegen:end
18 changes: 18 additions & 0 deletions packages/ui/components/data-portal/ManagementTable.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { type Meta, type StoryObj } from '@storybook/react'

import { user } from '~ui/mockData/user'

import { ManagementTable } from './ManagementTable'

export default {
title: 'Data Portal/Tables/User Management',
component: ManagementTable,
parameters: {
msw: [user.forUserTable],
rqDevtools: true,
},
} satisfies Meta<typeof ManagementTable>

type StoryDef = StoryObj<typeof ManagementTable>

export const Default = {} satisfies StoryDef
143 changes: 143 additions & 0 deletions packages/ui/components/data-portal/ManagementTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { Button, Group, NativeSelect, Stack, Text } from '@mantine/core'
import {
MantineReactTable,
type MRT_ColumnDef,
MRT_GlobalFilterTextInput,
type MRT_Icons,
MRT_TablePagination,
useMantineReactTable,
} from 'mantine-react-table'
import { useMemo } from 'react'

import { type ApiOutput } from '@weareinreach/api'
import { Icon } from '~ui/icon'
import { trpc as api } from '~ui/lib/trpcClient'

const customIcons: Partial<MRT_Icons> = {
IconSortAscending: () => <Icon icon={'carbon:chevron-up'} color='black' />,
IconSortDescending: () => <Icon icon={'carbon:chevron-down'} color='black' />,
}

export const ManagementTable = () => {
const { data: userData } = api.user.forUserTable.useQuery()

const columns = useMemo<MRT_ColumnDef<UserDataRecord>[]>(
() => [
{
accessorKey: 'name',
header: 'Name',
},
{
accessorKey: 'email',
header: 'Email',
},
{
accessorKey: 'emailVerified',
header: 'Email Verified',
Cell: ({ cell }) => {
const cellValue = cell.getValue()
if (cellValue instanceof Date) {
return cellValue.toISOString()
}
return null
},
},
{
accessorKey: 'updatedAt',
header: 'Last updated',
Cell: ({ cell }) => {
return cell.getValue<Date>().toISOString()
},
},
{
accessorKey: 'createdAt',
header: 'Created At',
Cell: ({ cell }) => {
return cell.getValue<Date>().toISOString()
},
},
{
accessorKey: 'active',
header: 'Active',
},
],
[]
)

const table = useMantineReactTable({
columns,
data: userData ?? [],
icons: customIcons,
enableGlobalFilter: true,
enableFilterMatchHighlighting: false,
positionGlobalFilter: 'left',
enableRowSelection: true,
mantineSearchTextInputProps: {
placeholder: 'Enter Name',
sx: { minWidth: '734px', height: '48px' },
},
initialState: {
showGlobalFilter: true,
},
enableTopToolbar: false,
enableBottomToolbar: false,
enablePagination: true,
mantinePaginationProps: {
withEdges: false,
siblings: 0,
showRowsPerPage: false,
},
paginationDisplayMode: 'pages',
layoutMode: 'semantic',
})

return (
<Stack>
<Text size='16px' fw={500} style={{ marginBottom: '-1rem' }}>
Total: {userData?.length ?? 0}
</Text>
<Group
noWrap={true}
position='left'
spacing={'16px'}
style={{
marginBottom: '4px',
}}
>
<MRT_GlobalFilterTextInput table={table} />
<NativeSelect
rightSection={<Icon icon='carbon:chevron-down' />}
data={['Data Entry Teams']}
styles={{
root: {
width: '208px',
height: '48px',
},
input: { paddingLeft: '16px', paddingRight: '16px', paddingTop: '12px', paddingBottom: '12px' },
}}
/>
<Button
styles={{
root: {
backgroundColor: 'inherit',
border: 'none',
width: '48px',
height: '48px',
padding: '12px',
marginTop: '10px',
},
label: { color: 'black' },
}}
>
<Icon icon='carbon:overflow-menu-horizontal' />
</Button>
</Group>
<Stack>
<MantineReactTable table={table} />
<MRT_TablePagination table={table} />
</Stack>
</Stack>
)
}

type UserDataRecord = NonNullable<ApiOutput['user']['forUserTable']>[number]
1 change: 1 addition & 0 deletions packages/ui/mockData/json/user.forUserTable.json

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions packages/ui/mockData/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,20 @@ export const user = {
return data
},
}),
forUserTable: getTRPCMock({
path: ['user', 'forUserTable'],
response: async (filterInput) => {
const data = (await import('./json/user.forUserTable.json')).default
const reformatted = data.map((item) => ({
...item,
createdAt: new Date(item.createdAt),
updatedAt: new Date(item.updatedAt),
...(item.emailVerified ? { emailVerified: new Date(item.emailVerified) } : { emailVerified: null }),
}))
if (filterInput?.active !== undefined) {
return reformatted.filter((item) => filterInput.active === item.active)
}
return reformatted
},
}),
} satisfies MockHandlerObject<'user'>