Author SHA1 Message Date
Robert Bond fdeff5b898 Merged PR 2605: updated query to include consultationclosed check
updated query to include consultationclosed check

Related work items: #24836
2026-09-07 10:46:32 +00:00
Robert Bond 4e9d585566 Merged PR 2596: fix build error
fix build error

Related work items: #24648
2026-09-02 12:37:32 +00:00
Robert Bond b95a20a980 Merged PR 2595: updated regex to exclude bulk annon mailers
updated regex to exclude bulk annon mailers

Related work items: #24648
2026-09-02 08:02:38 +00:00
Robert Bond c9e7743782 Merged PR 2586: update text for reps showing
update text for reps showing

Related work items: #24650
2026-08-25 15:20:56 +00:00
Robert Bond 6bf5918387 Merged PR 2585: added text before make reps button
added text before make reps button

Related work items: #24650
2026-08-25 09:01:11 +00:00
Robert Bond c2d79cf83f Merged PR 2580: fixed the links
fixed the links

Related work items: #24648
2026-08-20 12:54:44 +00:00
Robert Bond 6ba1e16f9a Merged PR 2573: added link to footer
added link to footer

Related work items: #24649
2026-08-18 15:17:25 +00:00
Robert Bond 6cce7d05f1 Merged PR 2572: overlay link to guidance
overlay link to guidance

Related work items: #24650
2026-08-18 15:02:36 +00:00
Robert Bond ac4834a2a4 Merged PR 2570: updated copyright links
updated copyright links

Related work items: #24648
2026-08-18 14:21:54 +00:00
14 changed files with 166 additions and 36 deletions
+11 -1
View File
@@ -72,7 +72,17 @@ export default function AIPolicyNotice() {
{t("home:ai-policy-notice-paragraph-one")}
</p>
<p className="govuk-body govuk-!-margin-bottom-4">
{t("home:ai-policy-notice-paragraph-two")}
{t("home:ai-policy-notice-paragraph-two")}{" "}
<a
target="_blank"
rel="noopener noreferrer"
href={t(
"home:ai-policy-notice-paragraph-two-a-link"
)}
>
{t("home:ai-policy-notice-paragraph-two-a-label")}
</a>{" "}
{t("home:ai-policy-notice-paragraph-two-b")}
</p>
<button
ref={dismissButtonRef}
+47
View File
@@ -877,6 +877,52 @@ const CaseSummary = (props) => {
<div className="govuk-grid-row">
<div className="govuk-grid-column-full">
<div className="">
{getFormCollectionByID(
appealTypeID
).PrimaryIdAttribute ==
"pinswg_sipscase" &&
isConsultationWindowOpen(
detailsObj
) && (
<p>
{t(
"case:summary-make-consultation-response-para-a"
)}
<Link
target="_blank"
className="govuk-link"
href={t(
"case:summary-make-representation-para-a-link"
)}
>
{t(
"case:summary-make-representation-para-a-label"
)}
</Link>
</p>
)}
{isGeneralRepresentationWindowOpen(
detailsObj
) && (
<div className="govuk-button-group">
<p>
{t(
"case:summary-make-representation-para-a"
)}
<Link
target="_blank"
className="govuk-link"
href={t(
"case:summary-make-representation-para-a-link"
)}
>
{t(
"case:summary-make-representation-para-a-label"
)}
</Link>
</p>
</div>
)}
<div className="govuk-button-group">
{getFormCollectionByID(
appealTypeID
@@ -983,6 +1029,7 @@ const CaseSummary = (props) => {
)}
</>
)}
{isGeneralRepresentationWindowOpen(
detailsObj
) && (
+27 -14
View File
@@ -108,7 +108,7 @@ export default function Footer(props) {
>
<span className="vo_hidden">
{t(
"common:social-bar-share-via-link",
"common:social-bar-share-via-link"
)}{" "}
</span>
Twitter
@@ -186,37 +186,37 @@ export default function Footer(props) {
<li className="govuk-footer__inline-list-item govuk-!-font-weight-bold govuk-!-margin-right-7">
<a
href={t(
"common:footer-guidance-link",
"common:footer-guidance-link"
)}
className="nav-link"
>
{t(
"common:footer-guidance-link-label",
"common:footer-guidance-link-label"
)}
</a>
</li>
<li className="govuk-footer__inline-list-item govuk-!-font-weight-bold govuk-!-margin-right-7">
<a
href={t(
"common:footer-announcements-link",
"common:footer-announcements-link"
)}
className="nav-link"
>
{t(
"common:footer-announcements-link-label",
"common:footer-announcements-link-label"
)}
</a>
</li>
<li className="govuk-footer__inline-list-item govuk-!-font-weight-bold">
<a
href={t(
"common:footer-contact-us-link",
"common:footer-contact-us-link"
)}
className="govuk-footer__link"
id="aContactUs"
>
{t(
"common:footer-contact-us-link-label",
"common:footer-contact-us-link-label"
)}
</a>
</li>
@@ -236,7 +236,7 @@ export default function Footer(props) {
id="aAccessibility"
>
{t(
"common:footer-accessibility-link-label",
"common:footer-accessibility-link-label"
)}
</Link>
</li>
@@ -257,13 +257,13 @@ export default function Footer(props) {
<li className="govuk-footer__inline-list-item">
<a
href={t(
"common:footer-copyright-link",
"common:footer-copyright-link"
)}
className="govuk-footer__link"
id="Access"
>
{t(
"common:footer-copyright-link-label",
"common:footer-copyright-link-label"
)}
</a>
</li>
@@ -271,13 +271,13 @@ export default function Footer(props) {
<li className="govuk-footer__inline-list-item">
<Link
href={t(
"common:footer-privacy-link",
"common:footer-privacy-link"
)}
id="aPrivacy"
className="govuk-footer__link"
>
{t(
"common:footer-privacy-link-label",
"common:footer-privacy-link-label"
)}
</Link>
</li>
@@ -285,13 +285,26 @@ export default function Footer(props) {
<li className="govuk-footer__inline-list-item">
<Link
href={t(
"common:footer-terms-conditions-link",
"common:footer-terms-conditions-link"
)}
id="aTermsConds"
className="govuk-footer__link"
>
{t(
"common:footer-terms-conditions-link-label",
"common:footer-terms-conditions-link-label"
)}
</Link>
</li>
<li className="govuk-footer__inline-list-item">
<Link
href={t(
"common:footer-pedw-use-ai-link"
)}
id="aHowToAI"
className="govuk-footer__link"
>
{t(
"common:footer-pedw-use-ai-label"
)}
</Link>
</li>
+3 -3
View File
@@ -88,9 +88,9 @@ module.exports = {
"/details-about-cookies": ["common", "cookies"],
"/terms-and-conditions": ["common"],
"/account/passwordreset": ["common", "home"],
"/auth/signin": ["common", "common", "auth"],
"/auth/verify-request": ["common", "common", "auth"],
"/auth/error": ["common", "common", "auth"],
"/auth/signin": ["common", "account", "auth"],
"/auth/verify-request": ["common", "account", "auth"],
"/auth/error": ["common", "account", "auth"],
"/admin": ["case"]
}
};
+5 -1
View File
@@ -17,6 +17,10 @@
"summary-case-stage-label": "Cam yr Achos",
"summary-environmental-statement-label": "Lleoliad Datganiad Amgylcheddol",
"summary-last-modified-label": "Addaswyd ddiwethaf",
"summary-make-consultation-response-para-a": "Gellir cyflwyno ymatebion i ymgynghoriadau, neu sylwadau, ar gyfer yr achos hwn bellach. I gael rhagor o wybodaeth am gyflwyno sylwadau i PCAC, gweler ein ",
"summary-make-representation-para-a": "Gellir cyflwyno sylwadau, neu gynrychioliadau, ar gyfer yr achos hwn bellach. I gael rhagor o wybodaeth am gyflwyno sylwadau i PCAC, gweler ein ",
"summary-make-representation-para-a-link": "https://www.llyw.cymru/defnyddio-deallusrwydd-artiffisial-ai-mewn-cyflwyniadau-i-pcac",
"summary-make-representation-para-a-label": "Canllawiau ar ddefnyddio Deallusrwydd Artiffisial Cynhyrchiol",
"summary-make-representation-label": "Cyflwyno sylwadau",
"summary-make-consultation-label": "Cyflwyno Ymateb i'r Ymgynghoriad",
"summary-representation-open-label": "Cynrychioliadau yn agor",
@@ -179,4 +183,4 @@
"summary-comp-acquisition-variation-accepted": "Newid i Gaffael Gorfodol wedi'i Dderbyn",
"summary-scheme-ammendment-request-submitted": "Cais i Newid Cynllun/Gorchymyn wedi'i Gyflwyno",
"summary-scheme-ammendment-request-accepted": "Cais i Newid Cynllun/Gorchymyn wedi'i Dderbyn"
}
}
+3 -1
View File
@@ -20,6 +20,8 @@
"cancel-link": "Canslo",
"save-exit-button": "Cadw a gadael",
"submit-and-start": "Cyflwyno a dechrau'r cwrs",
"footer-pedw-use-ai-label": "Sut mae PCAC yn defnyddio deallusrwydd artiffisial (AI)",
"footer-pedw-use-ai-link": "https://www.llyw.cymru/penderfyniadau-cynllunio-ac-amgylchedd-cymru/sut-mae-pcac-yn-defnyddio-deallusrwydd-artiffisial-ai",
"footer-terms-conditions-link-label": "Telerau ac amodau",
"footer-terms-conditions-link": "https://llyw.cymru/gwaith-achos-cynllunio-telerau-ac-amodau",
"footer-privacy-link-label": "Preifatrwydd",
@@ -32,7 +34,7 @@
"footer-contact-us-link-label": "Cysylltu â ni",
"footer-contact-us-link": "https://llyw.cymru/penderfyndiadau-cynllunio-ac-amgylchedd-cymru/cysylltwch-ni",
"footer-copyright-link-label": "Datganiad hawlfraint",
"footer-copyright-link": "https://llyw.cymru/datganiad-hawlfraint",
"footer-copyright-link": "https://www.llyw.cymru/penderfyniadau-cynllunio-ac-amgylchedd-cymru/datganiad-hawlfraint",
"footer-alternative-languages-link-label": "Ieithoedd amgen",
"footer-alternative-languages-link": "https://llyw.cymru/ieithoedd-amgen",
"footer-guidance-link-label": "Canllawiau a gwasanaethau Penderfyniadau Cynllunio ac Amgylchedd Cymru",
+5 -2
View File
@@ -56,9 +56,12 @@
"signin-benefits-paragraph": "Drwy fewngofnodi gyda'r botwm Mewngofnodi, byddwch yn gallu:",
"ai-policy-notice-title": "Pwysig: canllawiau ar ddefnyddio cynnwys a gynhyrchir gan AI",
"ai-policy-notice-paragraph-one": "Deellir y gall partïon ddewis defnyddio Deallusrwydd Artiffisial Cynhyrchiol (AI) wrth gyflwyno apeliadau neu gynrychioliadau i PCAC. Er bod gan y rhai sy'n ymgysylltu â PCAC hawl i ddefnyddio AI i gynorthwyo eu cyflwyniadau, dylid nodi y gall cynnwys a gynhyrchir gan AI gynnwys honiadau ffug neu ddi-sail.",
"ai-policy-notice-paragraph-two": "Gan y bydd cyflwyniadau ysgrifenedig yn destun craffu yn y broses apelio, o bosibl o dan groesholiad mewn gwrandawiadau ac ymholiadau, ni ddylech wneud cyflwyniadau ysgrifenedig nad ydych yn eu deall neu'n gwybod eu bod yn gywir. Gall cyflwyno tystiolaeth anghywir arwain at gost ddiangen wrth wirio neu wrthbrofi tystiolaeth o'r fath a gallai arwain at ddyfarnu costau yn eich erbyn. Gweler ein Canllawiau ar gyfer defnyddio AI Cynhyrchiol am ragor o wybodaeth.",
"ai-policy-notice-paragraph-two": "Gan y bydd cyflwyniadau ysgrifenedig yn destun craffu yn y broses apelio ac o bosibl yn destun croesholi mewn gwrandawiadau ac ymchwiliadau ni ddylech wneud cyflwyniadau ysgrifenedig nad ydych yn eu deall neu nad ydych yn gwybod eu bod yn gywir. Gall cyflwyno tystiolaeth anghywir arwain at gostau diangen wrth wirio neu wrthbrofi'r dystiolaeth honno, a gallai arwain at orchymyn i chi dalu costau. Gweler ein ",
"ai-policy-notice-paragraph-two-a-label": "Canllawiau ar ddefnyddio Deallusrwydd Artiffisial (AI) Cynhyrchiol",
"ai-policy-notice-paragraph-two-a-link": "https://www.llyw.cymru/defnyddio-deallusrwydd-artiffisial-ai-mewn-cyflwyniadau-i-pcac",
"ai-policy-notice-paragraph-two-b": " am ragor o wybodaeth.",
"ai-policy-notice-dismiss-button": "Rwy'n deall",
"contact-us-heading": "Cysylltu â ni",
"contact-us-paragraph": "Os oes gennych unrhyw ymholiadau ynghylch apêl, cais neu unrhyw beth arall sy'n ymwneud â Gwaith Achos Cynllunio, gallwch gysylltu â ni",
"contact-us-button": "Cysylltu â ni"
}
}
+5 -1
View File
@@ -17,6 +17,10 @@
"summary-case-stage-label": "Case Stage",
"summary-environmental-statement-label": "Environmental Statement Location",
"summary-last-modified-label": "Last modified",
"summary-make-consultation-response-para-a": "Consultations responses, or comments, may now be submitted for this case. For further information on making submissions to PEDW, please see our ",
"summary-make-representation-para-a": "Representations, or comments, may now be submitted for this case. For further information on making submissions to PEDW, please see our ",
"summary-make-representation-para-a-link": "https://www.gov.wales/using-ai-submissions-pedw",
"summary-make-representation-para-a-label": "Guidance for the use of Generative AI",
"summary-make-representation-label": "Make representation",
"summary-make-consultation-label": "Submit a Consultation Response",
"summary-representation-open-label": "Representations open",
@@ -180,4 +184,4 @@
"summary-comp-acquisition-variation-accepted": "Compulsory Acquisition Variation Accepted",
"summary-scheme-ammendment-request-submitted": "Scheme/Order Amendment Request Submitted",
"summary-scheme-ammendment-request-accepted": "Scheme/Order Amendment Request Accepted"
}
}
+4 -2
View File
@@ -20,6 +20,8 @@
"cancel-link": "Cancel",
"save-exit-button": "Save and exit",
"submit-and-start": "Submit and start course",
"footer-pedw-use-ai-label": "How PEDW uses AI",
"footer-pedw-use-ai-link": "https://www.gov.wales/planning-and-environment-decisions-wales/how-pedw-uses-ai",
"footer-terms-conditions-link-label": "Terms and conditions",
"footer-terms-conditions-link": "https://gov.wales/planning-casework-terms-and-conditions",
"footer-privacy-link-label": "Privacy",
@@ -30,9 +32,9 @@
"footer-accessibility-link": "/accessibility",
"footer-feedback-link": "Give feedback about this page",
"footer-contact-us-link-label": "Contact us",
"footer-contact-us-link": "https://gov.wales/planning-and-environment-decisions-wales/contact-us",
"footer-contact-us-link": "https://www.gov.wales/planning-and-environment-decisions-wales/contact-us",
"footer-copyright-link-label": "Copyright statement",
"footer-copyright-link": "https://gov.wales/copyright-statement",
"footer-copyright-link": "https://www.gov.wales/planning-and-environment-decisions-wales/copyright-statement",
"footer-alternative-languages-link-label": "Alternative languages",
"footer-alternative-languages-link": "https://gov.wales/alternative-languages",
"footer-guidance-link-label": "Planning and Environment Decisions Wales guidance and services",
+4 -1
View File
@@ -56,7 +56,10 @@
"signin-benefits-paragraph": "By signing in with the Sign in button, you will be able to:",
"ai-policy-notice-title": "Important: guidance on use of AI-generated content",
"ai-policy-notice-paragraph-one": "It is understood that parties may choose to make use of Generative Artificial Intelligence (AI) when submitting appeals or representations to PEDW. While those engaging with PEDW are entitled to use AI to aid their submissions, it should be noted that content generated by an AI may include false or unsubstantiated claims.",
"ai-policy-notice-paragraph-two": "As written submissions will be subject to scrutiny in the appeals process, potentially under cross-examination at hearings and inquiries, you should not make written submissions that you do not understand or know to be accurate. The submission of inaccurate evidence may incur unnecessary expense verifying or rebutting such evidence and could lead to an award of costs against you. Please see our Guidance for the use of Generative AI for further information.",
"ai-policy-notice-paragraph-two": "As written submissions will be subject to scrutiny in the appeals process, potentially under cross-examination at hearings and inquiries, you should not make written submissions that you do not understand or know to be accurate. The submission of inaccurate evidence may incur unnecessary expense verifying or rebutting such evidence and could lead to an award of costs against you. Please see our ",
"ai-policy-notice-paragraph-two-a-label": "Guidance for the use of Generative AI",
"ai-policy-notice-paragraph-two-a-link": "https://www.gov.wales/using-ai-submissions-pedw",
"ai-policy-notice-paragraph-two-b": " for further information.",
"ai-policy-notice-dismiss-button": "I understand",
"contact-us-heading": "Contact us",
"contact-us-paragraph": "If you have any queries on an appeal, application or anything else regarding Planning Caserwork you can contact us",
+17 -3
View File
@@ -372,16 +372,30 @@ export default async function CombinedApiProxy(req, res) {
}
// === Fetch Reps open events ===
let repsPeriods;
let repsPeriods = [];
try {
const repsQuery = `pinswg_sipses?$filter=_pinswg_sipscase_value eq ${incidentID} and pinswg_consultationopen ne null &$select=pinswg_consultationopen,pinswg_consultationclose`;
const repsQuery =
`pinswg_sipses?` +
`$filter=_pinswg_sipscase_value eq ${incidentID} ` +
`and pinswg_consultationopen ne null ` +
`and (pinswg_consultationclose eq null or pinswg_consultationclose ge ${nowStr})` +
`&$select=pinswg_consultationopen,pinswg_consultationclose`;
const repsRes = await axios.get(
WEBAPI_URL + repsQuery + hashAPIPath(repsQuery),
azureHeaders(token.access_token)
);
repsPeriods = repsRes.data.value;
const repsRecords = repsRes.data.value;
repsPeriods = repsRecords.filter((period) => {
if (!period.pinswg_consultationclose) {
return true;
}
return new Date(period.pinswg_consultationclose) >= now;
});
} catch (err) {
consoleLogger(
`Reps fetch failed for incidentID: ${incidentID}`
+33 -5
View File
@@ -14,13 +14,25 @@ const SignIn = (props) => {
const { footerLinks, pages, csrfToken, callbackUrl } = props;
const [buttonDisabled, setButtonDisabled] = useState(false);
const [emailError, setEmailError] = useState("");
const emailRegex =
/^(?!.*(?:.+\.)?(?:burpcollaborator\.net|interactsh\.com|mailinator\.com|10minutemail\.com|yopmail\.com|trashmail\.com)$)(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}|(?:\[(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:.+)])$/;
const handleSubmit = async (event) => {
event.preventDefault();
const email = String(event.target.email.value || "").trim();
if (!emailRegex.test(email)) {
setEmailError(t("account:invalid-email-address-errormsg"));
setButtonDisabled(false);
return;
}
setEmailError("");
setButtonDisabled(true);
try {
const email = String(event.target.email.value || "").trim();
const currentLocale = lang === "cy" ? "cy" : "en";
const response = await fetch("/api/auth/resolve-locale", {
@@ -103,7 +115,9 @@ const SignIn = (props) => {
action="/api/auth/signin/email"
onSubmit={handleSubmit}
>
<div className="govuk-form-group ">
<div
className={`govuk-form-group${emailError ? " govuk-form-group--error" : ""}`}
>
<input
className="govuk-input"
name="csrfToken"
@@ -113,7 +127,6 @@ const SignIn = (props) => {
}
/>
<input
className="govuk-input"
name="callbackUrl"
type="hidden"
defaultValue={
@@ -130,7 +143,6 @@ const SignIn = (props) => {
: "en"
}
/>
<label
className="govuk-label"
htmlFor="email"
@@ -139,12 +151,28 @@ const SignIn = (props) => {
"auth:auth-email-label"
)}
</label>
{emailError ? (
<span
id="email-error"
className="govuk-error-message"
>
<span className="govuk-visually-hidden">
Error:
</span>{" "}
{emailError}
</span>
) : null}
<input
className="govuk-input govuk-!-width-three-quarters"
className={`govuk-input govuk-!-width-three-quarters${emailError ? " govuk-input--error" : ""}`}
type="email"
id="email"
name="email"
aria-describedby={
emailError
? "email-error"
: undefined
}
/>
</div>
<div className="govuk-form-group">
+1 -1
View File
@@ -307,7 +307,7 @@ let ContactUs = (props) => {
value ? undefined : t("newappeal:is-required-label");
const emailRegex =
/^(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}|(?:\[(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:.+)])$/;
/^(?!.*(?:.+\.)?(?:burpcollaborator\.net|interactsh\.com|mailinator\.com|10minutemail\.com|yopmail\.com|trashmail\.com)$)(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}|(?:\[(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:.+)])$/;
const email = (value) =>
value && !emailRegex.test(value)
+1 -1
View File
@@ -307,7 +307,7 @@ let ContactUs = (props) => {
value ? undefined : t("newappeal:is-required-label");
const emailRegex =
/^(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}|(?:\[(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:.+)])$/;
/^(?!.*(?:.+\.)?(?:burpcollaborator\.net|interactsh\.com|mailinator\.com|10minutemail\.com|yopmail\.com|trashmail\.com)$)(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}|(?:\[(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:.+)])$/;
const email = (value) =>
value && !emailRegex.test(value)