471 lines
16 KiB
JavaScript
471 lines
16 KiB
JavaScript
import Link from "next/link";
|
|
import _, { has, last } from "lodash";
|
|
import { useRouter } from "next/router";
|
|
import useTranslation from "next-translate/useTranslation";
|
|
import { useState, useEffect } from "react";
|
|
import xpath from "xpath";
|
|
import BuildRow from "./buildrow";
|
|
import { reduxForm, formValueSelector, getFormSubmitErrors } from "redux-form";
|
|
import { useDispatch, useSelector, shallowEqual, connect } from "react-redux";
|
|
import {
|
|
setCaseReference,
|
|
setCurrentSection,
|
|
setDocumentsList,
|
|
setFilesForAppeal,
|
|
setNewAppealProgress,
|
|
} from "../../store/appealType/action";
|
|
import { getFormCollectionByID, getProgressObj } from "../utils";
|
|
import { updateCase, patchCase, uploadFiles, sendEmail } from "../../actions";
|
|
|
|
import { FieldsTranslations } from "../elements";
|
|
import jsonpath from "jsonpath";
|
|
import BuildProgress from "./buildprogress";
|
|
|
|
let BuildSection = (props) => {
|
|
const [currentSectionSelected, setCurrentSectionSelected] = useState(1);
|
|
const [pickupWhereLeftOff, setPickupWhereLeftOff] = useState(true);
|
|
|
|
const [savingStatus, setSavingStatus] = useState(false);
|
|
|
|
let { t } = useTranslation();
|
|
|
|
const router = useRouter();
|
|
const { locale } = router;
|
|
|
|
const {
|
|
formXML,
|
|
sectionCount,
|
|
onSubmit,
|
|
handleSubmit,
|
|
load,
|
|
pristine,
|
|
reset,
|
|
formTitle,
|
|
setCurrentSection,
|
|
refno,
|
|
gotoSection,
|
|
mandatoryFieldsData,
|
|
} = props;
|
|
|
|
const documentListObj = props.appealType.documentList;
|
|
const currentSection = props.appealType.currentSection;
|
|
|
|
const parser = new DOMParser();
|
|
var doc = parser.parseFromString(props.formXML, "text/xml");
|
|
var titles = xpath.select(
|
|
"//form/tabs/tab[" + currentSection + " ]/labels/label/@description",
|
|
doc
|
|
);
|
|
var rowXML = xpath.select(
|
|
"/form/tabs/tab[" +
|
|
currentSection +
|
|
"]/columns//sections/section/rows/row",
|
|
//"/form/tabs/tab/columns//sections/section/rows/row",
|
|
doc
|
|
);
|
|
|
|
var formObjXML = xpath.select("/form/tabs", doc);
|
|
|
|
var titleList = xpath.select(
|
|
"//form/tabs/tab[*]/labels/label/@description",
|
|
doc
|
|
);
|
|
|
|
const progObj = getProgressObj(
|
|
formXML,
|
|
titleList,
|
|
mandatoryFieldsData,
|
|
props
|
|
);
|
|
|
|
const isProgressComplete = (progObj) => {
|
|
const progressCount = 0;
|
|
|
|
for (let key in progObj) {
|
|
progObj[key].allFieldsComplete === true && progressCount++;
|
|
}
|
|
|
|
return progObj.length == progressCount;
|
|
};
|
|
|
|
const lastIndex = progObj
|
|
.map((whichIsLast) => whichIsLast.allFieldsComplete == true)
|
|
.lastIndexOf(true);
|
|
|
|
const handleParam = (setValue) => (e) => setValue(e.target.value);
|
|
|
|
const uploadAppealFiles = (values) => {
|
|
// get filelists from values object
|
|
let fileListObj = _.filter(values, function (v, key) {
|
|
return _.includes(key, "pinswg_fileUpload");
|
|
});
|
|
|
|
//console.log(fileListObj);
|
|
|
|
console.log(
|
|
"\n////////////////////////\n upload files:",
|
|
props.props.accountDetails.containerID
|
|
);
|
|
|
|
var dataObj = values;
|
|
|
|
for (let key in dataObj) {
|
|
_.includes(key, "pinswg_fileUpload") == true && delete dataObj[key];
|
|
}
|
|
|
|
uploadFiles(
|
|
dataObj,
|
|
fileListObj,
|
|
props.props.accountDetails.containerID,
|
|
props.props.appealType.caseReference.ticketnumber
|
|
).then((data) => {
|
|
//console.log("hello", data);
|
|
|
|
return data;
|
|
});
|
|
};
|
|
|
|
const updateCaseProgress = async (
|
|
values,
|
|
sendSavedEmail,
|
|
useSaveStatus
|
|
) => {
|
|
let incidentId = props.appealType.caseReference.incidentid;
|
|
let updateBody = values || {};
|
|
|
|
setSavingStatus(useSaveStatus);
|
|
uploadAppealFiles(values);
|
|
props.setNewAppealProgress(
|
|
getProgressObj(formXML, titleList, mandatoryFieldsData, props)
|
|
);
|
|
|
|
let appTypeCollection = getFormCollectionByID(
|
|
props.appealType.appealTypeID
|
|
);
|
|
let updateBindAppealTypeToIncident =
|
|
appTypeCollection.NavigationProperty;
|
|
|
|
Object.assign(updateBody, {
|
|
"pinswg_appealcasetype": props.appealType.appealTypeID,
|
|
"pinswg_Appellant@odata.bind":
|
|
"/contacts(" + props.props.accountDetails.loggedinUserId + ")",
|
|
"pinswg_name": props.appealType.caseReference.ticketnumber,
|
|
[updateBindAppealTypeToIncident + "@odata.bind"]:
|
|
"/incidents(" + incidentId + ")",
|
|
});
|
|
|
|
updateBody = JSON.stringify(updateBody);
|
|
updateBody = updateBody.replace(/:"Yes"/gm, `:true`);
|
|
updateBody = updateBody.replace(/:"No"/gm, `:false`);
|
|
updateBody = JSON.parse(updateBody);
|
|
|
|
Object.keys(updateBody).forEach((key) => {
|
|
if (updateBody[key] === null) {
|
|
delete updateBody[key];
|
|
}
|
|
if (key.indexOf("_") == 0) {
|
|
delete updateBody[key];
|
|
}
|
|
});
|
|
|
|
//console.log(updateBody);
|
|
|
|
let updateFormCollection = appTypeCollection.LogicalCollectionName;
|
|
let primaryAttribute = appTypeCollection.PrimaryIdAttribute;
|
|
|
|
const reference = "PEDW-PARTIAL";
|
|
const templateId = "021b0a7b-df00-41f1-b94e-c269bee98c75";
|
|
const templateIdCY = "f3c4a56b-bfb8-4d39-97dd-888df3062b0a";
|
|
const emailAddress = props.props.accountDetails.loggedinUserEmail;
|
|
const personalisation = {
|
|
"caseReference": props.appealType.caseReference.ticketnumber,
|
|
"emailAddress": props.props.accountDetails.loggedinUserEmail,
|
|
"returnLink":
|
|
props.props.url +
|
|
(router.locale != "en" ? "/cy/fymhorth/" : "/myportal/") +
|
|
appTypeCollection.UrlName +
|
|
"?lpa=" +
|
|
props.appealType.appealLPA +
|
|
"&apt=" +
|
|
appTypeCollection.appealTypeID +
|
|
"&casereference=" +
|
|
props.appealType.caseReference.ticketnumber +
|
|
"&inid=" +
|
|
props.appealType.caseReference.incidentid,
|
|
"linkExpiry": 10 * 60,
|
|
};
|
|
|
|
sendSavedEmail == true &&
|
|
sendEmail(
|
|
router.locale != "en" ? templateIdCY : templateId,
|
|
emailAddress,
|
|
personalisation,
|
|
reference
|
|
);
|
|
|
|
useSaveStatus &&
|
|
router.replace(
|
|
router.locale != "en"
|
|
? "/" + router.locale + "/myportal"
|
|
: "/myportal"
|
|
);
|
|
};
|
|
|
|
const onHandleSubmit = (values) => {
|
|
//if (currentSection == sectionCount) {
|
|
let valuesObj = values || {};
|
|
|
|
delete valuesObj["_pinswg_appellant_value"];
|
|
console.log("has errors:", props.invalid);
|
|
props.invalid == false && updateCaseProgress(valuesObj, false, false);
|
|
|
|
setCurrentSection(currentSection + 1);
|
|
};
|
|
|
|
const [hasErrors, setHasErrors] = useState("");
|
|
|
|
const getErrors = () => {
|
|
let errorsobj = props.props.form["appealForm"];
|
|
//setHasErrors(errorsobj.hasOwnProperty("syncErrors"));
|
|
window.scrollTo(0, 0);
|
|
};
|
|
|
|
let errorsobj = {};
|
|
const ShowErrorHeader = (props) => {
|
|
errorsobj = props.props.appealForm.syncErrors;
|
|
errorsobj = _.keys(errorsobj);
|
|
|
|
const getErrorLabel = (whichField) => {
|
|
var doc = parser.parseFromString(props.formXML, "text/xml");
|
|
var errorFieldLabel = xpath.select(
|
|
"//*[control/@id='" + whichField + "']//@description",
|
|
doc
|
|
);
|
|
|
|
return errorFieldLabel[0].value;
|
|
};
|
|
|
|
const ShowErrors = () => {
|
|
let errorList = [];
|
|
for (let i = 0; i < errorsobj.length; ++i) {
|
|
//get label from error key - search rowxml for id = errorobj
|
|
|
|
errorList.push(
|
|
<li key={i}>
|
|
<a href={"#" + errorsobj[i] + "_label"}>
|
|
{" "}
|
|
{getErrorLabel(errorsobj[i])}
|
|
</a>
|
|
</li>
|
|
);
|
|
}
|
|
|
|
return errorList;
|
|
};
|
|
|
|
return !_.isEmpty(errorsobj) ? (
|
|
<div
|
|
className="govuk-error-summary"
|
|
aria-labelledby="error-summary-title"
|
|
role="alert"
|
|
tabIndex="-1"
|
|
data-module="govuk-error-summary"
|
|
>
|
|
<h2
|
|
className="govuk-error-summary__title"
|
|
id="error-summary-title"
|
|
>
|
|
The following fields have a problem :
|
|
</h2>
|
|
<div className="govuk-error-summary__body">
|
|
<ul className="govuk-list govuk-error-summary__list">
|
|
<ShowErrors />
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
""
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div className="govuk-grid-row">
|
|
<div className="govuk-grid-column-two-thirds">
|
|
<h1 className="govuk-heading-m govuk-!-margin-top-5">
|
|
{FieldsTranslations(titles[0].value)}
|
|
</h1>
|
|
<form onSubmit={handleSubmit(onHandleSubmit)}>
|
|
{hasErrors == true ? (
|
|
<ShowErrorHeader
|
|
hasErrors={hasErrors}
|
|
props={props.props.form}
|
|
formXML={formXML}
|
|
/>
|
|
) : (
|
|
""
|
|
)}
|
|
<BuildRow
|
|
rowXML={rowXML}
|
|
whichSection={props.whichSection}
|
|
sectionCount={props.sectionCount}
|
|
onSubmit={onSubmit}
|
|
mandatoryFieldsData={mandatoryFieldsData}
|
|
props={props}
|
|
/>
|
|
|
|
<div className="govuk-button-group">
|
|
{props.sectionCount != currentSection ? (
|
|
<button
|
|
type="submit"
|
|
className="govuk-button"
|
|
data-module="govuk-button"
|
|
onClick={() => {
|
|
getErrors();
|
|
let valuesObj = _.has(
|
|
props.props.form[props.form],
|
|
"values"
|
|
)
|
|
? props.props.form[props.form].values
|
|
: {};
|
|
|
|
//console.log("valuesobj:", valuesObj);
|
|
|
|
delete valuesObj["_pinswg_appellant_value"];
|
|
|
|
//console.log("on save:", valuesObj);
|
|
updateCaseProgress(valuesObj, false, false);
|
|
}}
|
|
>
|
|
{t("common:continue-button")}
|
|
</button>
|
|
) : (
|
|
""
|
|
)}
|
|
{props.sectionCount == currentSection ? (
|
|
<button
|
|
disabled={!isProgressComplete(progObj)}
|
|
type="submit"
|
|
className="govuk-button"
|
|
data-module="govuk-button"
|
|
>
|
|
{t("common:submit-button")}
|
|
</button>
|
|
) : (
|
|
""
|
|
)}
|
|
{currentSection > 1 ? (
|
|
<a
|
|
className="govuk-link"
|
|
href="#"
|
|
onClick={() =>
|
|
setCurrentSection(currentSection - 1)
|
|
}
|
|
>
|
|
{t("common:back-link")}
|
|
</a>
|
|
) : (
|
|
""
|
|
)}
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div className="govuk-grid-column-one-third">
|
|
<div className="at-nav-container">
|
|
{/* <span>
|
|
Last section is {lastIndex} - {currentSection}
|
|
</span> */}
|
|
<BuildProgress
|
|
progObj={progObj}
|
|
props={props}
|
|
titleList={titleList}
|
|
documentListObj={documentListObj}
|
|
formObjXML={formXML}
|
|
mandatoryFieldsData={mandatoryFieldsData}
|
|
currentSection={currentSection}
|
|
initialValues={props.initialValues}
|
|
setCurrentSection={setCurrentSection}
|
|
/>
|
|
|
|
<hr className="govuk-section-break govuk-section-break--m govuk-section-break--visible" />
|
|
|
|
{savingStatus ? (
|
|
<span className=" progress-save-active">
|
|
Saving data
|
|
<img
|
|
className="data-loading-icon"
|
|
src="/assets/images/loading.gif"
|
|
alt={
|
|
router.locale == "cy"
|
|
? "Nôl data"
|
|
: "Saving data"
|
|
}
|
|
/>
|
|
</span>
|
|
) : (
|
|
<button
|
|
className="govuk-button govuk-button--secondary progress-save "
|
|
onClick={() => {
|
|
let valuesObj =
|
|
props.props.form[props.form].values || {};
|
|
|
|
console.log("valuesobj:", valuesObj);
|
|
|
|
delete valuesObj["_pinswg_appellant_value"];
|
|
|
|
console.log("on save:", valuesObj);
|
|
updateCaseProgress(valuesObj, true, true);
|
|
}}
|
|
>
|
|
{t("common:save-exit-button")}
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const mapStateToProps = (state) => {
|
|
return {
|
|
search: state.search,
|
|
searchResultsObj: state.searchResultsObj,
|
|
formData: state.formData,
|
|
appealType: state.appealType,
|
|
initialValues: state.appealType.caseReference.caseDetails,
|
|
//form: state.form,
|
|
};
|
|
};
|
|
|
|
const mapDispatchToProps = (dispatch) => {
|
|
return {
|
|
setCurrentSection: (currentSection) => {
|
|
dispatch(setCurrentSection(currentSection));
|
|
},
|
|
gotoSection: (thisSection) => {
|
|
dispatch(setCurrentSection(thisSection));
|
|
},
|
|
setDocumentsList: (documentList) => {
|
|
dispatch(setDocumentsList(documentList));
|
|
},
|
|
setFilesForAppeal: (blobList) => {
|
|
dispatch(setFilesForAppeal(blobList));
|
|
},
|
|
setNewAppealProgress: (progressObj) => {
|
|
dispatch(setNewAppealProgress(progressObj));
|
|
},
|
|
};
|
|
};
|
|
|
|
const selector = formValueSelector("appealForm"); // <-- same as form name
|
|
|
|
export default connect(
|
|
mapStateToProps,
|
|
mapDispatchToProps
|
|
)(
|
|
reduxForm({
|
|
form: "appealForm",
|
|
destroyOnUnmount: false,
|
|
enableReinitialize: true, // this is needed!!
|
|
})(BuildSection)
|
|
);
|