Files
pedwfrontend/pages/myportal/contactus.js
T
2026-05-14 08:55:49 +00:00

570 lines
21 KiB
JavaScript

import useTranslation from "next-translate/useTranslation";
import Head from "next/head";
import { useRouter } from "next/router";
import Breadcrumbs from "../../components/breadcrumbs";
import CookieBanner from "../../components/cookieBanner";
import Footer from "../../components/footer";
import Header from "../../components/header";
import ServiceBanner from "../../components/myportal/servicebanner";
import Link from "next/link";
import {
Field,
change,
formValueSelector,
reduxForm,
touch,
SubmissionError
} from "redux-form";
import { connect } from "react-redux";
import { createCRMTask } from "../../actions/services/integrationService";
import { sendEmail } from "../../actions/services/notifyService";
import { useState } from "react";
const RenderPickList = ({
datafieldname,
picklistData,
id,
name,
label,
input,
errorMsg,
meta: { touched, error }
}) => {
let { t } = useTranslation();
const required = (value) => {
return value || value == 0
? undefined
: t("newappeal:is-required-label");
};
return (
<>
<div
className={
touched && error
? "govuk-form-group govuk-!-margin-bottom-1 govuk-form-group--error"
: "govuk-form-group govuk-!-margin-bottom-1"
}
>
<label className="govuk-label " htmlFor={id} id={id + "_label"}>
{label}
</label>
{touched && error && (
<span id={id + "-error"} className="govuk-error-message">
<span className="govuk-visually-hidden">Error:</span>{" "}
{error}
</span>
)}
<select
{...input}
className="govuk-select govuk-input--width-20"
id={id}
name={id}
>
<option value="" disabled defaultValue>
{t("newappeal:select-default")}
</option>
<option value="plq">
{t("common:contact-us-select-plq")}
</option>
<option value="ipq">
{t("common:contact-us-select-ipq")}
</option>
<option value="pcpq">
{t("common:contact-us-select-pcpq")}
</option>
<option value="pi">
{t("common:contact-us-select-pi")}
</option>
<option value="appadvice">
{t("common:contact-us-select-appadvice")}
</option>
<option value="repadvice">
{t("common:contact-us-select-repadvice")}
</option>
<option value="ceq">
{t("common:contact-us-select-ceq")}
</option>
<option value="other">
{t("common:contact-us-select-other")}
</option>
<option value="postdec">
{t("common:contact-us-select-postdec")}
</option>
<option value="comp">
{t("common:contact-us-select-comp")}
</option>
</select>
</div>
</>
);
};
const RenderMultiline = ({
id,
className,
rows,
cols,
datafieldname,
name,
label,
input,
errorMsg,
meta: { touched, error },
...custom
}) => {
return (
<>
<div
className={
touched && error
? "govuk-form-group govuk-form-group--error"
: "govuk-form-group "
}
>
<label className="govuk-label " htmlFor={id} id={id + "_label"}>
{label}
</label>
{touched && error && (
<span id={id + "-error"} className="govuk-error-message">
<span className="govuk-visually-hidden">Error:</span>{" "}
{errorMsg || error}
</span>
)}
<textarea
id={id}
name={id}
rows={rows}
cols={cols}
className={className}
{...input}
maxLength={
Object.prototype.hasOwnProperty.call(
custom,
"maxFieldLength"
)
? custom.maxFieldLength
? custom.maxFieldLength
: 800
: 800
}
></textarea>
</div>
</>
);
};
const RenderTextfield = ({
id,
className,
rows,
datafieldname,
name,
label,
input,
errorMsg,
meta: { touched, error },
...custom
}) => {
return (
<>
<div
className={
touched && error
? "govuk-form-group govuk-form-group--error"
: "govuk-form-group "
}
>
<label className="govuk-label " htmlFor={id} id={id + "_label"}>
{label}
</label>
{touched && error && (
<span id={id + "-error"} className="govuk-error-message">
<span className="govuk-visually-hidden">Error:</span>{" "}
{errorMsg || error}
</span>
)}
<input
{...input}
type={"email"}
className={className}
name={id || name}
id={id || name}
maxLength={
Object.prototype.hasOwnProperty.call(
custom,
"maxFieldLength"
)
? custom.maxFieldLength
? custom.maxFieldLength
: 100
: 200
}
pattern={
Object.prototype.hasOwnProperty.call(custom, "pattern")
? custom.pattern
: undefined
}
/>
</div>
</>
);
};
const contactPurpose = (contactValue) => {
let contactPurposeBody;
switch (contactValue) {
case "plq":
contactPurposeBody = (
<p className="govuk-body">
Questions about Planning legislation or policy
</p>
);
break;
case "ipq":
contactPurposeBody = (
<p className="govuk-body">
Questions or comments about applications for major
infrastructure projects
</p>
);
break;
case "pcpq":
contactPurposeBody = (
<p className="govuk-body">
Questions or comments about planning and environmental
appeals
</p>
);
break;
case "pi":
contactPurposeBody = (
<p className="govuk-body">
Query about using the Casework Portal
</p>
);
break;
case "appadvice":
contactPurposeBody = (
<p className="govuk-body">Advice How to submit an appeal</p>
);
break;
case "repadvice":
contactPurposeBody = (
<p className="govuk-body">
Advice How to comment on an appeal or application
</p>
);
break;
case "ceq":
contactPurposeBody = (
<p className="govuk-body">
Queries about forthcoming Hearing or Inquiry event
</p>
);
break;
case "other":
contactPurposeBody = (
<p className="govuk-body">Other enquiry for PEDW</p>
);
break;
case "postdec":
contactPurposeBody = (
<p className="govuk-body">
Issues or questions about a case after the decision is
issued
</p>
);
break;
case "comp":
contactPurposeBody = (
<p className="govuk-body">General Complaints of Compliments</p>
);
break;
default:
// code block
}
return contactPurposeBody;
};
let t;
let ContactUs = (props) => {
const { footerLinks, pages } = props;
let { t } = useTranslation();
const [formSubmitted, setFormSubmitted] = useState(false);
const router = useRouter();
const { locale } = router;
const required = (value) =>
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]:.+)])$/;
const email = (value) =>
value && !emailRegex.test(value)
? t("account:invalid-email-address-errormsg")
: undefined;
const onSubmit = async (formValues) => {
// Only called if validation passes
sendContactEmail(formValues);
createCRMTask(formValues);
formValues.typeOfContact == "plq" &&
sendPETEmail(formValues, props.petEmail);
console.log("Form submitted:", formValues);
};
const sendContactEmail = async (formValues) => {
Object.assign(formValues, {
"contactSubject": contactPurpose(formValues.typeOfContact).props
.children
});
const reference = "PEDW-CONTACT-US";
const templateId = "69228c5f-8500-40ff-a6c5-95a9434c3ec8";
const templateIdCY = "b8f1f76d-4ab9-4a2f-b294-e3623c6095a3";
try {
const res = await sendEmail(
router.locale !== "en" ? templateIdCY : templateId,
formValues.contactEmail,
formValues,
reference
);
console.log("Email sent successfully.");
setFormSubmitted(true);
} catch (error) {
console.error("Email sending failed:", error);
alert("Something went wrong. Please try again later.");
// Required: inform redux-form this is a submit error
throw new SubmissionError({
_error: "Failed to send email. Please try again later."
});
}
};
const sendPETEmail = async (formValues, petEmail) => {
const reference = "PEDW-CONTACT-US-PET";
const templateId = "56bbdcf9-d63d-48e9-a794-3e253dd7498b";
const templateIdCY = "00b794d3-29aa-434d-b696-0ef0b0337d79";
console.log(petEmail);
try {
const res = await sendEmail(
templateId,
petEmail,
formValues,
reference
);
console.log("Email sent successfully.");
setFormSubmitted(true);
} catch (error) {
console.error("Email sending failed:", error);
alert("Something went wrong. Please try again later.");
// Required: inform redux-form this is a submit error
throw new SubmissionError({
_error: "Failed to send email. Please try again later."
});
}
};
return (
<div>
<Head>
<title>{t("common:service-name")}</title>
</Head>
<div id="page_wrapper">
<CookieBanner />
<Header />
<div className="govuk-width-container">
<Breadcrumbs />
<ServiceBanner props={props} />
<main
className="govuk-main-wrapper govuk-!-padding-top-9 govuk-main-wrapper--auto-spacing"
id="main-content"
role="main"
>
<div className="govuk-grid-row">
<div className="govuk-grid-column-full">
<h2 className="govuk-heading-l govuk-!-margin-bottom-7">
{t("common:footer-contact-us-link-label")}
</h2>
<div className="wgForm">
{formSubmitted ? (
<div className="govuk-panel govuk-panel--confirmation">
<h1 className="govuk-panel__title">
{t(
"common:contact-us-thank-you-title"
)}
</h1>
<div className="govuk-panel__body">
{t(
"common:contact-us-thank-you-sub"
)}
</div>
</div>
) : (
<>
<p className="govuk-body">
{t("common:contact-us-para")}
</p>
<form
onSubmit={props.handleSubmit(
onSubmit
)}
>
<Field
name={"contactEmail"}
id={"contactEmail"}
label={t(
"common:contact-us-email-label"
)}
component={RenderTextfield}
validate={[required, email]}
className="govuk-input govuk-input--width-20"
type="email"
/>
<Field
name="typeOfContact"
id="typeOfContact"
component={RenderPickList}
label={t(
"common:contact-us-contact-type-label"
)}
validate={[required]}
/>
<div className="govuk-form-group">
{props.typeOfContactValue && (
<div>
{contactPurpose(
props.typeOfContactValue
)}
</div>
)}
</div>
<Field
name="contactbody"
id="contactbody"
component={RenderMultiline}
label={t(
"common:contact-us-contact-body-label"
)}
rows={10}
cols={80}
validate={[required]}
/>
<button
type="submit"
className="govuk-button"
>
{t(
"common:contact-us-send-button"
)}
</button>
<button
type="button"
className="govuk-button govuk-button--secondary govuk-!-margin-left-5"
onClick={props.reset}
>
{t(
"common:contact-us-clear-form-button"
)}
</button>
</form>
</>
)}
</div>
</div>
</div>
</main>
</div>
<Footer footerLinks={footerLinks} ticketnumber={props} />
</div>
</div>
);
};
const selector = formValueSelector("contactUsForm"); // <-- same as form name
// ContactUs = connect((state) => {
// const typeOfContactValue = selector(state, "typeOfContact");
// return {
// typeOfContactValue,
// initialValues: {
// contactEmail:
// state.accountDetails.accountDetails?.emailaddress1 || "",
// },
// };
// })(ContactUs);
const mapDispatchToProps = (dispatch) => ({});
const mapStateToProps = (state) => {
const typeOfContactValue = selector(state, "typeOfContact");
const email = state.accountDetails.accountDetails?.emailaddress1;
return {
accountDetails: state.accountDetails,
typeOfContactValue,
initialValues: email ? { contactEmail: email } : {},
petEmail: process.env.NEXT_PUBLIC_PETEMAIL
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(
reduxForm({
form: "contactUsForm",
enableReinitialize: true,
destroyOnUnmount: false,
touchOnBlur: true,
touchOnChange: true,
onSubmitFail: (errors, dispatch, submitError, props) => {
if (errors) {
// Touch all fields with errors so validation messages appear
const errorFields = Object.keys(errors);
dispatch(touch("contactUsForm", ...errorFields));
// Scroll to first error
const firstErrorField = errorFields[0];
const errorElement = document.querySelector(
`[name="${firstErrorField}"]`
);
if (
errorElement &&
typeof errorElement.scrollIntoView === "function"
) {
errorElement.scrollIntoView({
behavior: "smooth",
block: "center"
});
errorElement.focus({ preventScroll: true });
} else {
console.warn(
"Could not find element for error field:",
firstErrorField
);
}
}
console.log("Redux Form onSubmitFail:", submitError);
}
})(ContactUs)
);