@damourlabs/euro-clinical-trials
Version:
A Nuxt 3 application for visualizing and managing clinical trials data in Europe, built with modern web technologies.
183 lines (175 loc) • 6.49 kB
text/typescript
import { h } from 'vue'
import type { ColumnDef } from '@tanstack/vue-table'
import type { User, Trial, Site } from '~/server/database/schema';
import { SiteDataTableDropDown } from '~/components/site'
import {
StatusBadge,
FieldDate,
GenericCompactCard
} from '~/components/common/field'
import SimplePercentage from '~/components/common/field/SimplePercentage.vue'
import { getHeaderClasses, getCellClasses, createResponsiveColumn } from '~/utils/table-helpers'
async function fetchTrial(_uuid: string) {
const trial = useTrialsStore().getById(_uuid)
if (trial === undefined) {
throw createError(`Trial with UUID ${_uuid} not found`)
}
return trial
}
async function fetchUser(_uuid: string) {
const user = useUsersStore().getById(_uuid)
if (user === undefined) {
throw createError(`User with UUID ${_uuid} not found`)
}
return user
}
export const SITE_COLUMNS: ColumnDef<Site>[] = [
createResponsiveColumn({
accessorKey: 'uuid',
header: () => h('div', { class: getHeaderClasses('right') }, 'Site UUID'),
cell: ({ row }) => {
const site = row.original
return h('div', { class: getCellClasses('right') },
h(GenericCompactCard<Site>, {
entityUuid: site.uuid,
entityType: 'site',
fetchFunction: () => Promise.resolve(site),
titleField: 'name',
subtitleField: 'address',
statusField: 'status',
colorScheme: 'green'
})
)
},
}, { hideOnMobile: true }),
{
accessorKey: 'name',
header: () => h('div', { class: getHeaderClasses('center') }, 'Site Name'),
cell: ({ row }) => {
const site = row.original
return h('div', { class: getCellClasses('center') + ' font-medium' }, site.name)
}
},
{
accessorKey: 'trialUuid',
header: () => h('div', { class: getHeaderClasses('center') }, 'Trial'),
cell: ({ row }) => {
const site = row.original
return h(GenericCompactCard<Trial>, {
entityUuid: site.trialUuid,
entityType: 'trial',
fetchFunction: fetchTrial,
titleField: 'title',
subtitleField: 'indication',
statusField: 'status',
colorScheme: 'blue'
})
}
},
createResponsiveColumn({
accessorKey: 'address',
header: () => h('div', { class: getHeaderClasses('center') }, 'Location'),
cell: ({ row }) => {
const site = row.original
return h('div', { class: getCellClasses('center') }, site.address)
}
}, { hideOnMobile: true }),
{
accessorKey: 'patientsEnrolled',
header: () => h('div', { class: getHeaderClasses('center') }, 'Patients Enrolled'),
cell: ({ row }) => {
const site = row.original
return h('div', { class: getCellClasses('center') + ' font-medium' }, site.patientsEnrolled)
}
},
{
accessorKey: 'dataCompleteness',
header: () => h('div', { class: getHeaderClasses('right') }, 'Data Completeness'),
cell: ({ row }) => {
const site = row.original
return h('div', { class: getCellClasses('right') },
h(SimplePercentage, {
value: site.dataCompleteness,
align: 'right'
})
)
}
},
createResponsiveColumn({
accessorKey: 'status',
header: () => h('div', { class: getHeaderClasses('center') }, 'Status'),
cell: ({ row }) => {
const site = row.original
return h('div', { class: getCellClasses('center') },
h(StatusBadge, {
status: site.status,
type: 'site'
})
)
}
}, { hideOnMobile: true }),
createResponsiveColumn({
accessorKey: 'activationDate',
header: () => h('div', { class: getHeaderClasses('right') }, 'Activation Date'),
cell: ({ row }) => {
const site = row.original
return h('div', { class: getCellClasses('right') },
h(FieldDate, {
date: site.activationDate,
format: 'short',
align: 'right'
})
)
}
}, { hideOnTablet: true }),
createResponsiveColumn({
accessorKey: 'contactPersonUuid',
header: () => h('div', { class: getHeaderClasses('center') }, 'Contact Person'),
cell: ({ row }) => {
const site = row.original
if (!site.contactPersonUuid) {
return h('div', { class: getCellClasses('center') + ' text-gray-500' }, 'N/A')
}
return h(GenericCompactCard<User>, {
entityUuid: site.contactPersonUuid,
entityType: 'user',
fetchFunction: fetchUser,
titleField: 'name',
subtitleField: 'email',
statusField: 'role',
colorScheme: 'purple'
})
},
enableHiding: true,
meta: { defaultHidden: true }
}, { hideOnMobile: true }),
createResponsiveColumn({
accessorKey: 'principalInvestigatorUuid',
header: () => h('div', { class: getHeaderClasses('center') }, 'Principal Investigator'),
cell: ({ row }) => {
const site = row.original
if (!site.principalInvestigatorUuid) {
return h('div', { class: getCellClasses('center') + ' text-gray-500' }, 'N/A')
}
return h(GenericCompactCard<User>, {
entityUuid: site.principalInvestigatorUuid,
entityType: 'user',
fetchFunction: fetchUser,
titleField: 'name',
subtitleField: 'email',
statusField: 'role',
colorScheme: 'orange'
})
},
enableHiding: true,
meta: { defaultHidden: true }
}, { hideOnMobile: true }),
{
id: 'actions',
enableHiding: false,
cell: ({ row }) => {
const site = row.original
return h(SiteDataTableDropDown, { siteId: site.uuid })
}
}
]