@ministryofjustice/hmpps-digital-prison-reporting-frontend
Version:
The Digital Prison Reporting Frontend contains templates and code to help display data effectively in UI applications.
123 lines (105 loc) • 3.7 kB
text/typescript
import Dict = NodeJS.Dict
import { components } from '../../types/api'
import { Cell, DataTable, FieldDefinition } from '../DataTableBuilder/types'
import type { Template } from '../../types/Templates'
import ParentChildDataTableBuilder from '../ParentChildDataTableBuilder/ParentChildDataTableBuilder'
export default class SectionedFieldsDataTableBuilder extends ParentChildDataTableBuilder {
sectionedFields: components['schemas']['SectionedField'][]
template: Template
constructor(variant: components['schemas']['VariantDefinition']) {
const { sectionedFields, template } = variant.specification
super(variant)
this.sectionedFields = sectionedFields
this.sections = this.sectionedFields.map((f) => f.name)
this.template = template
}
getChildFields(childId: string): FieldDefinition[] {
const childVariant = this.variant.childVariants.find((child) => child.id === childId)
return childVariant ? childVariant.specification.fields : []
}
getJoinKey() {
return this.variant.childVariants[0].joinFields[0]
}
initSectionedData(data: Array<Dict<string>>) {
return data.flatMap((row) => {
const initialisedSectionsWithFields = this.sectionedFields.map((section) => {
const sectionHeader = this.mapNamesToFields([section.name])[0]
let fields: FieldDefinition[] = []
const { child } = section
if (section.fields) {
fields = this.mapNamesToFields(section.fields)
} else if (section.child) {
fields = this.getChildFields(section.child)
}
return {
header: sectionHeader,
fields,
child,
}
})
return initialisedSectionsWithFields.map((section) => {
if (section.child) {
const childData = this.getChildData(section.child)
const displayFields = section.fields.filter((f) => f.visible)
const joinKey = this.getJoinKey()
return {
header: section.header.display,
fields: childData.data
.filter((cd) => cd[joinKey] === row[joinKey])
.map((cd) => {
return {
heading: cd[displayFields[0]?.name] || 'Not found',
data: cd[displayFields[1]?.name] || 'Not found',
}
}),
}
}
return {
header: section.header.display,
fields: section.fields
.filter((f) => f.visible)
.map((f) => {
return {
heading: f.display,
data: row[f.name],
}
}),
}
})
})
}
getChildData(childId: string) {
return this.childData.find((d) => d.id === childId)
}
createRows(data: Array<Dict<string>>): Cell[][] {
const sectionedData = this.initSectionedData(data)
const rows = sectionedData.flatMap((section, index) => {
const sectionHeaderRow = this.createSectionHeader(section.header, index)
const sectionRows = section.fields.map((field) => {
return [
{
text: field.heading,
classes: 'dpr-row-heading',
},
{
text: field.data,
classes: 'dpr-row-heading-data',
},
]
})
return [...sectionHeaderRow, ...sectionRows]
})
return rows
}
buildTable(data: Array<Dict<string>>): DataTable {
return {
head: [
{ text: '', classes: 'dpr-row-section-header' },
{ text: '', classes: 'pr-row-section-header-value' },
],
rows: this.createRows(data),
rowCount: data.length,
colCount: this.columns.length,
}
}
}