Skip to content

Conversation

@harrim91
Copy link
Contributor

@harrim91 harrim91 commented Jan 6, 2026

Description

Adds new page to show preview of message plan in production. Page looks visually similar to "choose templates" page, but with different logic - e.g. the "card" elements have different content, conditional templates which aren't set are not shown (choose templates always shows slots for all conditional templates even if they are empty) - so also refactored a lot of the components there to be composable, and have lifted the choose templates specific logic out of the components and into the page.

Context

Type of changes

  • Refactoring (non-breaking change)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would change existing functionality)
  • Bug fix (non-breaking change which fixes an issue)

Checklist

  • I am familiar with the contributing guidelines
  • I have followed the code style of the project
  • I have added tests to cover my changes
  • I have updated the documentation accordingly
  • This PR is a result of pair or mob programming
  • If I have used the 'skip-trivy-package' label I have done so responsibly and in the knowledge that this is being fixed as part of a separate ticket/PR.

Sensitive Information Declaration

To ensure the utmost confidentiality and protect your and others privacy, we kindly ask you to NOT including PII (Personal Identifiable Information) / PID (Personal Identifiable Data) or any other sensitive data in this PR (Pull Request) and the codebase changes. We will remove any PR that do contain any sensitive information. We really appreciate your cooperation in this matter.

  • I confirm that neither PII/PID nor sensitive data are included in this PR and the codebase changes.

@harrim91 harrim91 requested a review from a team as a code owner January 6, 2026 17:55
@harrim91 harrim91 marked this pull request as draft January 6, 2026 17:55
@harrim91 harrim91 marked this pull request as ready for review January 19, 2026 17:19
@harrim91 harrim91 changed the title CCM-12038: WIP preview production message plan CCM-12038: preview production message plan Jan 20, 2026
},
ctas: {
primary: {
href: '/message-plans/get-ready-to-move/{{routingConfigId}}',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how come?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I put most of the choose templates stuff into page.tsx which is server rendered. The CTA now uses a server action to do the validation / redirect, rather than having a link with an event listener / e.preventDefault etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should still have the href tho for accessibility purposes surely? so its clear from the markup that the button will take them to a different page, even if the href isnt going to be responsible for the navigation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know, I thought that this was better for accessibility. With the link/href, you'd expect clicking that to navigate you somewhere. But it actually has some client-side pseudo form validation, and if the validation failed, then it didn't navigate and you get a form error. It felt like a form masquerading as a link.

This way, it's a form with a submit button. Its not uncommon for submitting a form to navigate you somewhere different - probably most of our forms do it - and it's not clear where you're going to end up because none of the form submit buttons have an href attribute. So I figured this is in line with how we do forms elsewhere. The difference I guess is that the form doesn't do anything in the sense of performing a backend action - but it does do form validation, it can return form error state. So it felt right to have it as a form.

<FormContext.Provider value={[state, action, isPending]}>
<NhsNotifyErrorSummary errorState={state.errorState} />
<NhsNotifyErrorSummary
hint={errorSummaryHint}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how was this working before?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There wasn't an instance of the FormProvider being used to render an error summary with a hint.

renderSMSMarkdown,
} from './markdownit';

export function renderTemplateMarkdown(template: TemplateDto): string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export function renderTemplateMarkdown(template: TemplateDto): string {
export function renderDigitalTemplateMarkdown(template: DigitalTemplate): string {

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had wondered this.

{children}
</SummaryList.Value>
);
}
Copy link
Contributor

@chris-elliott-nhsd chris-elliott-nhsd Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not sure what's being gained from this level of splitting everything out. this seems to be a 57-line file where all it does is append a class name to an existing nhsuk-react-components component, which would just be a few characters if it wasn't split out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was an existing component (the nhsuk-react-components component with customised styling) which is now being reused in a few places. It's just the styling though, I guess I could just import the scss module into the places where this new component is being used, and just render the proper nhsuk component and apply the styles to it in each place. But having an scss module without a component feels odd - it feels to me to worth having it encapsulated into a proper component.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could just put our style overrides in app.scss?


await expect(page).toHaveURL(
`${baseURL}/templates/message-plans/choose-templates/${dbEntry.id}`
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you think about checking the status once we get here? i.e. to confirm its not got "production" status?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unsure what the value is - why would it have changed? the db storage helper doesn't have any functionality for getting data, so presumably we're not doing anything like that anywhere else either. that sounds a bit lazy - not against adding it, just not sure if it's worth it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well I more meant to clearly differentiate between the production ones going to the preview page and it being the choose templates when its not production
so not testing because it would have changed, but because we expect that and expect it not to be production
but if you dont think there's value, thats fair

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get what you mean, it's just because the config is created explicitly by the test with a status of DRAFT. Checking the template status is not really testing the behaviour of the page, it's just ensuring that there's no random process outside of the test that has altered that status in the background in the time it took to create the item and load the page. Or that the act of redirecting from one page to the other doesn't change the status.

I guess I could check that the status tag on the choose templates page that it's redirected to says "Draft"

@@ -0,0 +1,92 @@
'use client';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm surprised you've had to create this vs using from the react lib?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean?

templateIds.NHSAPP,
user,
'Test NHS App template'
` 'Test NHS App template - ${templateIds.NHSAPP}`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra spaces here

`details.${targetClassName}`
);
for (const element of details) {
element.open = isOpen;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you briefly explain why we mutate the dom here, for my understanding?

throw new Error('Routing configuration not found');
}

const channelsWithoutTemplates = getChannelsMissingTemplates(routingConfig);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the PROOF_APPROVED PR should go in today - at that point you might want to add validation that all letters are PROOF_APPROVED

Copy link
Contributor

@alexnuttall alexnuttall Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this case shouldn't be reachable on the frontend anyway, since we prevent selection of letter templates in other statuses. So it doesn't need to be handled on the frontend?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants