Skip to content

Commit

Permalink
Add table method to CourseParticipationUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
jsrobertson committed Jan 15, 2025
1 parent 9cdb043 commit a1968a9
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 3 deletions.
115 changes: 114 additions & 1 deletion server/utils/courseParticipationUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import type { Request } from 'express'

import type { RequestWithCourseParticipationDetailsBody } from './courseParticipationUtils'
import CourseParticipationUtils from './courseParticipationUtils'
import { courseParticipationFactory } from '../testutils/factories'
import { referPaths } from '../paths'
import { courseParticipationFactory, referralFactory } from '../testutils/factories'
import type { CourseParticipationPresenter } from '@accredited-programmes/ui'
import type {
CourseParticipationOutcome,
Expand Down Expand Up @@ -622,4 +623,116 @@ describe('CourseParticipationUtils', () => {
})
})
})

describe('table', () => {
const referral = referralFactory.build()
const courseParticipations = [
courseParticipationFactory.build({
courseName: 'Unfinished programme name',
detail: undefined,
id: 'unfinished-programme-id',
outcome: {
yearCompleted: undefined,
yearStarted: 2023,
},
setting: {
location: undefined,
type: 'community',
},
}),
courseParticipationFactory.build({
courseName: 'Finished programme name',
detail: 'Some more details',
id: 'finished-programme-id',
outcome: {
yearCompleted: 2024,
yearStarted: undefined,
},
setting: {
location: 'Whatton',
type: 'custody',
},
}),
]

const expectedResponse = {
attributes: {
'data-module': 'moj-sortable-table',
'data-testid': 'existing-participations',
},
head: [
{
attributes: { 'aria-sort': 'ascending' },
text: 'Programme',
},
{
attributes: { 'aria-sort': 'none' },
text: 'Location',
},
{
attributes: { 'aria-sort': 'none' },
text: 'Outcome',
},
{ text: 'Notes' },
],
rows: [
[
{
attributes: {
'data-sort-value': 'Finished programme name',
},
html: `<a href="${referPaths.new.programmeHistory.show({ courseParticipationId: 'finished-programme-id', referralId: referral.id })}">Finished programme name</a>`,
},
{ text: 'Whatton' },
{ text: 'Completed 2024' },
{ text: 'Some more details' },
],
[
{
attributes: {
'data-sort-value': 'Unfinished programme name',
},
html: `<a href="${referPaths.new.programmeHistory.show({ courseParticipationId: 'unfinished-programme-id', referralId: referral.id })}">Unfinished programme name</a>`,
},
{ text: 'Not known' },
{ text: 'Deselected 2023' },
{ text: undefined },
],
],
}

it('returns a GovukFrontendTable with the correct properties and data', () => {
expect(CourseParticipationUtils.table(courseParticipations, referral.id, 'existing-participations')).toEqual(
expectedResponse,
)
})

describe('when the participations can be edited', () => {
it('returns a GovukFrontendTable with the action column', () => {
expect(
CourseParticipationUtils.table(courseParticipations, referral.id, 'referral-participations', true),
).toEqual({
...expectedResponse,
attributes: {
...expectedResponse.attributes,
'data-testid': 'referral-participations',
},
head: [...expectedResponse.head, { text: 'Action' }],
rows: expectedResponse.rows.map((row, index) => [
...row,
{
html: `<ul class="govuk-summary-list__actions-list">
<li class="govuk-summary-list__actions-list-item">
<a class="govuk-link" href="${referPaths.new.programmeHistory.editProgramme({ courseParticipationId: courseParticipations[index].id, referralId: referral.id })}">Change<span class="govuk-visually-hidden"> programme (${courseParticipations[index].courseName})</span></a>
</li>
<li class="govuk-summary-list__actions-list-item">
<a class="govuk-link" href="${referPaths.new.programmeHistory.delete({ courseParticipationId: courseParticipations[index].id, referralId: referral.id })}">Remove<span class="govuk-visually-hidden"> programme (${courseParticipations[index].courseName})</span></a>
</li>
</ul>`,
},
]),
})
})
})
})
})
88 changes: 86 additions & 2 deletions server/utils/courseParticipationUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import type {
CourseParticipationUpdate,
Referral,
} from '@accredited-programmes-api'
import type { GovukFrontendSummaryListRowKey } from '@govuk-frontend'
import type {
GovukFrontendSummaryListRowKey,
GovukFrontendTable,
GovukFrontendTableHeadElement,
GovukFrontendTableRow,
} from '@govuk-frontend'

