Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OOC-4405: Update landing page (part 2) content (CQC checkbox) #211

Merged
merged 10 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions model/src/components/component-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ export const ComponentTypes: ComponentDef[] = [
options: {},
schema: {},
},
{
name: "TextFieldCustom",
type: "TextFieldCustom",
title: "Text field",
subType: "field",
hint: "",
options: {},
schema: {},
},
{
name: "MultilineTextField",
type: "MultilineTextField",
Expand Down
14 changes: 14 additions & 0 deletions model/src/components/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export enum ComponentTypeEnum {
TextField = "TextField",
TextFieldCustom = "TextFieldCustom",
MultilineTextField = "MultilineTextField",
YesNoField = "YesNoField",
DateField = "DateField",
Expand Down Expand Up @@ -28,6 +29,7 @@ export enum ComponentTypeEnum {

export type ComponentType =
| "TextField"
| "TextFieldCustom"
| "MultilineTextField"
| "YesNoField"
| "DateField"
Expand Down Expand Up @@ -178,6 +180,17 @@ export interface TextFieldComponent extends TextFieldBase {
};
}

export interface TextFieldCustomComponent extends TextFieldBase {
type: "TextFieldCustom";
options: TextFieldBase["options"] & {
customValidationMessage?: string;
conditionalTextField?: {
dependsOn: string;
};
fieldName?: string;
};
}

export interface EmailAddressFieldComponent extends TextFieldBase {
type: "EmailAddressField";
}
Expand Down Expand Up @@ -345,6 +358,7 @@ export type ComponentDef =
| SelectFieldComponent
| TelephoneNumberFieldComponent
| TextFieldComponent
| TextFieldCustomComponent
| TimeFieldComponent
| UkAddressFieldComponent
| YesNoFieldComponent
Expand Down
87 changes: 62 additions & 25 deletions runner/src/server/forms/ReportAnOutbreak.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,61 +33,87 @@
"title": "Acute Respiratory Infections (ARI) - COVID-19, Flu or unknown infection in Adult Social Care settings",
"components": [
{
"name": "S0Q4",
"name": "S0Q1",
"options": {
"customValidationMessages": {
"string.regex.base": "Enter a full UK postcode",
"string.pattern.base": "Enter a full UK postcode"
}
},
"type": "TextField",
"title": "Please enter your setting Postcode",
"title": "Your setting postcode",
"schema": {
"regex": "^([a-zA-Z]{1,2}[0-9][a-zA-Z0-9]? *[0-9][a-zA-Z]{2}|[a-zA-Z]{1,2}[0-9][a-zA-Z0-9]?)$"
},
"nameHasError": false,
"hint": "Please provide the postcode of the specific setting affected (i.e. not the overarching management company if applicable). If there is no one specific setting affected e.g. Domiciliary or Home Care, then please provide the postcode of the care provider company"
"hint": "Give the postcode of your care setting, not the management company. If you provide domiciliary or home care, enter the postcode of the care provider company."
},
{
"name": "S0Q2",
"options": {
"required":false,
"customValidationMessages": {
"string.regex.base": "Enter a valid CQC Location ID",
"string.pattern.base": "Enter a valid CQC Location ID"
}
},
"type": "TextField",
"title": "Please enter your CQC Location ID",
"options": { "required": true },
"type": "SelectField",
"title": "Your local UKHSA health protection team",
"list": "sjgMDe",
"nameHasError": false,
"schema": { "regex": "^(1-\\d{1,9}|[a-zA-Z0-9]{3,7})$" }
"schema": {},
"values": {
"type": "listRef"
}
},
{
"name": "VMOkqi",
"name": "cstZQG",
"options": {},
"type": "Para",
"content": "If you don’t know your CQC Location ID then please visit <a id=\"cqc number\" target=\"_blank\" href=\"https://www.cqc.org.uk/about-us/transparency/using-cqc-data\">Using CQC data - Care Quality Commission</a> and scroll about half way down the page to <b style=\"color:#1d70b8\">CQC care directory - csv</b>. You will find your CQC Location ID in this look up table.\n</br></br>",
"content": "<a target=\"_blank\" id=\"local-health-protection-team\" href=\"https://www.gov.uk/health-protection-team\">Use your postcode to find your local health protection team (opens in a new tab)</a>",
"schema": {}
},
{
"name": "S0Q3",
"options": { "required": true },
"type": "SelectField",
"title": "Please enter your local HPT here",
"list": "sjgMDe",
"options": {
"required": false,
"optionalText": false,
"conditionalTextField": {
"dependsOn": "S0Q4"
},
"fieldName": "cqc"
},
"type": "TextFieldCustom",
"title": "Your Care Quality Commission (CQC) location ID",
"nameHasError": false,
"schema": {},
"values": {
"type": "listRef"
"schema": {
"regex": "^(1-\\d{1,9}|[a-zA-Z0-9]{3,7})$"
}
},
{
"name": "rIpMWq",
"options": {},
"type": "Para",
"content": "<div class='govuk-checkboxes__divider'>or</div>"
},
{
"name": "S0Q4",
"options": {
"hideTitle": true,
"required": false
},
"hint": "Please make sure you've selected the correct local health protection team (HPT) to guarantee you receive the appropriate support"
"type": "CheckboxesField",
"title": "My setting is not registered with the CQC",
"nameHasError": false,
"list": "OZDejp",
"schema": {}
},
{
"name": "cstZQG",
"name": "VMOkqi",
"options": {},
"type": "Para",
"content": "Click on the link to <a target=\"_blank\" id=\"local-health-protection-team\" href=\"https://www.gov.uk/health-protection-team\">Find your local health protection team in England - GOV.UK</a> (www.gov.uk) [Enter the postcode of your care setting]",
"content": "<a id=\"cqc number\" target=\"_blank\" href=\"https://www.cqc.org.uk/about-us/transparency/using-cqc-data\">Find your CQC location ID in the care directory on the CQC website (opens in a new tab).</a>",
"schema": {}
},
{
"name": "rIpMWr",
"options": {},
"type": "Html",
"content": "<script>\ndocument.addEventListener('DOMContentLoaded', function() {\nconst cqcIdText = document.getElementById('S0Q3');\nconst cqcIdCheckbox = document.getElementById('S0Q4');\nfunction updateTextFieldRequiredState() {\nconst isChecked = cqcIdCheckbox.checked;\ncqcIdText.required = !isChecked;\n}\nfunction clearCheckbox() {\ncqcIdCheckbox.checked = false;\n}\ncqcIdCheckbox.addEventListener('change', function() {\nif (cqcIdCheckbox.checked) {\ncqcIdText.value = '';\n}\nupdateTextFieldRequiredState();\n});\ncqcIdText.addEventListener('input', function() {\nif (cqcIdText.value !== '') {\nclearCheckbox();\n}\nupdateTextFieldRequiredState()\n});\n});\n</script>"
}
],
"next": [
Expand Down Expand Up @@ -1661,6 +1687,17 @@
}
],
"lists": [
{
"title": "care-setting-not-registered",
"name": "OZDejp",
"type": "string",
"items": [
{
"text": "My setting is not registered with the CQC",
"value": "My setting is not registered with the CQC"
}
]
},
{
"title": "social-care-provider-type",
"name": "MpSRIP",
Expand Down
11 changes: 10 additions & 1 deletion runner/src/server/plugins/engine/components/CheckboxesField.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { FormData, FormSubmissionErrors, FormSubmissionState } from "../types";
import {
FormData,
FormPayload,
FormSubmissionErrors,
FormSubmissionState,
} from "../types";
import { ListComponentsDef } from "@xgovformbuilder/model";
import { FormModel } from "../models";
import joi from "joi";
Expand Down Expand Up @@ -31,6 +36,10 @@ export class CheckboxesField extends SelectionControlField {
this.stateSchema = schema;
}

getStateValueFromValidForm(payload: FormPayload) {
return payload[this.name];
}

getDisplayStringFromState(state: FormSubmissionState) {
return state?.[this.name]
?.map(
Expand Down
65 changes: 65 additions & 0 deletions runner/src/server/plugins/engine/components/TextFieldCustom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { TextFieldCustomComponent } from "@xgovformbuilder/model";
import { FormModel } from "../models";
import joi from "joi";
import * as helpers from "./helpers";
import { FormPayload } from "../types";
import { FormComponent } from "./FormComponent";

// Currently only used on the ReportAnOutbreak/uon-and-cqc page to handle textfield and checkbox comparisons
export class TextFieldCustom extends FormComponent {
formSchema;
stateSchema;
pattern;
dependentField;
fieldName;

constructor(def: TextFieldCustomComponent, model: FormModel) {
super(def, model);

const { options, schema = {} } = def;
this.options = options;
this.schema = schema;

if (schema.regex) {
this.pattern = new RegExp(schema.regex);
}

if (options.conditionalTextField) {
this.dependentField = options.conditionalTextField.dependsOn;
}

if (options.fieldName) {
this.fieldName = options.fieldName;
}

let componentSchema = joi.optional().allow(null).allow("");

this.formSchema = componentSchema;
}

getStateSchemaKeys() {
let schema: any = this.formSchema;

if (this.fieldName) {
schema = schema.custom(
helpers.customTextCheckboxValidator(this.fieldName)
);
}

this.schema = schema;
return { [this.name]: schema };
}

getStateValueFromValidForm(payload: FormPayload) {
const currentFieldValue = payload[this.name].trim();
const dependentFieldValue = payload[this.dependentField];

if (currentFieldValue === "" && !dependentFieldValue) {
return false;
}
if (currentFieldValue && !this.pattern.test(currentFieldValue)) {
return "regex";
}
return currentFieldValue;
}
}
16 changes: 16 additions & 0 deletions runner/src/server/plugins/engine/components/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,22 @@ export function getCustomDateValidator(
};
}

export function customTextCheckboxValidator(fieldName: string) {
return (value: string, helpers: joi.CustomHelpers) => {
if (!value) {
return helpers.error(`string.${fieldName}`, {
label: helpers.state.key,
});
}
if (value == "regex") {
return helpers.error(`string.${fieldName}.regex`, {
label: helpers.state.key,
});
}
return value;
};
}

export function internationalPhoneValidator(
value: string,
_helpers: joi.CustomHelpers
Expand Down
1 change: 1 addition & 0 deletions runner/src/server/plugins/engine/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export { RadiosField } from "./RadiosField";
export { SelectField } from "./SelectField";
export { TelephoneNumberField } from "./TelephoneNumberField";
export { TextField } from "./TextField";
export { TextFieldCustom } from "./TextFieldCustom";
export { TimeField } from "./TimeField";
export { UkAddressField } from "./UkAddressField";
export { WebsiteField } from "./WebsiteField";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ const messageTemplate = {
dateDayYear: "{{#label}} must include a day and a year",
dateDayMonth: "{{#label}} must include a day and a month",
dateYear4digits: "The year must include 4 numbers",
cqc:
"Enter your CQC location ID or select 'My setting is not registered with the CQC'",
cqcRegex: "Enter a valid CQC Location ID",
};

export const messages: ValidationOptions["messages"] = {
Expand All @@ -39,6 +42,8 @@ export const messages: ValidationOptions["messages"] = {
"string.email": messageTemplate.email,
"string.regex.base": messageTemplate.format,
"string.maxWords": messageTemplate.maxWords,
"string.cqc": messageTemplate.cqc,
"string.cqc.regex": messageTemplate.cqcRegex,

"date.base": messageTemplate.date,
"date.empty": messageTemplate.required,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% from "input/macro.njk" import govukInput %}

{% macro TextFieldCustom(component) %}
{{ govukInput(component.model) }}
{% endmacro %}
2 changes: 1 addition & 1 deletion runner/src/server/plugins/engine/views/partials/form.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% from "button/macro.njk" import govukButton %}
{% from "summary-list/macro.njk" import govukSummaryList -%}

<form method="post" enctype="multipart/form-data" autocomplete="on">
<form method="post" enctype="multipart/form-data" autocomplete="on" novalidate>
<input type="hidden" name="crumb" value="{{crumb}}"/>
{{ componentList(components) }}

Expand Down