diff --git a/components/elements/index.js b/components/elements/index.js
index 8a4d84bf..a11ea73b 100644
--- a/components/elements/index.js
+++ b/components/elements/index.js
@@ -37,6 +37,7 @@ const ReactQuill = dynamic(() => import("react-quill-new"), { ssr: false });
import { useStore as store, useSelector } from "react-redux";
import { useDispatch } from "react-redux";
+import { validateField } from "./validationUtils"; // Import the validation function
const RenderTextfield = ({
id,
@@ -223,7 +224,9 @@ export function Textfield(props) {
// console.log(parentField, formProps, form);
//console.log("validation props:", validation);
-
+ const requiredMessage = t("account:is-required-label");
+ const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label");
+ const invalidPostcodeMessage = t("newappeal:invalid-postcode-label");
return (
{parentField != false ? (
@@ -234,7 +237,15 @@ export function Textfield(props) {
component={RenderTextfield}
type="text"
className="govuk-input govuk-input--width-20"
- validate={eval(validation)}
+ validate={(value) =>
+ validateField(
+ value,
+ validation,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ )
+ } // Use the external validate function
label={props.label}
maxFieldLength={props.maxFieldLength}
/>
@@ -246,7 +257,15 @@ export function Textfield(props) {
component={RenderTextfield}
type="text"
className="govuk-input govuk-input--width-20"
- validate={eval(validation)}
+ validate={(value) =>
+ validateField(
+ value,
+ validation,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ )
+ } // Use the external validate function
label={props.label}
errorMsg={t("newappeal:is-required-label")}
maxFieldLength={props.maxFieldLength}
@@ -356,6 +375,9 @@ export function MultiLinefield(props) {
//console.log(showIfHasParentShowValue, formProps[form].values[parentField]);
let { t } = useTranslation();
+ const requiredMessage = t("newappeal:is-required-label");
+ const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label");
+ const invalidPostcodeMessage = t("newappeal:invalid-postcode-label");
return (
<>
{parentField != false ? (
@@ -383,7 +405,15 @@ export function MultiLinefield(props) {
rows="5"
className="govuk-textarea govuk-input--width-30"
aria-describedby={props.name + "-hint"}
- validate={eval(validation)}
+ validate={(value) =>
+ validateField(
+ value,
+ validation,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ )
+ } // Use the external validate function
maxFieldLength={props.maxFieldLength}
/>
@@ -412,7 +442,15 @@ export function MultiLinefield(props) {
rows="5"
className="govuk-textarea govuk-input--width-30"
aria-describedby={props.name + "-hint"}
- validate={eval(validation)}
+ validate={(value) =>
+ validateField(
+ value,
+ validation,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ )
+ } // Use the external validate function
maxFieldLength={props.maxFieldLength}
/>
@@ -517,6 +555,9 @@ export function RichMultiLinefield(props) {
//console.log(showIfHasParentShowValue, formProps[form].values[parentField]);
let { t } = useTranslation();
+ const requiredMessage = t("newappeal:is-required-label");
+ const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label");
+ const invalidPostcodeMessage = t("newappeal:invalid-postcode-label");
return (
<>
{parentField != false ? (
@@ -543,7 +584,15 @@ export function RichMultiLinefield(props) {
rows="5"
className="govuk-textarea govuk-input--width-30"
aria-describedby={props.name + "-hint"}
- validate={eval(validation)}
+ validate={(value) =>
+ validateField(
+ value,
+ validation,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ )
+ } // Use the external validate function
maxFieldLength={props.maxFieldLength}
/>
@@ -572,7 +621,15 @@ export function RichMultiLinefield(props) {
rows="5"
className="govuk-textarea govuk-input--width-30"
aria-describedby={props.name + "-hint"}
- validate={eval(validation)}
+ validate={(value) =>
+ validateField(
+ value,
+ validation,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ )
+ } // Use the external validate function
maxFieldLength={props.maxFieldLength}
/>
@@ -738,6 +795,9 @@ export function DateFieldPicker(props) {
_.has(formProps[form].values, parentField) &&
formProps[form].values[parentField]) == parentFieldShowOnValue;
+ const requiredMessage = t("newappeal:is-required-label");
+ const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label");
+ const invalidPostcodeMessage = t("newappeal:invalid-postcode-label");
return (
{parentField != false ? (
@@ -747,7 +807,15 @@ export function DateFieldPicker(props) {
id={name}
label={label}
component={RenderDatePicker}
- validate={eval(validation)}
+ validate={(value) =>
+ validateField(
+ value,
+ validation,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ )
+ } // Use the external validate function
errorMsg={t("newappeal:select-a-date-label")}
dateStart={dateStart}
dateEnd={dateEnd}
@@ -760,7 +828,15 @@ export function DateFieldPicker(props) {
id={name}
label={label}
component={RenderDatePicker}
- validate={eval(validation)}
+ validate={(value) =>
+ validateField(
+ value,
+ validation,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ )
+ } // Use the external validate function
errorMsg={t("newappeal:select-a-date-label")}
dateStart={dateStart}
dateEnd={dateEnd}
@@ -1187,6 +1263,9 @@ export function Radiofield(props) {
(showIfHasParentShowValue == parentField) != false &&
showIfHasParentShowValue;
+ const requiredMessage = t("newappeal:is-required-label");
+ const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label");
+ const invalidPostcodeMessage = t("newappeal:invalid-postcode-label");
return (
<>
{parentField != false ? (
@@ -1202,7 +1281,15 @@ export function Radiofield(props) {
component={RenderRadio}
inline={props.inline}
hint={props.hint}
- validate={eval(validation)}
+ validate={(value) =>
+ validateField(
+ value,
+ validation,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ )
+ } // Use the external validate function
requiredDocumentLabel={props.requiredDocumentLabel}
requiredDocumentValue={props.requiredDocumentValue}
setDocumentsList={props.setDocumentsList}
@@ -1221,7 +1308,15 @@ export function Radiofield(props) {
component={RenderRadio}
inline={props.inline}
hint={props.hint}
- validate={eval(validation)}
+ validate={(value) =>
+ validateField(
+ value,
+ validation,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ )
+ } // Use the external validate function
requiredDocumentLabel={props.requiredDocumentLabel}
requiredDocumentValue={props.requiredDocumentValue}
setDocumentsList={props.setDocumentsList}
@@ -1458,7 +1553,9 @@ export function NumericField(props) {
showIfHasParentShowValue;
//console.log("parentField:", parentField, showIfHasParentShowValue);
-
+ const requiredMessage = t("newappeal:is-required-label");
+ const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label");
+ const invalidPostcodeMessage = t("newappeal:invalid-postcode-label");
return (
<>
{parentField != false ? (
@@ -1474,7 +1571,15 @@ export function NumericField(props) {
pattern="[0-9]*"
inputMode="numeric"
parse={Number}
- validate={eval(validation)}
+ validate={(value) =>
+ validateField(
+ value,
+ validation,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ )
+ } // Use the external validate function
component={RenderTextfield}
label={label}
maxFieldLength={props.maxFieldLength}
@@ -1586,6 +1691,9 @@ export function DecimalField(props) {
return undefined;
};
+ const requiredMessage = t("newappeal:is-required-label");
+ const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label");
+ const invalidPostcodeMessage = t("newappeal:invalid-postcode-label");
return (
<>
{parentField != false ? (
@@ -1602,7 +1710,15 @@ export function DecimalField(props) {
pattern="[0-9]*"
inputMode="numeric"
parse={Number}
- validate={eval(validation)}
+ validate={(value) =>
+ validateField(
+ value,
+ validation,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ )
+ } // Use the external validate function
component={RenderTextfield}
label={props.label}
maxFieldLength={props.maxFieldLength}
diff --git a/components/elements/validationUtils.js b/components/elements/validationUtils.js
new file mode 100644
index 00000000..ea0d60b9
--- /dev/null
+++ b/components/elements/validationUtils.js
@@ -0,0 +1,71 @@
+// validationUtils.js
+
+// Validation functions
+const required = (value, requiredMessage, emojiNotAllowedMessage) => {
+ let errors;
+ if (!value) {
+ errors = requiredMessage;
+ } else {
+ const emojiRegex =
+ /[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{1FA70}-\u{1FAFF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{2300}-\u{23FF}\u{2B50}\u{1F004}-\u{1F0CF}\u{1F0A0}-\u{1F0A5}\u{1F170}-\u{1F251}]/gu;
+
+ if (emojiRegex.test(value)) {
+ errors = emojiNotAllowedMessage;
+ }
+ }
+ return errors;
+};
+
+const postcode = (value, invalidPostcodeMessage) =>
+ value &&
+ !/^([A-Z][A-HJ-Y]?[0-9][A-Z0-9]? ?[0-9][A-Z]{2}|GIR ?0A{2})$/i.test(value)
+ ? "Invalid postcode"
+ : undefined;
+
+// Function to parse the validation string
+export const parseValidationString = (validationString) => {
+ if (typeof validationString !== "string") {
+ return []; // Return an empty array if it's not a string
+ }
+
+ // Remove square brackets and split by commas
+ return validationString
+ .replace(/[\[\]']+/g, "") // Remove square brackets
+ .split(",") // Split by commas
+ .map((rule) => rule.trim()); // Trim each validation rule
+};
+
+// Function to handle multiple validation rules
+export const validateField = (
+ value,
+ validationString,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+) => {
+ const validations = parseValidationString(validationString); // Parse the validation string
+ let errors;
+
+ console.log(typeof validations, validations);
+ for (let validationRule of validations) {
+ const validationFunc = validationFunctions[validationRule];
+ if (validationFunc) {
+ errors = validationFunc(
+ value,
+ requiredMessage,
+ emojiNotAllowedMessage,
+ invalidPostcodeMessage
+ );
+ }
+ if (errors) break; // Exit if any validation fails
+ }
+
+ return errors;
+};
+
+// Map validation strings to actual validation functions
+export const validationFunctions = {
+ required,
+ postcode,
+ // Add other validation functions as needed
+};