interface CourseParticipationDetailsBody {
detail: string
Expand Down Expand Up @@ -151,6 +156,81 @@ export default class CourseParticipationUtils {
}
}

static table(
courseParticipations: Array<CourseParticipation>,
referralId: Referral['id'],
testId: string,
editable = false,
): GovukFrontendTable {
const head: Array<GovukFrontendTableHeadElement> = [
{
attributes: { 'aria-sort': 'ascending' },
text: 'Programme',
},
{
attributes: { 'aria-sort': 'none' },
text: 'Location',
},
{
attributes: { 'aria-sort': 'none' },
text: 'Outcome',
},
{ text: 'Notes' },
...(editable ? [{ text: 'Action' }] : []),
]

const rows: Array<GovukFrontendTableRow> = courseParticipations
.sort((a, b) => (a.courseName ?? '').localeCompare(b.courseName ?? ''))
.map(courseParticipation => {
return [
{
attributes: {
'data-sort-value': courseParticipation.courseName,
},
html: `<a href="${referPaths.new.programmeHistory.show({ courseParticipationId: courseParticipation.id, referralId })}">${courseParticipation.courseName}</a>`,
},
{ text: this.textValue(courseParticipation.setting?.location) },
{ text: this.textValue(this.outcomeString(courseParticipation.outcome)) },
{ text: courseParticipation.detail },
...(editable
? [
{
html: `<ul class="govuk-summary-list__actions-list">
<li class="govuk-summary-list__actions-list-item">
<a class="govuk-link" href="${referPaths.new.programmeHistory.editProgramme({ courseParticipationId: courseParticipation.id, referralId })}">Change<span class="govuk-visually-hidden"> programme (${courseParticipation.courseName})</span></a>
</li>
<li class="govuk-summary-list__actions-list-item">
<a class="govuk-link" href="${referPaths.new.programmeHistory.delete({ courseParticipationId: courseParticipation.id, referralId })}">Remove<span class="govuk-visually-hidden"> programme (${courseParticipation.courseName})</span></a>
</li>
</ul>`,
},
]
: []),
]
})

return {
attributes: {
'data-module': 'moj-sortable-table',
'data-testid': testId,
},
head,
rows,
}
}

private static outcomeString(outcome?: CourseParticipationOutcome) {
if (outcome?.yearStarted) {
return `Deselected ${outcome.yearStarted}`
}

if (outcome?.yearCompleted) {
return `Completed ${outcome.yearCompleted}`
}

return undefined
}

private static summaryListRows(
courseParticipation: CourseParticipationPresenter,
): Array<GovukFrontendSummaryListRowWithKeyAndValue> {
Expand All @@ -176,7 +256,7 @@ export default class CourseParticipationUtils {

return {
key: { text: keyText },
value: { text: valueTextItemsWithoutBlanks.join(', ') || 'Not known' },
value: { text: this.textValue(valueTextItemsWithoutBlanks.join(', ')) },
}
}

Expand Down Expand Up @@ -216,6 +296,10 @@ export default class CourseParticipationUtils {
return this.summaryListRow('Setting', valueTextItems)
}

private static textValue(value?: string): string {
return value || 'Not known'
}

private static validateYear(
field: string,
value: string,
Expand Down

0 comments on commit a1968a9

Please sign in to comment.