Merged PR 2242: Refactor: New Appeal flow structural cleanup (Slices 1–8, no behaviour change)

## Summary

This PR merges the completed new-appeal refactor stream (Slices 1–8) into SIPS-Development.

This refactor was executed in controlled slices with regression validation at each step.

## Scope

Structural and readability improvements only:
- XML/form derivation extraction
- payload and file helper extraction
- side-effect facade introduction
- BuildSection and BuildCheckSection decomposition
- BuildCheckRow formatter map refactor
- nested prop boundary cleanup
- start-flow cleanup (CreateCase / AboutYou)

## Behaviour

No intended behavioural changes.

The following were explicitly preserved:
- S78 journey behaviour
- payload shapes and field names/ids
- HASCAS mapping logic
- appellant/agent branching
- validation rules and messages
- redirect/query parameters (`lpa`, `apt`, `id`)
- navigation and side-effect sequencing
- EN/CY output parity

## Validation

Full regression has been performed on:
- start flow (CreateCase / AboutYou)
- save and resume flows
- file upload handling
- check answers rendering
- submit/finalisation sequence
- confirmation flow
- CRM insertion path
- EN/CY parity

Additional checks:
- docsOffline branch behaviour
- completion and partial-save email paths
- negative-path validation scenarios
- lint (warnings baseline unchanged)

## Risk

Low:
- changes are structural only
- no business logic changes
- no contract changes

## Rollback

Safe rollback via reverting this merge commit.

## Notes

This refactor reduces coupling and prepares the new-appeal flow for future appeal-type expansion.

Related work items: #22570, #22576, #22577, #22583, #22586, #22587, #22588, #22590
This commit is contained in:
Robert Bond
2026-04-13 13:09:12 +00:00
parent bd3d311cfb
commit 0de9268255
47 changed files with 2010 additions and 945 deletions
+19 -16
View File
@@ -262,7 +262,7 @@ const RenderRadio = ({
{
["documentCheckList_" +
id]:
custom.requiredDocumentLabel,
custom.requiredDocumentLabel
}
))
: delete docListObj[
@@ -297,7 +297,7 @@ function Radiofield(props) {
formProps,
parentFieldShowOnValue,
validation,
hint,
hint
} = props;
const router = useRouter();
@@ -438,22 +438,25 @@ let AboutYou = (props) => {
const router = useRouter();
const { locale } = router;
const isWelsh = router.locale == "cy";
const {
onSubmit,
handleSubmit,
appellantAgentValue,
setFormStep,
updateField,
updateField
} = props;
const [isAgent, setIsAgent] = useState(false);
const isAgentSelected = appellantAgentValue == "846040001";
const isAppellantSelected = appellantAgentValue == "846040000";
const yesNo = router.locale == "cy" ? ["Ydw", "Na"] : ["Yes", "No"];
const appellantAgent =
router.locale == "cy" ? ["Apelydd", "Asiant"] : ["Appellant", "Agent"];
const contactPref =
router.locale == "cy" ? ["Ebost", "Post"] : ["Email", "Post"];
const yesNo = isWelsh ? ["Ydw", "Na"] : ["Yes", "No"];
const appellantAgent = isWelsh
? ["Apelydd", "Asiant"]
: ["Appellant", "Agent"];
const contactPref = isWelsh ? ["Ebost", "Post"] : ["Email", "Post"];
const required = (value) =>
value ? undefined : t("newappeal:is-required-label");
@@ -493,7 +496,7 @@ let AboutYou = (props) => {
};
const handlePartialUpdate = () => {
if (appellantAgentValue == "846040001" && isAgent == false) {
if (isAgentSelected && isAgent == false) {
updateField("caseForm", "pinswg_appellantfirstname", "");
updateField("caseForm", "pinswg_appellantlastname", "");
updateField("caseForm", "pinswg_appellantemailaddress", "");
@@ -570,7 +573,7 @@ let AboutYou = (props) => {
errorMsg={t("newappeal:select-an-option-label")}
hint={t("newappeal:about-you-who-are-you-hint-label")}
/>
{appellantAgentValue == "846040000" && (
{isAppellantSelected && (
<>
<h2 className="govuk-heading-s">
{t("newappeal:about-you-appellant-contact-details")}
@@ -668,7 +671,7 @@ let AboutYou = (props) => {
/>
</>
)}
{appellantAgentValue == "846040001" && (
{isAgentSelected && (
<>
<h2 className="govuk-heading-s">
{t("newappeal:about-you-appellant-contact-details")}
@@ -891,15 +894,15 @@ const mapStateToProps = (state) => {
pinswg_appellantaddress:
state.accountDetails.accountDetails.address1_composite,
pinswg_appellantphonenumber:
state.accountDetails.accountDetails.telephone1,
},
state.accountDetails.accountDetails.telephone1
}
};
};
const mapDispatchToProps = (dispatch) => {
return {
updateField: (form, field, newValue) =>
dispatch(change(form, field, newValue)),
dispatch(change(form, field, newValue))
};
};
@@ -915,7 +918,7 @@ AboutYou = connect((state) => {
const appellantAgentValue = selector(state, "pinswg_appellantagent");
return {
appellantAgentValue,
appellantAgentValue
};
})(AboutYou);
@@ -928,6 +931,6 @@ export default connect(
reduxForm({
form: "caseForm",
enableReinitialize: true, // this is needed!!
destroyOnUnmount: false,
destroyOnUnmount: false
})(AboutYou)
);