diff --git a/apps/web/src/routes/_app/admin/groups/index.tsx b/apps/web/src/routes/_app/admin/groups/index.tsx index b0e1d07ce..20a933ded 100644 --- a/apps/web/src/routes/_app/admin/groups/index.tsx +++ b/apps/web/src/routes/_app/admin/groups/index.tsx @@ -1,6 +1,6 @@ import { useState } from 'react'; -import { Button, ClientTable, Heading, SearchBar, Sheet } from '@douglasneuroinformatics/libui/components'; +import { Button, DataTable, Heading, Sheet } from '@douglasneuroinformatics/libui/components'; import { useTranslation } from '@douglasneuroinformatics/libui/hooks'; import type { Group } from '@opendatacapture/schemas/group'; import { createFileRoute, Link } from '@tanstack/react-router'; @@ -8,14 +8,12 @@ import { createFileRoute, Link } from '@tanstack/react-router'; import { PageHeader } from '@/components/PageHeader'; import { useDeleteGroupMutation } from '@/hooks/useDeleteGroupMutation'; import { groupsQueryOptions, useGroupsQuery } from '@/hooks/useGroupsQuery'; -import { useSearch } from '@/hooks/useSearch'; const RouteComponent = () => { const { t } = useTranslation(); const groupsQuery = useGroupsQuery(); const deleteGroupMutation = useDeleteGroupMutation(); const [selectedGroup, setSelectedGroup] = useState(null); - const { filteredData, searchTerm, setSearchTerm } = useSearch(groupsQuery.data ?? [], 'name'); return ( setSelectedGroup(null)}> @@ -27,33 +25,16 @@ const RouteComponent = () => { })} -
- - -
- + { + accessorKey: 'type', + cell: (ctx) => { + const type = ctx.getValue() as Group['type']; if (type === 'CLINICAL') { return t('common.clinical'); } else if (type === 'RESEARCH') { @@ -61,13 +42,26 @@ const RouteComponent = () => { } return type satisfies never; }, - label: t('common.groupType') + header: t('common.groupType') } ]} - data={filteredData} - entriesPerPage={15} - minRows={15} - onEntryClick={setSelectedGroup} + data={groupsQuery.data} + rowActions={[ + { + label: t('common.manage'), + onSelect: setSelectedGroup + } + ]} + togglesComponent={() => ( + + )} /> diff --git a/apps/web/src/routes/_app/admin/users/index.tsx b/apps/web/src/routes/_app/admin/users/index.tsx index 6965b13e5..d375b9108 100644 --- a/apps/web/src/routes/_app/admin/users/index.tsx +++ b/apps/web/src/routes/_app/admin/users/index.tsx @@ -2,15 +2,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import { isAllUndefined, snakeToCamelCase } from '@douglasneuroinformatics/libjs'; import { estimatePasswordStrength } from '@douglasneuroinformatics/libpasswd'; -import { - Button, - ClientTable, - Dialog, - Form, - Heading, - SearchBar, - Sheet -} from '@douglasneuroinformatics/libui/components'; +import { Button, DataTable, Dialog, Form, Heading, Sheet } from '@douglasneuroinformatics/libui/components'; import { useTranslation } from '@douglasneuroinformatics/libui/hooks'; import type { FormTypes } from '@opendatacapture/runtime-core'; import { $UserPermission } from '@opendatacapture/schemas/core'; @@ -24,7 +16,6 @@ import { PageHeader } from '@/components/PageHeader'; import { WithFallback } from '@/components/WithFallback'; import { useDeleteUserMutation } from '@/hooks/useDeleteUserMutation'; import { groupsQueryOptions, useGroupsQuery } from '@/hooks/useGroupsQuery'; -import { useSearch } from '@/hooks/useSearch'; import { useUpdateUserMutation } from '@/hooks/useUpdateUserMutation'; import { usersQueryOptions, useUsersQuery } from '@/hooks/useUsersQuery'; import { useAppStore } from '@/store'; @@ -276,7 +267,6 @@ const RouteComponent = () => { const deleteUserMutation = useDeleteUserMutation(); const updateUserMutation = useUpdateUserMutation(); const [selectedUser, setSelectedUser] = useState(null); - const { filteredData, searchTerm, setSearchTerm } = useSearch(usersQuery.data ?? [], 'username'); const [data, setData] = useState(null); @@ -307,34 +297,16 @@ const RouteComponent = () => { })} -
- - -
- + { + accessorKey: 'basePermissionLevel', + cell: (ctx) => { + const basePermissionLevel = ctx.getValue() as User['basePermissionLevel']; if (!basePermissionLevel) { return t({ en: 'None', @@ -343,14 +315,27 @@ const RouteComponent = () => { } return t(`common.${snakeToCamelCase(basePermissionLevel)}`); }, - label: t('common.basePermissionLevel') + header: t('common.basePermissionLevel') } ]} - data={filteredData} + data={usersQuery.data} data-testid="admin-users-table" - entriesPerPage={15} - minRows={15} - onEntryClick={setSelectedUser} + rowActions={[ + { + label: t('common.manage'), + onSelect: setSelectedUser + } + ]} + togglesComponent={() => ( + + )} /> diff --git a/apps/web/src/routes/_app/datahub/index.tsx b/apps/web/src/routes/_app/datahub/index.tsx index 4a813e689..74cfa9656 100644 --- a/apps/web/src/routes/_app/datahub/index.tsx +++ b/apps/web/src/routes/_app/datahub/index.tsx @@ -41,7 +41,7 @@ const Filters: React.FC<{ table: TanstackTable.Table }> = ({ table }) = const columns = table.getAllColumns(); - const dobColumn = columns.find((column) => column.id === 'date-of-birth')!; + const dobColumn = columns.find((column) => column.id === 'dateOfBirth')!; const dobFilter = dobColumn.getFilterValue() as DateFilter; const sexColumn = columns.find((column) => column.id === 'sex')!; @@ -311,7 +311,7 @@ const MasterDataTable: React.FC<{ id: 'subjectId' }, { - accessorFn: (subject) => subject.dateOfBirth, + accessorKey: 'dateOfBirth', cell: (ctx) => { const value = ctx.getValue() as Date | null | undefined; return value ? toBasicISOString(value) : 'NULL'; @@ -327,8 +327,7 @@ const MasterDataTable: React.FC<{ } return true; }, - header: t('core.identificationData.dateOfBirth.label'), - id: 'date-of-birth' + header: t('core.identificationData.dateOfBirth.label') }, { accessorFn: (subject) => subject.sex ?? null, @@ -358,7 +357,7 @@ const MasterDataTable: React.FC<{ value: ['MALE', 'FEMALE', null] satisfies SexFilter }, { - id: 'date-of-birth', + id: 'dateOfBirth', value: { allowNull: true, max: null, diff --git a/apps/web/src/translations/common.json b/apps/web/src/translations/common.json index 1a0c68248..6e7025669 100644 --- a/apps/web/src/translations/common.json +++ b/apps/web/src/translations/common.json @@ -77,6 +77,10 @@ "en": "Insufficient password strength", "fr": "Mot de passe trop faible" }, + "manage": { + "en": "Manage", + "fr": "Gérer" + }, "method": { "en": "Method", "fr": "Méthode" @@ -85,6 +89,10 @@ "en": "Password", "fr": "Mot de passe" }, + "passwordsMustMatch": { + "en": "Passwords Must Match", + "fr": "Les mots de passe doivent correspondre" + }, "personalInfo": { "en": "Personal Information", "fr": "Renseignements personnels" @@ -101,10 +109,6 @@ "en": "Standard", "fr": "Standard" }, - "passwordsMustMatch": { - "en": "Passwords Must Match", - "fr": "Les mots de passe doivent correspondre" - }, "subjectIdentification": { "description": { "en": "The following items are used to compute a unique identifier that enables consistent cross-session identification.", @@ -154,5 +158,9 @@ "usernameExists": { "en": "Username already exists", "fr": "Le nom d'utilisateur existe déjà" + }, + "view": { + "en": "View", + "fr": "Voir" } } diff --git a/apps/web/src/translations/layout.json b/apps/web/src/translations/layout.json index 9c7192c22..194d3966a 100644 --- a/apps/web/src/translations/layout.json +++ b/apps/web/src/translations/layout.json @@ -50,10 +50,6 @@ "en": "Data Hub", "fr": "Centre de données" }, - "upload": { - "en": "Upload Data", - "fr": "Téléverser les données" - }, "endSession": { "en": "End Current Session", "fr": "Terminer la session en cours" @@ -66,6 +62,10 @@ "en": "Start Session", "fr": "Commencer une session" }, + "upload": { + "en": "Upload Data", + "fr": "Téléverser les données" + }, "viewCurrentSubject": { "en": "View Current Subject", "fr": "Voir le client actuel"