@damourlabs/euro-clinical-trials
Version:
A Nuxt 3 application for visualizing and managing clinical trials data in Europe, built with modern web technologies.
150 lines (134 loc) • 5.42 kB
text/typescript
import { h } from 'vue'
import type { ColumnDef } from '@tanstack/vue-table'
import type { Trial, RegulatoryApproval } from '~/server/database/schema';
import {
StatusBadge,
FieldDate,
GenericCompactCard
} from '~/components/common/field'
import { getHeaderClasses, getCellClasses, createResponsiveColumn } from '~/utils/table-helpers'
import RegulatoryApprovalCard from '~/components/regulatory-approval/RegulatoryApprovalCard.vue'
async function fetchTrial(_uuid: string) {
const trial = useTrialsStore().getById(_uuid)
if (trial === undefined) {
throw createError(`Trial with UUID ${_uuid} not found`)
}
return trial
}
export const REGULATORY_APPROVAL_COLUMNS: ColumnDef<RegulatoryApproval>[] = [
createResponsiveColumn({
accessorKey: 'uuid',
header: () => h('div', { class: getHeaderClasses('right') }, 'Approval ID'),
cell: ({ row }) => {
const approval = row.original
return h('div', { class: getCellClasses('right') },
h(RegulatoryApprovalCard, {
approval,
size: 'micro'
})
)
},
}),
createResponsiveColumn({
accessorKey: 'approvalType',
header: () => h('div', { class: getHeaderClasses('center') }, 'Type'),
cell: ({ row }) => {
const approvalType = row.getValue('approvalType') as string
return h('div', { class: getCellClasses('center') },
h(StatusBadge, { status: approvalType })
)
},
}),
createResponsiveColumn({
accessorKey: 'status',
header: () => h('div', { class: getHeaderClasses('center') }, 'Status'),
cell: ({ row }) => {
const status = row.getValue('status') as string
const statusVariant = getStatusVariant(status)
return h('div', { class: getCellClasses('center') },
h(StatusBadge, {
status,
variant: statusVariant
})
)
},
}),
createResponsiveColumn({
accessorKey: 'authority',
header: () => h('div', { class: getHeaderClasses() }, 'Authority'),
cell: ({ row }) => {
const authority = row.getValue('authority') as string
const truncated = authority.length > 40 ? authority.substring(0, 40) + '...' : authority
return h('div', { class: getCellClasses() + ' font-medium', title: authority }, truncated)
},
}),
createResponsiveColumn({
accessorKey: 'approvalDate',
header: () => h('div', { class: getHeaderClasses('center') }, 'Approval Date'),
cell: ({ row }) => {
const approvalDate = row.getValue('approvalDate') as string | null
if (!approvalDate) {
return h('div', { class: getCellClasses('center') + ' text-gray-400' }, 'Not set')
}
return h('div', { class: getCellClasses('center') },
h(FieldDate, { date: approvalDate })
)
},
}),
createResponsiveColumn({
accessorKey: 'expiryDate',
header: () => h('div', { class: getHeaderClasses('center') }, 'Expiry Date'),
cell: ({ row }) => {
const expiryDate = row.getValue('expiryDate') as string | null
if (!expiryDate) {
return h('div', { class: getCellClasses('center') + ' text-gray-400' }, 'No expiry')
}
const isExpired = new Date(expiryDate) < new Date()
const isExpiringSoon = new Date(expiryDate) < new Date(Date.now() + 30 * 24 * 60 * 60 * 1000) // 30 days
return h('div', {
class: getCellClasses('center') + (isExpired ? ' text-red-600' : isExpiringSoon ? ' text-orange-600' : '')
},
h(FieldDate, { date: expiryDate })
)
},
}),
createResponsiveColumn({
accessorKey: 'trialUuid',
header: () => h('div', { class: getHeaderClasses('center') }, 'Trial'),
cell: ({ row }) => {
const trialUuid = row.getValue('trialUuid') as string
return h('div', { class: getCellClasses('center') },
h(GenericCompactCard<Trial>, {
entityUuid: trialUuid,
entityType: 'trial',
fetchFunction: fetchTrial,
titleField: 'title',
subtitleField: 'description',
statusField: 'status',
colorScheme: 'blue'
})
)
},
}),
createResponsiveColumn({
accessorKey: 'createdAt',
header: () => h('div', { class: getHeaderClasses('center') }, 'Created'),
cell: ({ row }) => {
const createdAt = row.getValue('createdAt') as string
return h('div', { class: getCellClasses('center') },
h(FieldDate, { date: createdAt, showTime: true })
)
},
})
]
// Helper function to determine status variant
function getStatusVariant(status: string): string {
const statusVariants: Record<string, string> = {
'Approved': 'success',
'Pending': 'warning',
'Rejected': 'error',
'Expired': 'secondary',
'Withdrawn': 'secondary'
}
return statusVariants[status] || 'default'
}