Files
pedwfrontend/components/case/representation/index.js
T
Robert Bond a25ab433a6 Merged PR 2279: passed in case customer email in search and update rep logic to stop non owne...
passed in case customer email in search and update rep logic to stop non owners rasing reps on other owners cases

Related work items: #22095
2026-04-28 12:00:12 +00:00

1290 lines
44 KiB
JavaScript

import { JSONPath as jsonpath } from "jsonpath-plus";
import useTranslation from "next-translate/useTranslation";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { connect } from "react-redux";
import { reduxForm } from "redux-form";
import { useSession } from "next-auth/react";
import {
generateRepPDF,
uploadRepFiles
} from "../../../actions/services/documentService";
import { sendEmail } from "../../../actions/services/notifyService";
import { formatDates, updateLinks } from "../../../components/utils";
import {
setRepresentationCapacity,
setRepresentationMessageSent,
setRepresentationReset,
setRepresentationSubmit,
setRepresentationSubmitConfirmation
} from "../../../store/currentView/action";
import ConsultationAgent from "./consultationAgent";
import ConsultationAppellant from "./consultationAppellant";
import ConsultationInterestedPartyPerson from "./consultationInterestedPartyPerson";
import RepAgent from "./representationAgent";
import RepAppellant from "./representationAppellant";
import RepCapacitySelection from "./representationCapacitySelection";
import RepCompleteSubmit from "./representationCompleteSubmit";
import RepInterestedPartyPerson from "./representationInterestedPartyPerson";
import RepLPA from "./representationLPA";
import RepLPACapacitySelection from "./representationLPACapacitySelection";
import RepLandOwner from "./representationLandowner";
import RepresentationProgress_enforcement from "./representationProgress/representationProgress_enforcement";
import RepresentationProgress_s78 from "./representationProgress/representationProgress_s78";
import RepresentationFlowFormStage from "./shell/RepresentationFlowFormStage";
import {
getQuestionnaireNextSection,
resolveJourneyStageFlags,
resolveRepresentationControlKey,
resolveSubmitTransition
} from "./utils/stepResolution";
import {
findDetailsObjForSubmit,
findDetailsObjForView,
findResultsObjForCurrentReference,
resolveInitialCaseDataSources,
resolveSubmitCaseDetailsSource
} from "./utils/dataResolution";
import {
buildRepresentationUpdateBody,
buildSubmitEnrichedValues,
runFinalisationSequence
} from "./utils/finalisationBoundary";
let MakeRepresentation = (props) => {
let { t } = useTranslation();
const [savingStatus, setSavingStatus] = useState(false);
const [finaliseAppealProcess, setFinaliseAppealProcess] = useState(false);
const [representationTypeConfirmed, setRepresentationTypeConfirmed] =
useState(
!!props?.currentView?.caseReference?.repDetails?.representationType
);
//const [questionnaireCount, setQuestionnaireCount] = useState(0);
const { data: session } = useSession();
const router = useRouter();
const { locale } = router;
const {
caseReference,
myCases,
myRepresentations,
watchedCases,
awaitingSubmission,
searchResultsObj,
representationSubmit,
currentType,
currentView,
setRepresentationCapacity,
setRepresentationSubmit,
setSubmitBack,
handleSubmit,
setRepresentationSubmitConfirmation,
setRepresentationMessageSent,
setShowQuestionnaireSection,
showQuestionnaireSection,
initialValues,
setCurrentReference,
ticketnumber,
docsOffline
} = props;
const formObj = props.props.form;
let setCaseQueryObj = props[currentType] || {};
var casesObj = {};
const appealType = currentView.caseReference.appealType;
const accountDetails = props.props.accountDetails.accountDetails;
const caseReferenceObj = props.props.currentView.caseReference;
const updateQuestionnaireCount = () => {
const countMap = {
846040000: 7,
846040001: 7,
846040025: 7,
846040004: 7,
846040018: 7,
846040003: 7,
846040009: 7,
846040008: 7,
846040005: 9,
846040006: 9,
846040007: 9
};
return countMap[appealType] || 7;
};
let questionnaireCount = updateQuestionnaireCount();
const isLPA =
accountDetails?.[
"pinswg_typeofinvolvement@OData.Community.Display.V1.FormattedValue"
] == "LPA"
? true
: false;
const isNRW = currentView.caseReference?.isNRW;
const { showCheckStage } = resolveJourneyStageFlags({
"representationSubmit": currentView.representationSubmit,
"representationSubmitConfirmation":
currentView.representationSubmitConfirmation
});
const setRepFileName = (values) => {
if (
!values.hasOwnProperty("representationCapacity") ||
!values.hasOwnProperty("representationType")
) {
return values;
}
const repCapMap = {
[t("myrepresentations:capacity-options-arr-appellant")]: "APP",
[t("myrepresentations:capacity-options-arr-agent")]: "APP", // agent treated as appellant proxy
[t("myrepresentations:capacity-options-arr-interested")]: "IP",
"Land Owner": "LO",
lpa: "LPA",
LPA: "LPA",
NRW: "NRW"
};
const repTypeMap = {
Statement: "Statement",
"Statement of common ground": "SCG",
"Written statement": "WS",
"Written statement of evidence": "WSE",
Questionnaire: "Questionnaire",
"Final comments": "Comments",
"Consultation Response": "Consultation_Response",
"Local Impact Report": "Local_Impact_Report",
"Marine Impact Report": "Marine_Impact_Report",
Other: "OTHER"
};
const now = new Date();
const pad = (num) => String(num).padStart(2, "0");
const dateStr = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(
now.getDate()
)}-${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(
now.getSeconds()
)}`;
const repCap = repCapMap[values.representationCapacity] || "";
const repType = repTypeMap[values.representationType] || "";
const sanitize = (str) =>
str.replace(/[\s~`!@#$%^&*(){}\[\];:"'<,.>?\/\\|_+=-]/g, "");
const namePart = isLPA
? sanitize(values.onBehalfOfLPA || "")
: `${sanitize(values.lastname || "")}_${sanitize(
values.firstname || ""
)}`;
values.repfile_name =
values.repfile_name ||
`${dateStr}_-_${repCap}_-_${repType}_-_${namePart}`;
return values;
};
useEffect(() => {
if (isLPA && !currentView?.representationCapacity) {
setRepresentationCapacity("LPA");
}
}, [isLPA, currentView?.representationCapacity, setRepresentationCapacity]);
const normalizeCapacity = (rawCapacity) => {
const normalized = (rawCapacity || "")
.toString()
.toLowerCase()
.replace(/(\band|[\s\-\+\(\)\,\&])/g, "");
const capacityMap = {
appellant: "appellant",
apelydd: "appellant",
agent: "agent",
asiant: "agent",
interestedparty: "interestedparty",
lpa: "lpa",
landowner: "landowner",
[t("myrepresentations:capacity-options-arr-appellant")
.toLowerCase()
.replace(/(\band|[\s\-\+\(\)\,\&])/g, "")]: "appellant",
[t("myrepresentations:capacity-options-arr-agent")
.toLowerCase()
.replace(/(\band|[\s\-\+\(\)\,\&])/g, "")]: "agent",
[t("myrepresentations:capacity-options-arr-interested")
.toLowerCase()
.replace(/(\band|[\s\-\+\(\)\,\&])/g, "")]: "interestedparty"
};
return capacityMap[normalized] || normalized || "false";
};
const getCasePath = () => {
switch (currentType) {
case "searchResultsObj":
return {
path: `$..[?(@ && @.title=="${caseReference}")]`,
json: setCaseQueryObj
};
case "watchedCases":
return {
path: `$..[?(@ && @.ticketnumber=="${caseReference}")]`,
json: watchedCases
};
default:
return {
path: `$..[?(@ && @.ticketnumber=="${ticketnumber}")]`,
json: setCaseQueryObj
};
}
};
const { path, json } = getCasePath();
casesObj = jsonpath({ path, json, eval: true });
casesObj = Object.assign({}, ...casesObj);
var detailsObj = {};
// const isAppellant =
// props.props.accountDetails.accountDetails.pinswg_typeofinvolvement ===
// 846040001;
const isAppellant =
props.props.accountDetails.accountDetails.emailaddress1 ==
props.searchResultsObj?.searchResultsObj?.value[0].customerid_contact
.emailaddress1;
const capacityOptionsArr = [];
isAppellant &&
capacityOptionsArr.push(
t("myrepresentations:capacity-options-arr-appellant")
);
const shouldIncludeInterested =
appealType !== 846040017 ||
caseReferenceObj.specialistProcess !== 846040000;
if (shouldIncludeInterested) {
capacityOptionsArr.push(
t("myrepresentations:capacity-options-arr-interested"),
t("myrepresentations:capacity-options-arr-agent")
);
}
const isEditState = router.query.state === "edit";
const hasState = router.query.hasOwnProperty("state");
const { caseDetailsSource, caseResultsSource } =
resolveInitialCaseDataSources({
hasState,
isEditState,
currentType: props.currentType,
myRepresentations: props.props.myRepresentations.myRepresentations,
searchDetailsObj: props.props.searchResultsObj.searchDetailsObj,
searchResultsObj: props.props.searchResultsObj.searchResultsObj,
watchedCasesDetails: props.props.watchedCases.watchedCasesDetails
});
let resultsObj = findResultsObjForCurrentReference({
"currentReference": currentView.caseReference.currentReference,
"caseResultsSource": caseResultsSource
});
// let detailsObj;
detailsObj = findDetailsObjForView({
hasState,
isEditState,
"queryCreated": router.query.created,
"ticketnumber": currentView.caseReference.ticketnumber,
"caseDetailsSource": caseDetailsSource
});
const safeDetailsObj = detailsObj || {};
const safeResultsObj = resultsObj || {};
// blocked out build reps arr for refactoring
// const buildRepsArr = (detailsObj) => {
// const buildArr = [];
// const todaysDate = new Date();
// const isDNS = appealType === 846040011;
// const isSIPS = appealType === 846040002;
// const isIP = true;
// const isAppellant =
// props.props.accountDetails.accountDetails
// .pinswg_typeofinvolvement === 846040001;
// // Determine key dates based on appeal type
// const startDate = new Date(
// isDNS
// ? detailsObj.pinswg_applicationacceptedasvalid
// : detailsObj.pinswg_startdate || detailsObj.pinswg_startdates
// );
// const questionnaireDate = new Date(
// isDNS
// ? detailsObj.pinswg_endofrepresentationperiod
// : detailsObj.pinswg_questionnaireduedate
// );
// questionnaireDate.setHours(23, 59, 59, 999);
// const finalCommentsDate = new Date(
// isDNS
// ? detailsObj.pinswg_endofrepresentationperiod
// : detailsObj.pinswg_finalcommentsduedate
// );
// finalCommentsDate.setHours(23, 59, 59, 999);
// const statementDueDate = new Date(
// isDNS
// ? detailsObj.pinswg_endofrepresentationperiod
// : detailsObj.pinswg_statementduedate ||
// detailsObj.pinswg_statementsduedate
// );
// statementDueDate.setHours(23, 59, 59, 999);
// // Shared condition
// const isWithin = (start, end) =>
// todaysDate >= start && todaysDate <= end;
// const notAppeal = (...types) => !types.includes(appealType);
// // Questionnaire
// if (
// isLPA &&
// notAppeal(846040019, 846040011, 846040015, 846040016) &&
// isWithin(startDate, finalCommentsDate)
// ) {
// buildArr.push("Questionnaire");
// }
// // DNS LPA Documents
// if (
// isLPA &&
// isDNS &&
// appealType !== 846040019 &&
// isWithin(startDate, finalCommentsDate)
// ) {
// buildArr.push("Local Impact Report", "Statement");
// }
// // Non-DNS Statement
// if (
// !isDNS &&
// appealType !== 846040004 &&
// isWithin(startDate, statementDueDate)
// ) {
// buildArr.push("Statement");
// }
// // DNS Non-LPA Statement
// if (isDNS && !isLPA && isWithin(startDate, statementDueDate)) {
// buildArr.push("Statement");
// }
// // Final Comments
// const isSpecialistNonHearing =
// currentView.caseReference.specialistProcess !== 846040001;
// if (
// (appealType !== 846040004 ||
// (appealType === 846040015 && isSpecialistNonHearing)) &&
// isWithin(statementDueDate, finalCommentsDate)
// ) {
// buildArr.push("Final comments");
// }
// if (
// appealType === 846040004 &&
// isSpecialistNonHearing &&
// isWithin(statementDueDate, finalCommentsDate)
// ) {
// buildArr.push("Final comments");
// }
// // Remove "Statement" for LPA Advert Part 3 (no statement)
// if (
// isLPA &&
// appealType === 846040018 &&
// currentView.caseReference.specialistProcess === 846040000
// ) {
// const index = buildArr.indexOf("Statement");
// if (index !== -1) buildArr.splice(index, 1);
// }
// // SIPS-related documents
// if (isSIPS) {
// const capacity = repCapacityType();
// if (capacity === "appellant") {
// buildArr.push("Consultation Response");
// } else {
// buildArr.push("Consultation Response", "Local Impact Report");
// }
// if (isNRW) {
// buildArr.push("Marine Impact Report");
// }
// }
// return buildArr;
// };
const buildRepsArr = (detailsObj) => {
const buildArr = [];
const todaysDate = new Date();
const isDNS = appealType === 846040011;
const isSIPS = appealType === 846040002;
const specialistProcess = currentView.caseReference.specialistProcess;
const isSpecialistNonHearing = specialistProcess !== 846040001;
const involvementType =
props.props?.accountDetails?.accountDetails
?.pinswg_typeofinvolvement;
const isAppellant = involvementType === 846040001;
const isAgent = involvementType === 846040000;
const isIP = involvementType === 846040061;
//const isLPA = involvementType === 846040000;
const startDate = new Date(
isDNS
? detailsObj.pinswg_applicationacceptedasvalid
: detailsObj.pinswg_startdate || detailsObj.pinswg_startdates
);
const finalCommentsDate = new Date(
isDNS
? detailsObj.pinswg_endofrepresentationperiod
: detailsObj.pinswg_finalcommentsduedate
);
finalCommentsDate.setHours(23, 59, 59, 999);
const statementDueDate = new Date(
isDNS
? detailsObj.pinswg_endofrepresentationperiod
: detailsObj.pinswg_statementduedate ||
detailsObj.pinswg_statementsduedate
);
statementDueDate.setHours(23, 59, 59, 999);
const isWithin = (start, end) =>
todaysDate >= start && todaysDate <= end;
const addRep = (value) => {
if (!buildArr.includes(value)) {
buildArr.push(value);
}
};
const canAddQuestionnaire =
isLPA &&
![846040019, 846040011, 846040015, 846040016].includes(
appealType
) &&
isWithin(startDate, finalCommentsDate);
if (canAddQuestionnaire) {
addRep("Questionnaire");
}
const isLpaAdvertPart3NoStatement =
isLPA &&
appealType === 846040018 &&
specialistProcess === 846040000;
const canAddDnsLpaDocs =
isLPA &&
isDNS &&
appealType !== 846040019 &&
!isAppellant &&
isWithin(startDate, finalCommentsDate);
if (canAddDnsLpaDocs) {
addRep("Local Impact Report");
addRep("Statement");
}
const canAddStatementForNonDns =
!isDNS &&
appealType !== 846040004 &&
!isLpaAdvertPart3NoStatement &&
!isAppellant &&
isWithin(startDate, statementDueDate);
if (canAddStatementForNonDns) {
addRep("Statement");
}
const canAddStatementForDnsNonLpa =
isDNS &&
!isLPA &&
!isAppellant &&
isWithin(startDate, statementDueDate);
if (canAddStatementForDnsNonLpa) {
addRep("Statement");
}
const canSubmitFinalComments = isAppellant || isAgent || isIP || isLPA;
const canAddFinalComments =
canSubmitFinalComments &&
isWithin(statementDueDate, finalCommentsDate) &&
(appealType !== 846040004 || isSpecialistNonHearing);
// IP and Agents and LPA can do final comments.
if (canAddFinalComments) {
addRep("Final comments");
}
if (isSIPS) {
const capacity = repCapacityType();
addRep("Consultation Response");
if (capacity !== "appellant") {
addRep("Local Impact Report");
}
if (isNRW) {
addRep("Marine Impact Report");
}
}
return buildArr;
};
const repCapacityType = () => {
const repForm = formObj["representationForm"];
if (
!repForm ||
!repForm.values ||
!repForm.values.representationCapacity
) {
return false;
}
return repForm.values.representationCapacity
.replace(/(\band|[\s\-\+\(\)\,\&])/g, "")
.toLowerCase();
};
const whichControl = () => {
const commonProps = {
formObj,
setRepresentationCapacity,
setRepresentationSubmit,
onHandleSubmit,
currentView,
setSubmitBack,
props,
setRepFileName,
updateRepresentation,
setSavingStatus,
savingStatus,
setCurrentReference,
onRepresentationTypeChange: () =>
setRepresentationTypeConfirmed(false),
onTypeSelectionConfirmed: () => setRepresentationTypeConfirmed(true)
};
const { controlKey } = resolveRepresentationControlKey({
"isLPA": isLPA,
"representationCapacity": currentView.representationCapacity,
"repDetailsCapacity":
currentView.caseReference?.repDetails?.representationCapacity,
"appealType": appealType,
"normalizeCapacity": normalizeCapacity
});
if (controlKey === "lpa-capacity-selection") {
return (
<RepLPACapacitySelection
{...commonProps}
capacityOptionsArr={capacityOptionsArr}
currentType={currentType}
casesObj={casesObj}
caseReference={caseReference}
ticketnumber={ticketnumber}
setRepFileName={setRepFileName}
updateRepresentation={updateRepresentation}
setSavingStatus={setSavingStatus}
savingStatus={savingStatus}
setCurrentReference={setCurrentReference}
/>
);
}
switch (controlKey) {
case "capacity-appellant": {
const Component =
appealType === 846040002
? ConsultationAppellant
: RepAppellant;
return (
<Component
{...commonProps}
appellantApplicantRepresentationArr={buildRepsArr(
detailsObj
)}
/>
);
}
case "capacity-lpa": {
return (
<RepLPA
{...commonProps}
appellantApplicantRepresentationArr={buildRepsArr(
detailsObj
)}
setShowQuestionnaireSection={
setShowQuestionnaireSection
}
showQuestionnaireSection={showQuestionnaireSection}
questionnaireCount={questionnaireCount}
/>
);
}
case "capacity-agent": {
const Component =
appealType === 846040002 ? ConsultationAgent : RepAgent;
return (
<Component
{...commonProps}
appellantApplicantRepresentationArr={buildRepsArr(
detailsObj
)}
/>
);
}
case "capacity-interestedparty": {
const Component =
appealType === 846040002
? ConsultationInterestedPartyPerson
: RepInterestedPartyPerson;
return (
<Component
{...commonProps}
interestedPersonRepresentationArr={buildRepsArr(
detailsObj
)}
/>
);
}
case "capacity-landowner": {
return (
<RepLandOwner
{...commonProps}
landOwnerRepresentationArr={buildRepsArr(detailsObj)}
/>
);
}
default:
return (
<RepCapacitySelection
{...commonProps}
capacityOptionsArr={capacityOptionsArr}
currentType={currentType}
casesObj={casesObj}
caseReference={caseReference}
/>
);
}
};
const whichProgress = () => {
const commonProps = {
props,
containerID: props.props.accountDetails.containerID,
currentView,
showQuestionnaireSection,
setShowQuestionnaireSection,
questionnaireCount
};
const s78AppealTypes = [
846040000, 846040001, 846040025, 846040004, 846040018, 846040003,
846040009, 846040008, 846040017
];
const enforcementAppealTypes = [846040005, 846040006, 846040007];
if (s78AppealTypes.includes(appealType)) {
return <RepresentationProgress_s78 {...commonProps} />;
}
if (enforcementAppealTypes.includes(appealType)) {
return <RepresentationProgress_enforcement {...commonProps} />;
}
return <></>;
};
const sortFileObj = (filelistObj) => {
const cleanArray = (arr) =>
arr
.filter((obj) => obj !== null)
.filter((obj) => Object.keys(obj).length > 0)
.filter((obj) => obj.name !== undefined);
const deduplicate = (arr) => {
const seen = new Set();
return arr.filter((obj) => {
const serialized = JSON.stringify(obj);
if (seen.has(serialized)) return false;
seen.add(serialized);
return true;
});
};
const extractFilesFromField = (filesObj) => {
return Object.values(filesObj).reduce((acc, file) => {
if (file?.name) {
acc.push({ name: file.name, size: file.size });
}
return acc;
}, []);
};
const cleanedBlobList = cleanArray(filelistObj);
const extractedFiles = extractFilesFromField(field.input.value);
const mergedFiles = [...extractedFiles, ...cleanedBlobList];
return deduplicate(mergedFiles);
};
const buildAddressStr = (detailsObj) => {
const toTitleCase = (str) =>
str.toLowerCase().replace(/\b\w/g, (char) => char.toUpperCase());
return [
detailsObj?.pinswg_siteaddressline1 ||
detailsObj?.pinswg_addressline1,
detailsObj?.pinswg_siteaddressline2 ||
detailsObj?.pinswg_addressline2,
detailsObj?.pinswg_siteaddresstown ||
detailsObj?.pinswg_addresstown,
detailsObj?.pinswg_siteaddresspostcode ||
detailsObj?.pinswg_postcode,
detailsObj?.pinswg_siteaddresscounty ||
detailsObj?.pinswg_addresscounty
]
.filter((v) => !!v && v.trim()) // remove empty/whitespace-only values
.map((v) => toTitleCase(v.trim())) // title-case each segment
.join(" ");
};
const updateRepresentation = async (
values,
sendSavedEmail,
useSaveStatus
) => {
const {
appealType: appealTypeProp,
currentView,
accountDetails,
loggedinUserEmail
} = props.props;
const incidentID = props.appealType.caseReference.incidentid;
const currentRef = caseReferenceObj.currentReference;
const containerID = accountDetails.containerID;
setSavingStatus(useSaveStatus);
const getSiteAddress = () => {
const {
pinswg_siteaddressline1,
pinswg_siteaddressline2,
pinswg_siteaddresstown,
pinswg_siteaddresspostcode
} = safeDetailsObj;
return [
pinswg_siteaddressline1,
pinswg_siteaddressline2,
pinswg_siteaddresstown,
pinswg_siteaddresspostcode
]
.filter(Boolean)
.join(" ");
};
const getRepresentationCapacity = () => {
if (
router.query.hasOwnProperty("state") &&
router.query.state === "edit"
) {
return currentView.representationCapacity;
}
return isLPA ? "LPA" : values.representationCapacity;
};
const baseBody = {
containerID,
appealType: appealType || caseReferenceObj.repDetails.appealType,
incidentID:
caseReferenceObj.incidentid ||
caseReferenceObj.repDetails.incidentid,
caseRef: currentRef,
casereference: currentRef,
pinswg_questionnaireduedate:
safeDetailsObj.pinswg_questionnaireduedate,
pinswg_statementduedate:
safeDetailsObj.pinswg_statementduedate ||
safeDetailsObj.pinswg_endofrepresentationperiod,
pinswg_statementsduedate:
safeDetailsObj.pinswg_statementsduedate ||
safeDetailsObj.pinswg_endofrepresentationperiod,
pinswg_finalcommentsduedate:
safeDetailsObj.pinswg_finalcommentsduedate ||
safeDetailsObj.pinswg_endofrepresentationperiod,
pinswg_name: currentRef,
firstname: accountDetails.firstname,
lastname: accountDetails.lastname,
emailAddress: accountDetails.emailaddress1,
siteAddress: getSiteAddress(),
pinswg_siteaddressline1: safeDetailsObj.pinswg_siteaddressline1,
pinswg_siteaddressline2: safeDetailsObj.pinswg_siteaddressline2,
pinswg_siteaddresstown: safeDetailsObj.pinswg_siteaddresstown,
pinswg_siteaddresspostcode:
safeDetailsObj.pinswg_siteaddresspostcode,
pinswg_lpareference: safeResultsObj?.pinswg_lpareference,
representationCapacity: getRepresentationCapacity(),
locale: router.locale
};
const formattedValues = {
...values,
...baseBody,
_pinswg_appellant_value: safeDetailsObj._pinswg_appellant_value,
"_pinswg_appellant_value@OData.Community.Display.V1.FormattedValue":
safeDetailsObj[
"_pinswg_appellant_value@OData.Community.Display.V1.FormattedValue"
],
_pinswg_localplanningauthority_value:
safeDetailsObj._pinswg_localplanningauthority_value ||
safeDetailsObj._pinswg_associatedlpa_value,
"_pinswg_localplanningauthority_value@OData.Community.Display.V1.FormattedValue":
safeDetailsObj[
"_pinswg_localplanningauthority_value@OData.Community.Display.V1.FormattedValue"
] ||
safeDetailsObj[
"_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue"
]
};
const updateBody = buildRepresentationUpdateBody({
formattedValues,
setRepFileName
});
const sendEmailIfNeeded = () => {
if (sendSavedEmail) {
const reference = "PEDW-PARTIAL-REP";
const templateId = "021b0a7b-df00-41f1-b94e-c269bee98c75";
const personalisation = {
caseReference: props.caseReference,
emailAddress: loggedinUserEmail,
returnLink: "",
linkExpiry: 600 // 10 minutes
};
sendEmail(
templateId,
loggedinUserEmail,
personalisation,
reference
);
}
};
const redirectToPortal = () => {
const base =
router.locale !== "en"
? `/${router.locale}/fymhorth`
: "/myportal";
router.replace(base);
};
const handleFileUpload = () => {
const filesWithLinks = updateLinks({
...values,
filesList: currentView.fileList
});
uploadRepresentationFiles(filesWithLinks);
};
const isSubmitted =
currentView.representationSubmit === true ||
currentView.representationSubmit === "true";
if (isSubmitted) {
sendEmailIfNeeded();
if (useSaveStatus) redirectToPortal();
} else {
handleFileUpload();
if (useSaveStatus) {
redirectToPortal();
}
}
console.log("Rep Updated - ", props.caseReference);
};
const onHandleSubmit = (values) => {
values = setRepFileName(values);
if (!caseReferenceObj?.currentReference) {
return;
}
const caseDetailsSource = resolveSubmitCaseDetailsSource({
"isEditState": router.query?.state === "edit",
"currentType": props.currentType,
"myRepresentations":
props.props.myRepresentations.myRepresentations,
"watchedCasesDetails": props.props.watchedCases.watchedCasesDetails,
"searchDetailsObj": props.props.searchResultsObj.searchDetailsObj
});
// Find correct case details
let detailsObj = findDetailsObjForSubmit({
ticketnumber,
caseDetailsSource
});
// Cancel submit status if editing
if (router.query?.state === "edit") {
setRepresentationSubmit(false);
}
// If it's a new form and has values, enrich payload
if (
formObj?.representationForm?.values &&
!router.query.hasOwnProperty("state")
) {
const formValues = formObj.representationForm.values;
const representationCapacity =
router.query?.state === "edit"
? props.props.currentView.representationCapacity
: isLPA
? "LPA"
: values.representationCapacity;
Object.assign(
values,
buildSubmitEnrichedValues({
formValues,
accountDetails,
appealType,
caseReferenceObj,
detailsObj,
resultsObj,
representationCapacity,
locale: router.locale
})
);
}
const shouldSubmit = !currentView.representationSubmit;
if (shouldSubmit) {
const hasNoCapacity =
!currentView.representationCapacity ||
currentView.representationCapacity === "";
const repType = values.representationType;
if (hasNoCapacity) {
const capacity = isLPA
? "LPA"
: normalizeCapacity(values.representationCapacity);
setRepresentationCapacity(capacity);
} else {
const submitTransition = resolveSubmitTransition({
"representationType": repType,
"showQuestionnaireSection": showQuestionnaireSection,
"questionnaireCount": questionnaireCount
});
if (submitTransition === "advanceQuestionnaire") {
setShowQuestionnaireSection(
getQuestionnaireNextSection(
showQuestionnaireSection,
questionnaireCount
)
);
updateRepresentation(values, false, false);
} else {
updateRepresentation(values, false, false);
setRepresentationSubmit(true);
}
}
window.scrollTo({ top: 0, behavior: "smooth" });
} else {
// Already submitted
console.log("capacity", currentView.representationCapacity);
console.log("has errors:", props.invalid);
Object.assign(values, {
locale: router.locale,
repComplete: currentView.caseReference.currentReference
});
if (props.invalid === false) {
updateRepresentation(values, false, false);
}
// Final PDF & upload
runFinalisationSequence({
values,
containerID: props.props.accountDetails.containerID,
currentReference:
props.currentView.caseReference.currentReference,
setFinaliseAppealProcess,
generateRepPDF,
updateLinks,
uploadRepresentationFiles,
setRepresentationSubmit,
setRepresentationSubmitConfirmation
}).then((data) => {
console.log(data, "");
});
}
};
const cleanFilesList = (blobList) => {
const cleanedFiles = (blobList.filesList || [])
.filter((file) => file !== null)
.filter(
(file) =>
file &&
typeof file === "object" &&
Object.keys(file).length > 0
)
.filter((file) => file.name !== undefined);
return {
...blobList,
filesList: cleanedFiles
};
};
const uploadRepresentationFiles = (values) => {
// Clean files list if present
const cleanedValues = values.hasOwnProperty("filesList")
? cleanFilesList(values)
: values;
// console.log(
// "\n////////////////////////\n upload files:",
// cleanedValues.containerID,
// "\n////////////////////////\n fileListObj:",
// fileListObj,
// "\n////////////////////////\n"
// );
// Prepare data object for upload
const dataObj = cleanedValues;
// Update links on values
const updatedValues = updateLinks(cleanedValues);
// Perform file upload and return the promise
return uploadRepFiles(
dataObj,
[{}],
updatedValues.containerID,
`${props.caseReference}/${dataObj.repfile_name}`
);
};
const repForm = props.props.form;
const isQuestionnaire =
formObj?.representationForm?.values?.representationType ===
"Questionnaire" && representationTypeConfirmed;
const appealIsConsultation = appealType === 846040002;
const appealIsLocalImpact =
currentView.caseReference.appealType === 846040011 ||
currentView.caseReference.appealType === 846040002;
const renderDueDate = () => {
if (
detailsObj?.pinswg_questionnaireduedate ||
detailsObj?.pinswg_endofrepresentationperiod ||
detailsObj?.pinswg_consultationclose
) {
return formatDates(
detailsObj.pinswg_questionnaireduedate ||
detailsObj.pinswg_endofrepresentationperiod ||
detailsObj.pinswg_consultationclose
);
}
return "N/A";
};
const renderStatementsDue = () => (
<div className="govuk-body-s">
{t("myrepresentations:statements-due-label")}:{" "}
<span className="govuk-body-s">
{formatDates(
safeDetailsObj.pinswg_statementduedate ||
safeDetailsObj.pinswg_statementsduedate ||
safeDetailsObj.pinswg_endofrepresentationperiod
)}
</span>
</div>
);
const renderMarineImpact = () =>
appealIsConsultation &&
isNRW && (
<div className="govuk-body-s">
{t("myrepresentations:marine-impact-report")}:{" "}
<span className="govuk-body-s">
{formatDates(safeDetailsObj.pinswg_consultationclose)}
</span>
</div>
);
const renderConsultationClose = () =>
appealIsConsultation && (
<div className="govuk-body-s">
{t("myrepresentations:consultation-close-label")}:{" "}
<span className="govuk-body-s">
{formatDates(safeDetailsObj.pinswg_consultationclose)}
</span>
</div>
);
const renderFinalCommentsDue = () =>
!(
currentView.caseReference.appealType === 846040011 ||
appealIsConsultation
) && (
<div className="govuk-body-s">
{t("myrepresentations:final-comments-due-label")}:{" "}
<span className="govuk-body-s">
{formatDates(safeDetailsObj.pinswg_finalcommentsduedate)}
</span>
</div>
);
return (
<div>
<form onSubmit={handleSubmit(onHandleSubmit)}>
{showCheckStage ? (
<RepCompleteSubmit
formObj={formObj}
capacityOptionsArr={capacityOptionsArr}
currentType={currentType}
casesObj={casesObj}
setRepresentationCapacity={setRepresentationCapacity}
setRepresentationSubmit={setRepresentationSubmit}
currentView={currentView}
setSubmitBack={setSubmitBack}
setRepresentationMessageSent={
setRepresentationMessageSent
}
setRepresentationSubmitConfirmation={
setRepresentationSubmitConfirmation
}
setShowQuestionnaireSection={
setShowQuestionnaireSection
}
showQuestionnaireSection={showQuestionnaireSection}
props={props}
questionnaireCount={questionnaireCount}
finaliseAppealProcess={finaliseAppealProcess}
setFinaliseAppealProcess={setFinaliseAppealProcess}
docsOffline={docsOffline}
/>
) : (
<RepresentationFlowFormStage
t={t}
appealIsConsultation={appealIsConsultation}
currentReference={
currentView.caseReference.currentReference
}
whichControl={whichControl}
appealIsLocalImpact={appealIsLocalImpact}
renderDueDate={renderDueDate}
renderStatementsDue={renderStatementsDue}
renderMarineImpact={renderMarineImpact}
renderConsultationClose={renderConsultationClose}
renderFinalCommentsDue={renderFinalCommentsDue}
isQuestionnaire={isQuestionnaire}
whichProgress={whichProgress}
/>
)}
</form>
</div>
);
};
const mapStateToProps = (state) => {
return {
search: state.search,
searchResultsObj: state.searchResultsObj,
formData: state.formData,
appealType: state.appealType,
currentView: state.currentView,
myRepresentations: state.myRepresentations,
initialValues: state.currentView.caseReference.repDetails
//form: state.form,
};
};
const mapDispatchToProps = (dispatch) => {
return {
setRepresentationCapacity: (representationCapacity) => {
dispatch(setRepresentationCapacity(representationCapacity));
},
setRepresentationSubmit: (representationSubmit) => {
dispatch(setRepresentationSubmit(representationSubmit));
},
setSubmitBack: () => {
dispatch(setRepresentationSubmit(false));
},
setRepresentationSubmitConfirmation: () => {
dispatch(setRepresentationSubmitConfirmation(true));
},
setRepresentationMessageSent: (messageSent) => {
dispatch(setRepresentationMessageSent(messageSent));
},
setRepresentationReset: () => {
dispatch(setRepresentationReset());
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(
reduxForm({
form: "representationForm",
destroyOnUnmount: false,
enableReinitialize: true
})(MakeRepresentation)
);