@defra/fcp-sfd-frontend-engine 0.22.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +164 -2
- package/dist/index.js +164 -2
- package/package.json +1 -1
- package/src/constants/index.js +22 -0
- package/src/constants/interrupter-journey.js +62 -0
- package/src/mutations/business/update-business-phone-numbers.js +1 -1
- package/src/services/check-interrupter-journey-session-service.js +37 -0
- package/src/services/initialise-fix-journey-service.js +125 -0
- package/src/services/services.js +9 -1
- package/src/services/set-fix-session-data-service.js +124 -0
- package/src/services/validate-fix-details-service.js +59 -0
package/dist/index.cjs
CHANGED
|
@@ -102,6 +102,52 @@ var BUSINESS_EMAIL_ADDRESS = "You have updated your business email address";
|
|
|
102
102
|
var BUSINESS_NAME = "You have updated your business name";
|
|
103
103
|
var BUSINESS_PHONE_NUMBERS = "You have updated your business phone numbers";
|
|
104
104
|
|
|
105
|
+
// src/constants/interrupter-journey.js
|
|
106
|
+
var PERSONAL_SECTION_FIELD_ORDER = {
|
|
107
|
+
name: ["first", "middle", "last"],
|
|
108
|
+
dob: ["day", "month", "year"],
|
|
109
|
+
address: ["address1", "address2", "address3", "city", "county", "postcode", "country"],
|
|
110
|
+
phone: ["personalTelephone", "personalMobile"],
|
|
111
|
+
email: ["personalEmail"]
|
|
112
|
+
};
|
|
113
|
+
var BUSINESS_SECTION_FIELD_ORDER = {
|
|
114
|
+
name: ["businessName"],
|
|
115
|
+
address: ["address1", "address2", "address3", "city", "county", "postcode", "country"],
|
|
116
|
+
phone: ["businessTelephone", "businessMobile"],
|
|
117
|
+
email: ["businessEmail"],
|
|
118
|
+
vat: ["vatNumber"]
|
|
119
|
+
};
|
|
120
|
+
var PERSONAL_SECTION_ORDER = ["name", "dob", "address", "phone", "email"];
|
|
121
|
+
var BUSINESS_SECTION_ORDER = ["name", "address", "phone", "email", "vat"];
|
|
122
|
+
var PERSONAL_SECTION_LABELS = {
|
|
123
|
+
name: "full name",
|
|
124
|
+
dob: "date of birth",
|
|
125
|
+
address: "personal address",
|
|
126
|
+
phone: "personal phone number",
|
|
127
|
+
email: "personal email address"
|
|
128
|
+
};
|
|
129
|
+
var BUSINESS_SECTION_LABELS = {
|
|
130
|
+
name: "business name",
|
|
131
|
+
address: "business address",
|
|
132
|
+
phone: "at least one business phone number",
|
|
133
|
+
email: "business email address",
|
|
134
|
+
vat: "business VAT number"
|
|
135
|
+
};
|
|
136
|
+
var PERSONAL_UPDATE_TEXT_LABELS = {
|
|
137
|
+
name: "your full name",
|
|
138
|
+
dob: "your date of birth",
|
|
139
|
+
address: "your personal address",
|
|
140
|
+
phone: "at least one personal phone number",
|
|
141
|
+
email: "your personal email address"
|
|
142
|
+
};
|
|
143
|
+
var BUSINESS_UPDATE_TEXT_LABELS = {
|
|
144
|
+
name: "your business name",
|
|
145
|
+
address: "your business address",
|
|
146
|
+
phone: "at least one business phone number",
|
|
147
|
+
email: "your business email address",
|
|
148
|
+
vat: "your business VAT number"
|
|
149
|
+
};
|
|
150
|
+
|
|
105
151
|
// src/constants/index.js
|
|
106
152
|
var constants = {
|
|
107
153
|
statusCodes: {
|
|
@@ -139,6 +185,16 @@ var constants = {
|
|
|
139
185
|
BUSINESS_EMAIL_ADDRESS,
|
|
140
186
|
BUSINESS_NAME,
|
|
141
187
|
BUSINESS_PHONE_NUMBERS
|
|
188
|
+
},
|
|
189
|
+
interrupterJourney: {
|
|
190
|
+
PERSONAL_SECTION_FIELD_ORDER,
|
|
191
|
+
BUSINESS_SECTION_FIELD_ORDER,
|
|
192
|
+
PERSONAL_SECTION_ORDER,
|
|
193
|
+
BUSINESS_SECTION_ORDER,
|
|
194
|
+
PERSONAL_SECTION_LABELS,
|
|
195
|
+
BUSINESS_SECTION_LABELS,
|
|
196
|
+
PERSONAL_UPDATE_TEXT_LABELS,
|
|
197
|
+
BUSINESS_UPDATE_TEXT_LABELS
|
|
142
198
|
}
|
|
143
199
|
};
|
|
144
200
|
|
|
@@ -736,7 +792,7 @@ var updateBusinessNameMutation = `
|
|
|
736
792
|
|
|
737
793
|
// src/mutations/business/update-business-phone-numbers.js
|
|
738
794
|
var updateBusinessPhoneNumbersMutation = `
|
|
739
|
-
mutation UpdateBusinessPhoneNumbers($input:
|
|
795
|
+
mutation UpdateBusinessPhoneNumbers($input: UpdateBusinessPhoneInput!) {
|
|
740
796
|
updateBusinessPhone(input: $input) {
|
|
741
797
|
business {
|
|
742
798
|
info {
|
|
@@ -1481,11 +1537,117 @@ var nullIfUndefined = (value) => {
|
|
|
1481
1537
|
return value ?? null;
|
|
1482
1538
|
};
|
|
1483
1539
|
|
|
1540
|
+
// src/services/check-interrupter-journey-session-service.js
|
|
1541
|
+
var checkInterrupterJourneySessionService = (yar, journeyKey) => {
|
|
1542
|
+
const sessionData = yar.get(journeyKey);
|
|
1543
|
+
if (!sessionData) {
|
|
1544
|
+
return false;
|
|
1545
|
+
}
|
|
1546
|
+
if (Array.isArray(sessionData.orderedSectionsToFix)) {
|
|
1547
|
+
return true;
|
|
1548
|
+
}
|
|
1549
|
+
return false;
|
|
1550
|
+
};
|
|
1551
|
+
|
|
1552
|
+
// src/services/initialise-fix-journey-service.js
|
|
1553
|
+
var initialiseFixJourneyService = (yar, source, journeyType) => {
|
|
1554
|
+
let sessionKey;
|
|
1555
|
+
let sectionOrder = [];
|
|
1556
|
+
if (journeyType === "business") {
|
|
1557
|
+
sessionKey = "businessDetailsValidation";
|
|
1558
|
+
sectionOrder = BUSINESS_SECTION_ORDER;
|
|
1559
|
+
}
|
|
1560
|
+
if (journeyType === "personal") {
|
|
1561
|
+
sessionKey = "personalDetailsValidation";
|
|
1562
|
+
sectionOrder = PERSONAL_SECTION_ORDER;
|
|
1563
|
+
}
|
|
1564
|
+
const sessionData = yar.get(sessionKey);
|
|
1565
|
+
if (!(sessionData == null ? void 0 : sessionData.sectionsNeedingUpdate)) {
|
|
1566
|
+
return sessionData;
|
|
1567
|
+
}
|
|
1568
|
+
const orderedSectionsToFix = orderSectionsToFix(
|
|
1569
|
+
sessionData.sectionsNeedingUpdate,
|
|
1570
|
+
source,
|
|
1571
|
+
sectionOrder
|
|
1572
|
+
);
|
|
1573
|
+
updateSessionData(sessionData, source, orderedSectionsToFix);
|
|
1574
|
+
yar.set(sessionKey, sessionData);
|
|
1575
|
+
return sessionData;
|
|
1576
|
+
};
|
|
1577
|
+
var updateSessionData = (sessionData, source, orderedSectionsToFix) => {
|
|
1578
|
+
sessionData.orderedSectionsToFix = orderedSectionsToFix;
|
|
1579
|
+
delete sessionData.sectionsNeedingUpdate;
|
|
1580
|
+
delete sessionData.personalFixUpdates;
|
|
1581
|
+
delete sessionData.businessFixUpdates;
|
|
1582
|
+
if (source) {
|
|
1583
|
+
sessionData.source = source;
|
|
1584
|
+
}
|
|
1585
|
+
};
|
|
1586
|
+
var orderSectionsToFix = (sectionsNeedingUpdate, source, SECTION_ORDER) => {
|
|
1587
|
+
const sections = SECTION_ORDER.filter((section) => {
|
|
1588
|
+
return sectionsNeedingUpdate.includes(section);
|
|
1589
|
+
});
|
|
1590
|
+
if (!source) {
|
|
1591
|
+
return sections;
|
|
1592
|
+
}
|
|
1593
|
+
if (!SECTION_ORDER.includes(source)) {
|
|
1594
|
+
return sections;
|
|
1595
|
+
}
|
|
1596
|
+
return [
|
|
1597
|
+
source,
|
|
1598
|
+
...sections.filter((section) => section !== source)
|
|
1599
|
+
];
|
|
1600
|
+
};
|
|
1601
|
+
|
|
1602
|
+
// src/services/validate-fix-details-service.js
|
|
1603
|
+
var validateFixDetailsService = (payload, orderedSectionsToFix, schemas2) => {
|
|
1604
|
+
const errors = [];
|
|
1605
|
+
for (const section of orderedSectionsToFix) {
|
|
1606
|
+
const schema = schemas2[section];
|
|
1607
|
+
const result = schema.validate(payload, {
|
|
1608
|
+
abortEarly: false,
|
|
1609
|
+
allowUnknown: true
|
|
1610
|
+
});
|
|
1611
|
+
if (result.error) {
|
|
1612
|
+
errors.push(...result.error.details);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
if (errors.length > 0) {
|
|
1616
|
+
return {
|
|
1617
|
+
error: {
|
|
1618
|
+
details: errors
|
|
1619
|
+
}
|
|
1620
|
+
};
|
|
1621
|
+
}
|
|
1622
|
+
return { value: payload };
|
|
1623
|
+
};
|
|
1624
|
+
|
|
1625
|
+
// src/services/set-fix-session-data-service.js
|
|
1626
|
+
var setFixSessionDataService = (yar, sessionData, payload, journeyKey, updateKey) => {
|
|
1627
|
+
const orderedSectionsToFix = sessionData.orderedSectionsToFix;
|
|
1628
|
+
const type = journeyKey === "businessDetailsValidation" ? "business" : "personal";
|
|
1629
|
+
const SECTION_FIELD_ORDER = type === "business" ? BUSINESS_SECTION_FIELD_ORDER : PERSONAL_SECTION_FIELD_ORDER;
|
|
1630
|
+
const fixUpdates = {};
|
|
1631
|
+
for (const section of orderedSectionsToFix) {
|
|
1632
|
+
const fields = SECTION_FIELD_ORDER[section];
|
|
1633
|
+
fixUpdates[section] = {};
|
|
1634
|
+
for (const field of fields) {
|
|
1635
|
+
fixUpdates[section][field] = payload[field] ?? "";
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
sessionData[updateKey] = fixUpdates;
|
|
1639
|
+
yar.set(journeyKey, sessionData);
|
|
1640
|
+
};
|
|
1641
|
+
|
|
1484
1642
|
// src/services/services.js
|
|
1485
1643
|
var services = {
|
|
1486
1644
|
addressLookup: addressLookupService,
|
|
1487
1645
|
buildUprnAddress,
|
|
1488
|
-
buildManualAddress
|
|
1646
|
+
buildManualAddress,
|
|
1647
|
+
checkInterrupterJourneySession: checkInterrupterJourneySessionService,
|
|
1648
|
+
initialiseFixJourney: initialiseFixJourneyService,
|
|
1649
|
+
validateFixDetails: validateFixDetailsService,
|
|
1650
|
+
setFixSessionData: setFixSessionDataService
|
|
1489
1651
|
};
|
|
1490
1652
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1491
1653
|
0 && (module.exports = {
|
package/dist/index.js
CHANGED
|
@@ -61,6 +61,52 @@ var BUSINESS_EMAIL_ADDRESS = "You have updated your business email address";
|
|
|
61
61
|
var BUSINESS_NAME = "You have updated your business name";
|
|
62
62
|
var BUSINESS_PHONE_NUMBERS = "You have updated your business phone numbers";
|
|
63
63
|
|
|
64
|
+
// src/constants/interrupter-journey.js
|
|
65
|
+
var PERSONAL_SECTION_FIELD_ORDER = {
|
|
66
|
+
name: ["first", "middle", "last"],
|
|
67
|
+
dob: ["day", "month", "year"],
|
|
68
|
+
address: ["address1", "address2", "address3", "city", "county", "postcode", "country"],
|
|
69
|
+
phone: ["personalTelephone", "personalMobile"],
|
|
70
|
+
email: ["personalEmail"]
|
|
71
|
+
};
|
|
72
|
+
var BUSINESS_SECTION_FIELD_ORDER = {
|
|
73
|
+
name: ["businessName"],
|
|
74
|
+
address: ["address1", "address2", "address3", "city", "county", "postcode", "country"],
|
|
75
|
+
phone: ["businessTelephone", "businessMobile"],
|
|
76
|
+
email: ["businessEmail"],
|
|
77
|
+
vat: ["vatNumber"]
|
|
78
|
+
};
|
|
79
|
+
var PERSONAL_SECTION_ORDER = ["name", "dob", "address", "phone", "email"];
|
|
80
|
+
var BUSINESS_SECTION_ORDER = ["name", "address", "phone", "email", "vat"];
|
|
81
|
+
var PERSONAL_SECTION_LABELS = {
|
|
82
|
+
name: "full name",
|
|
83
|
+
dob: "date of birth",
|
|
84
|
+
address: "personal address",
|
|
85
|
+
phone: "personal phone number",
|
|
86
|
+
email: "personal email address"
|
|
87
|
+
};
|
|
88
|
+
var BUSINESS_SECTION_LABELS = {
|
|
89
|
+
name: "business name",
|
|
90
|
+
address: "business address",
|
|
91
|
+
phone: "at least one business phone number",
|
|
92
|
+
email: "business email address",
|
|
93
|
+
vat: "business VAT number"
|
|
94
|
+
};
|
|
95
|
+
var PERSONAL_UPDATE_TEXT_LABELS = {
|
|
96
|
+
name: "your full name",
|
|
97
|
+
dob: "your date of birth",
|
|
98
|
+
address: "your personal address",
|
|
99
|
+
phone: "at least one personal phone number",
|
|
100
|
+
email: "your personal email address"
|
|
101
|
+
};
|
|
102
|
+
var BUSINESS_UPDATE_TEXT_LABELS = {
|
|
103
|
+
name: "your business name",
|
|
104
|
+
address: "your business address",
|
|
105
|
+
phone: "at least one business phone number",
|
|
106
|
+
email: "your business email address",
|
|
107
|
+
vat: "your business VAT number"
|
|
108
|
+
};
|
|
109
|
+
|
|
64
110
|
// src/constants/index.js
|
|
65
111
|
var constants = {
|
|
66
112
|
statusCodes: {
|
|
@@ -98,6 +144,16 @@ var constants = {
|
|
|
98
144
|
BUSINESS_EMAIL_ADDRESS,
|
|
99
145
|
BUSINESS_NAME,
|
|
100
146
|
BUSINESS_PHONE_NUMBERS
|
|
147
|
+
},
|
|
148
|
+
interrupterJourney: {
|
|
149
|
+
PERSONAL_SECTION_FIELD_ORDER,
|
|
150
|
+
BUSINESS_SECTION_FIELD_ORDER,
|
|
151
|
+
PERSONAL_SECTION_ORDER,
|
|
152
|
+
BUSINESS_SECTION_ORDER,
|
|
153
|
+
PERSONAL_SECTION_LABELS,
|
|
154
|
+
BUSINESS_SECTION_LABELS,
|
|
155
|
+
PERSONAL_UPDATE_TEXT_LABELS,
|
|
156
|
+
BUSINESS_UPDATE_TEXT_LABELS
|
|
101
157
|
}
|
|
102
158
|
};
|
|
103
159
|
|
|
@@ -695,7 +751,7 @@ var updateBusinessNameMutation = `
|
|
|
695
751
|
|
|
696
752
|
// src/mutations/business/update-business-phone-numbers.js
|
|
697
753
|
var updateBusinessPhoneNumbersMutation = `
|
|
698
|
-
mutation UpdateBusinessPhoneNumbers($input:
|
|
754
|
+
mutation UpdateBusinessPhoneNumbers($input: UpdateBusinessPhoneInput!) {
|
|
699
755
|
updateBusinessPhone(input: $input) {
|
|
700
756
|
business {
|
|
701
757
|
info {
|
|
@@ -1440,11 +1496,117 @@ var nullIfUndefined = (value) => {
|
|
|
1440
1496
|
return value ?? null;
|
|
1441
1497
|
};
|
|
1442
1498
|
|
|
1499
|
+
// src/services/check-interrupter-journey-session-service.js
|
|
1500
|
+
var checkInterrupterJourneySessionService = (yar, journeyKey) => {
|
|
1501
|
+
const sessionData = yar.get(journeyKey);
|
|
1502
|
+
if (!sessionData) {
|
|
1503
|
+
return false;
|
|
1504
|
+
}
|
|
1505
|
+
if (Array.isArray(sessionData.orderedSectionsToFix)) {
|
|
1506
|
+
return true;
|
|
1507
|
+
}
|
|
1508
|
+
return false;
|
|
1509
|
+
};
|
|
1510
|
+
|
|
1511
|
+
// src/services/initialise-fix-journey-service.js
|
|
1512
|
+
var initialiseFixJourneyService = (yar, source, journeyType) => {
|
|
1513
|
+
let sessionKey;
|
|
1514
|
+
let sectionOrder = [];
|
|
1515
|
+
if (journeyType === "business") {
|
|
1516
|
+
sessionKey = "businessDetailsValidation";
|
|
1517
|
+
sectionOrder = BUSINESS_SECTION_ORDER;
|
|
1518
|
+
}
|
|
1519
|
+
if (journeyType === "personal") {
|
|
1520
|
+
sessionKey = "personalDetailsValidation";
|
|
1521
|
+
sectionOrder = PERSONAL_SECTION_ORDER;
|
|
1522
|
+
}
|
|
1523
|
+
const sessionData = yar.get(sessionKey);
|
|
1524
|
+
if (!(sessionData == null ? void 0 : sessionData.sectionsNeedingUpdate)) {
|
|
1525
|
+
return sessionData;
|
|
1526
|
+
}
|
|
1527
|
+
const orderedSectionsToFix = orderSectionsToFix(
|
|
1528
|
+
sessionData.sectionsNeedingUpdate,
|
|
1529
|
+
source,
|
|
1530
|
+
sectionOrder
|
|
1531
|
+
);
|
|
1532
|
+
updateSessionData(sessionData, source, orderedSectionsToFix);
|
|
1533
|
+
yar.set(sessionKey, sessionData);
|
|
1534
|
+
return sessionData;
|
|
1535
|
+
};
|
|
1536
|
+
var updateSessionData = (sessionData, source, orderedSectionsToFix) => {
|
|
1537
|
+
sessionData.orderedSectionsToFix = orderedSectionsToFix;
|
|
1538
|
+
delete sessionData.sectionsNeedingUpdate;
|
|
1539
|
+
delete sessionData.personalFixUpdates;
|
|
1540
|
+
delete sessionData.businessFixUpdates;
|
|
1541
|
+
if (source) {
|
|
1542
|
+
sessionData.source = source;
|
|
1543
|
+
}
|
|
1544
|
+
};
|
|
1545
|
+
var orderSectionsToFix = (sectionsNeedingUpdate, source, SECTION_ORDER) => {
|
|
1546
|
+
const sections = SECTION_ORDER.filter((section) => {
|
|
1547
|
+
return sectionsNeedingUpdate.includes(section);
|
|
1548
|
+
});
|
|
1549
|
+
if (!source) {
|
|
1550
|
+
return sections;
|
|
1551
|
+
}
|
|
1552
|
+
if (!SECTION_ORDER.includes(source)) {
|
|
1553
|
+
return sections;
|
|
1554
|
+
}
|
|
1555
|
+
return [
|
|
1556
|
+
source,
|
|
1557
|
+
...sections.filter((section) => section !== source)
|
|
1558
|
+
];
|
|
1559
|
+
};
|
|
1560
|
+
|
|
1561
|
+
// src/services/validate-fix-details-service.js
|
|
1562
|
+
var validateFixDetailsService = (payload, orderedSectionsToFix, schemas2) => {
|
|
1563
|
+
const errors = [];
|
|
1564
|
+
for (const section of orderedSectionsToFix) {
|
|
1565
|
+
const schema = schemas2[section];
|
|
1566
|
+
const result = schema.validate(payload, {
|
|
1567
|
+
abortEarly: false,
|
|
1568
|
+
allowUnknown: true
|
|
1569
|
+
});
|
|
1570
|
+
if (result.error) {
|
|
1571
|
+
errors.push(...result.error.details);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
if (errors.length > 0) {
|
|
1575
|
+
return {
|
|
1576
|
+
error: {
|
|
1577
|
+
details: errors
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1580
|
+
}
|
|
1581
|
+
return { value: payload };
|
|
1582
|
+
};
|
|
1583
|
+
|
|
1584
|
+
// src/services/set-fix-session-data-service.js
|
|
1585
|
+
var setFixSessionDataService = (yar, sessionData, payload, journeyKey, updateKey) => {
|
|
1586
|
+
const orderedSectionsToFix = sessionData.orderedSectionsToFix;
|
|
1587
|
+
const type = journeyKey === "businessDetailsValidation" ? "business" : "personal";
|
|
1588
|
+
const SECTION_FIELD_ORDER = type === "business" ? BUSINESS_SECTION_FIELD_ORDER : PERSONAL_SECTION_FIELD_ORDER;
|
|
1589
|
+
const fixUpdates = {};
|
|
1590
|
+
for (const section of orderedSectionsToFix) {
|
|
1591
|
+
const fields = SECTION_FIELD_ORDER[section];
|
|
1592
|
+
fixUpdates[section] = {};
|
|
1593
|
+
for (const field of fields) {
|
|
1594
|
+
fixUpdates[section][field] = payload[field] ?? "";
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
sessionData[updateKey] = fixUpdates;
|
|
1598
|
+
yar.set(journeyKey, sessionData);
|
|
1599
|
+
};
|
|
1600
|
+
|
|
1443
1601
|
// src/services/services.js
|
|
1444
1602
|
var services = {
|
|
1445
1603
|
addressLookup: addressLookupService,
|
|
1446
1604
|
buildUprnAddress,
|
|
1447
|
-
buildManualAddress
|
|
1605
|
+
buildManualAddress,
|
|
1606
|
+
checkInterrupterJourneySession: checkInterrupterJourneySessionService,
|
|
1607
|
+
initialiseFixJourney: initialiseFixJourneyService,
|
|
1608
|
+
validateFixDetails: validateFixDetailsService,
|
|
1609
|
+
setFixSessionData: setFixSessionDataService
|
|
1448
1610
|
};
|
|
1449
1611
|
export {
|
|
1450
1612
|
constants,
|
package/package.json
CHANGED
package/src/constants/index.js
CHANGED
|
@@ -39,6 +39,18 @@ import {
|
|
|
39
39
|
BUSINESS_PHONE_NUMBERS
|
|
40
40
|
} from './success-messages.js'
|
|
41
41
|
|
|
42
|
+
// Interrupter journey constants
|
|
43
|
+
import {
|
|
44
|
+
PERSONAL_SECTION_FIELD_ORDER,
|
|
45
|
+
BUSINESS_SECTION_FIELD_ORDER,
|
|
46
|
+
PERSONAL_SECTION_ORDER,
|
|
47
|
+
BUSINESS_SECTION_ORDER,
|
|
48
|
+
PERSONAL_SECTION_LABELS,
|
|
49
|
+
BUSINESS_SECTION_LABELS,
|
|
50
|
+
PERSONAL_UPDATE_TEXT_LABELS,
|
|
51
|
+
BUSINESS_UPDATE_TEXT_LABELS
|
|
52
|
+
} from './interrupter-journey.js'
|
|
53
|
+
|
|
42
54
|
export const constants = {
|
|
43
55
|
statusCodes: {
|
|
44
56
|
BAD_REQUEST,
|
|
@@ -75,5 +87,15 @@ export const constants = {
|
|
|
75
87
|
BUSINESS_EMAIL_ADDRESS,
|
|
76
88
|
BUSINESS_NAME,
|
|
77
89
|
BUSINESS_PHONE_NUMBERS
|
|
90
|
+
},
|
|
91
|
+
interrupterJourney: {
|
|
92
|
+
PERSONAL_SECTION_FIELD_ORDER,
|
|
93
|
+
BUSINESS_SECTION_FIELD_ORDER,
|
|
94
|
+
PERSONAL_SECTION_ORDER,
|
|
95
|
+
BUSINESS_SECTION_ORDER,
|
|
96
|
+
PERSONAL_SECTION_LABELS,
|
|
97
|
+
BUSINESS_SECTION_LABELS,
|
|
98
|
+
PERSONAL_UPDATE_TEXT_LABELS,
|
|
99
|
+
BUSINESS_UPDATE_TEXT_LABELS
|
|
78
100
|
}
|
|
79
101
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for the interrupter journey.
|
|
3
|
+
*
|
|
4
|
+
* Defines the field order for personal and business detail sections,
|
|
5
|
+
* display labels, and the consistent ordering of sections for the fix journey.
|
|
6
|
+
*
|
|
7
|
+
* The ordering defined here is used throughout the fix journey to ensure
|
|
8
|
+
* consistent presentation of sections and error ordering.
|
|
9
|
+
*
|
|
10
|
+
* @module interrupter-journey-constants
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export const PERSONAL_SECTION_FIELD_ORDER = {
|
|
14
|
+
name: ['first', 'middle', 'last'],
|
|
15
|
+
dob: ['day', 'month', 'year'],
|
|
16
|
+
address: ['address1', 'address2', 'address3', 'city', 'county', 'postcode', 'country'],
|
|
17
|
+
phone: ['personalTelephone', 'personalMobile'],
|
|
18
|
+
email: ['personalEmail']
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const BUSINESS_SECTION_FIELD_ORDER = {
|
|
22
|
+
name: ['businessName'],
|
|
23
|
+
address: ['address1', 'address2', 'address3', 'city', 'county', 'postcode', 'country'],
|
|
24
|
+
phone: ['businessTelephone', 'businessMobile'],
|
|
25
|
+
email: ['businessEmail'],
|
|
26
|
+
vat: ['vatNumber']
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const PERSONAL_SECTION_ORDER = ['name', 'dob', 'address', 'phone', 'email']
|
|
30
|
+
export const BUSINESS_SECTION_ORDER = ['name', 'address', 'phone', 'email', 'vat']
|
|
31
|
+
|
|
32
|
+
export const PERSONAL_SECTION_LABELS = {
|
|
33
|
+
name: 'full name',
|
|
34
|
+
dob: 'date of birth',
|
|
35
|
+
address: 'personal address',
|
|
36
|
+
phone: 'personal phone number',
|
|
37
|
+
email: 'personal email address'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const BUSINESS_SECTION_LABELS = {
|
|
41
|
+
name: 'business name',
|
|
42
|
+
address: 'business address',
|
|
43
|
+
phone: 'at least one business phone number',
|
|
44
|
+
email: 'business email address',
|
|
45
|
+
vat: 'business VAT number'
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const PERSONAL_UPDATE_TEXT_LABELS = {
|
|
49
|
+
name: 'your full name',
|
|
50
|
+
dob: 'your date of birth',
|
|
51
|
+
address: 'your personal address',
|
|
52
|
+
phone: 'at least one personal phone number',
|
|
53
|
+
email: 'your personal email address'
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const BUSINESS_UPDATE_TEXT_LABELS = {
|
|
57
|
+
name: 'your business name',
|
|
58
|
+
address: 'your business address',
|
|
59
|
+
phone: 'at least one business phone number',
|
|
60
|
+
email: 'your business email address',
|
|
61
|
+
vat: 'your business VAT number'
|
|
62
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates that an interrupter journey session is still usable.
|
|
3
|
+
*
|
|
4
|
+
* Ensures the expected session structure exists before allowing
|
|
5
|
+
* the user to continue a fix journey.
|
|
6
|
+
*
|
|
7
|
+
* If the session has been cleared or is incomplete (for example,
|
|
8
|
+
* due to multi-tab usage), the journey should be restarted.
|
|
9
|
+
*
|
|
10
|
+
* @module checkInterrupterJourneySessionService
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns true if the session contains valid data for the given journey.
|
|
15
|
+
* Returns false if the session is missing or incomplete.
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} yar - Hapi session object
|
|
18
|
+
* @param {string} journeyKey - Session key for the journey (e.g., 'personalDetailsValidation')
|
|
19
|
+
* @returns {boolean} True if session has orderedSectionsToFix array, false otherwise
|
|
20
|
+
*/
|
|
21
|
+
const checkInterrupterJourneySessionService = (yar, journeyKey) => {
|
|
22
|
+
const sessionData = yar.get(journeyKey)
|
|
23
|
+
|
|
24
|
+
if (!sessionData) {
|
|
25
|
+
return false
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (Array.isArray(sessionData.orderedSectionsToFix)) {
|
|
29
|
+
return true
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
checkInterrupterJourneySessionService
|
|
37
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Initialises the fix journey in the user's session.
|
|
3
|
+
*
|
|
4
|
+
* This service is the single place where the fix journey order is defined.
|
|
5
|
+
* It calculates and stores the ordered list of either personal or business
|
|
6
|
+
* detail sections that the user needs to fix.
|
|
7
|
+
*
|
|
8
|
+
* This sets:
|
|
9
|
+
* - orderedSectionsToFix: the ordered list of sections to fix
|
|
10
|
+
* - source: the section the user selected to start the journey (if provided)
|
|
11
|
+
*
|
|
12
|
+
* If a source is provided, that section is placed first, followed by the
|
|
13
|
+
* remaining sections in the order defined by this service.
|
|
14
|
+
*
|
|
15
|
+
* Downstream routes and presenters read this data from the session and
|
|
16
|
+
* don't reorder it.
|
|
17
|
+
*
|
|
18
|
+
* @module initialiseFixJourneyService
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
PERSONAL_SECTION_ORDER,
|
|
23
|
+
BUSINESS_SECTION_ORDER
|
|
24
|
+
} from '../constants/interrupter-journey.js'
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Initialises the fix journey session data.
|
|
28
|
+
*
|
|
29
|
+
* @param {Object} yar - Hapi session object
|
|
30
|
+
* @param {string} source - The section user clicked to fix (optional)
|
|
31
|
+
* @param {string} journeyType - Either 'personal' or 'business'
|
|
32
|
+
* @returns {Object|undefined} Updated session data, or undefined if session data does not exist
|
|
33
|
+
*/
|
|
34
|
+
const initialiseFixJourneyService = (yar, source, journeyType) => {
|
|
35
|
+
// Determined by journeyType
|
|
36
|
+
let sessionKey
|
|
37
|
+
let sectionOrder = []
|
|
38
|
+
|
|
39
|
+
if (journeyType === 'business') {
|
|
40
|
+
sessionKey = 'businessDetailsValidation'
|
|
41
|
+
sectionOrder = BUSINESS_SECTION_ORDER
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (journeyType === 'personal') {
|
|
45
|
+
sessionKey = 'personalDetailsValidation'
|
|
46
|
+
sectionOrder = PERSONAL_SECTION_ORDER
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const sessionData = yar.get(sessionKey)
|
|
50
|
+
|
|
51
|
+
if (!sessionData?.sectionsNeedingUpdate) {
|
|
52
|
+
return sessionData
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const orderedSectionsToFix = orderSectionsToFix(
|
|
56
|
+
sessionData.sectionsNeedingUpdate,
|
|
57
|
+
source,
|
|
58
|
+
sectionOrder
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
updateSessionData(sessionData, source, orderedSectionsToFix)
|
|
62
|
+
|
|
63
|
+
yar.set(sessionKey, sessionData)
|
|
64
|
+
|
|
65
|
+
return sessionData
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Updates session data with the ordered sections and clears temporary fields.
|
|
70
|
+
*
|
|
71
|
+
* @param {Object} sessionData - The session data to update
|
|
72
|
+
* @param {string} source - The selected section (optional)
|
|
73
|
+
* @param {Array<string>} orderedSectionsToFix - Ordered list of sections to fix
|
|
74
|
+
*/
|
|
75
|
+
const updateSessionData = (sessionData, source, orderedSectionsToFix) => {
|
|
76
|
+
sessionData.orderedSectionsToFix = orderedSectionsToFix
|
|
77
|
+
|
|
78
|
+
// Clean up temporary fields used only during validation
|
|
79
|
+
delete sessionData.sectionsNeedingUpdate
|
|
80
|
+
delete sessionData.personalFixUpdates
|
|
81
|
+
delete sessionData.businessFixUpdates
|
|
82
|
+
|
|
83
|
+
if (source) {
|
|
84
|
+
sessionData.source = source
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Returns an ordered list of sections that the user needs to fix.
|
|
90
|
+
*
|
|
91
|
+
* Sections are ordered based on how the personal/business details data
|
|
92
|
+
* is presented on the main page.
|
|
93
|
+
*
|
|
94
|
+
* If a source is provided, that section is moved to the top of the list.
|
|
95
|
+
* Source indicates which link the user clicked to get to the fix list page.
|
|
96
|
+
*
|
|
97
|
+
* @param {Array<string>} sectionsNeedingUpdate - Sections identified as needing fixes
|
|
98
|
+
* @param {string} source - The section user clicked on (optional)
|
|
99
|
+
* @param {Array<string>} SECTION_ORDER - The defined order for sections
|
|
100
|
+
* @returns {Array<string>} Ordered list of sections to fix
|
|
101
|
+
*/
|
|
102
|
+
const orderSectionsToFix = (sectionsNeedingUpdate, source, SECTION_ORDER) => {
|
|
103
|
+
const sections = SECTION_ORDER.filter((section) => {
|
|
104
|
+
return sectionsNeedingUpdate.includes(section)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
if (!source) {
|
|
108
|
+
return sections
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Source comes from a URL query param, so only allow known section keys
|
|
112
|
+
// for this journey type to avoid injecting unexpected values into session state.
|
|
113
|
+
if (!SECTION_ORDER.includes(source)) {
|
|
114
|
+
return sections
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return [
|
|
118
|
+
source,
|
|
119
|
+
...sections.filter(section => section !== source)
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export {
|
|
124
|
+
initialiseFixJourneyService
|
|
125
|
+
}
|
package/src/services/services.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { addressLookupService } from './os-places/address-lookup-service.js'
|
|
2
2
|
import { buildUprnAddress, buildManualAddress } from './build-address-variables-service.js'
|
|
3
|
+
import { checkInterrupterJourneySessionService } from './check-interrupter-journey-session-service.js'
|
|
4
|
+
import { initialiseFixJourneyService } from './initialise-fix-journey-service.js'
|
|
5
|
+
import { validateFixDetailsService } from './validate-fix-details-service.js'
|
|
6
|
+
import { setFixSessionDataService } from './set-fix-session-data-service.js'
|
|
3
7
|
|
|
4
8
|
export const services = {
|
|
5
9
|
addressLookup: addressLookupService,
|
|
6
10
|
buildUprnAddress,
|
|
7
|
-
buildManualAddress
|
|
11
|
+
buildManualAddress,
|
|
12
|
+
checkInterrupterJourneySession: checkInterrupterJourneySessionService,
|
|
13
|
+
initialiseFixJourney: initialiseFixJourneyService,
|
|
14
|
+
validateFixDetails: validateFixDetailsService,
|
|
15
|
+
setFixSessionData: setFixSessionDataService
|
|
8
16
|
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stores fix journey data on the session.
|
|
3
|
+
*
|
|
4
|
+
* This service is used during the interrupter journey to persist form data
|
|
5
|
+
* as users progress through multiple steps. When users provide updates to
|
|
6
|
+
* invalid personal or business details, their input is stored in the session
|
|
7
|
+
* so it can be reviewed and submitted in later steps.
|
|
8
|
+
*
|
|
9
|
+
* The service automatically determines whether this is a personal or business
|
|
10
|
+
* journey by examining the journeyKey parameter, then structures the payload
|
|
11
|
+
* data according to the appropriate section-based schema.
|
|
12
|
+
*
|
|
13
|
+
* Why this matters:
|
|
14
|
+
* - Users may need to fix multiple detail sections (e.g., name + address + email)
|
|
15
|
+
* - Each section has its own set of fields defined in SECTION_FIELD_ORDER
|
|
16
|
+
* - By organizing data by section, the review page can easily iterate and
|
|
17
|
+
* display each section with its corresponding fields
|
|
18
|
+
* - Session storage preserves form state across page navigations
|
|
19
|
+
*
|
|
20
|
+
* Data structure example:
|
|
21
|
+
* For personal details with sections ['name', 'email']:
|
|
22
|
+
* {
|
|
23
|
+
* personalFixUpdates: {
|
|
24
|
+
* name: { first: 'John', middle: '', last: 'Doe' },
|
|
25
|
+
* email: { personalEmail: 'john@example.com' }
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* @module setFixSessionDataService
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import {
|
|
33
|
+
PERSONAL_SECTION_FIELD_ORDER,
|
|
34
|
+
BUSINESS_SECTION_FIELD_ORDER
|
|
35
|
+
} from '../constants/interrupter-journey.js'
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Maps form payload data into session storage, organized by detail sections.
|
|
39
|
+
*
|
|
40
|
+
* This function takes flat form submission data and restructures it into a
|
|
41
|
+
* hierarchical object where each section (e.g., 'name', 'email', 'address')
|
|
42
|
+
* contains its corresponding fields. Any fields missing from the payload
|
|
43
|
+
* are populated with empty strings, ensuring the session always has a
|
|
44
|
+
* complete structure for downstream presenters and services.
|
|
45
|
+
*
|
|
46
|
+
* The section-based structure is essential because:
|
|
47
|
+
* 1. The fix journey is organized by sections that need fixing
|
|
48
|
+
* 2. The review page displays each section separately
|
|
49
|
+
* 3. The mutation needs to know which fields belong to which section
|
|
50
|
+
* 4. Presenters can easily iterate sections and their fields
|
|
51
|
+
*
|
|
52
|
+
* @param {Object} yar - Hapi session object with get/set methods
|
|
53
|
+
* @param {Object} sessionData - Current session data object to be mutated; expects sessionData.orderedSectionsToFix to exist
|
|
54
|
+
* @param {Object} payload - Flat form submission data (e.g., { first: 'John', last: 'Doe', personalEmail: '...' })
|
|
55
|
+
* Example: ['name', 'address', 'email'] - order matches the presentation order
|
|
56
|
+
* @param {string} journeyKey - Session key that identifies the journey type
|
|
57
|
+
* - 'personalDetailsValidation' for personal details
|
|
58
|
+
* - 'businessDetailsValidation' for business details
|
|
59
|
+
* This key is used to auto-detect the journey type
|
|
60
|
+
* @param {string} updateKey - Object key where the structured updates are stored
|
|
61
|
+
* - 'personalFixUpdates' for personal details
|
|
62
|
+
* - 'businessFixUpdates' for business details
|
|
63
|
+
*
|
|
64
|
+
* @returns {void} Modifies sessionData in place and persists via yar.set()
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* // Store personal detail updates
|
|
68
|
+
* setFixSessionDataService(
|
|
69
|
+
* yar,
|
|
70
|
+
* sessionData,
|
|
71
|
+
* { first: 'Jane', last: '', personalEmail: 'jane@example.com' },
|
|
72
|
+
* 'personalDetailsValidation',
|
|
73
|
+
* 'personalFixUpdates'
|
|
74
|
+
* )
|
|
75
|
+
* // Result: sessionData.personalFixUpdates = {
|
|
76
|
+
* // name: { first: 'Jane', middle: '', last: '' },
|
|
77
|
+
* // email: { personalEmail: 'jane@example.com' }
|
|
78
|
+
* // }
|
|
79
|
+
*/
|
|
80
|
+
const setFixSessionDataService = (
|
|
81
|
+
yar,
|
|
82
|
+
sessionData,
|
|
83
|
+
payload,
|
|
84
|
+
journeyKey,
|
|
85
|
+
updateKey
|
|
86
|
+
) => {
|
|
87
|
+
const orderedSectionsToFix = sessionData.orderedSectionsToFix
|
|
88
|
+
// Determine type from journey key
|
|
89
|
+
// This allows the service to auto-select the correct field schema
|
|
90
|
+
const type = journeyKey === 'businessDetailsValidation' ? 'business' : 'personal'
|
|
91
|
+
|
|
92
|
+
// Select the appropriate field order based on type
|
|
93
|
+
// Each type (personal/business) has different fields for each section
|
|
94
|
+
const SECTION_FIELD_ORDER = type === 'business' ? BUSINESS_SECTION_FIELD_ORDER : PERSONAL_SECTION_FIELD_ORDER
|
|
95
|
+
|
|
96
|
+
const fixUpdates = {}
|
|
97
|
+
|
|
98
|
+
// Loop through each section that needs fixing (e.g. name, email)
|
|
99
|
+
// The order is preserved from orderedSectionsToFix
|
|
100
|
+
for (const section of orderedSectionsToFix) {
|
|
101
|
+
const fields = SECTION_FIELD_ORDER[section]
|
|
102
|
+
|
|
103
|
+
fixUpdates[section] = {}
|
|
104
|
+
|
|
105
|
+
// Loop through each field in the section (e.g. firstName, lastName)
|
|
106
|
+
// This ensures all expected fields are present in the session,
|
|
107
|
+
// even if they weren't provided in the form submission
|
|
108
|
+
for (const field of fields) {
|
|
109
|
+
// Map the payload value to the session data, defaulting to an empty string if not provided
|
|
110
|
+
// Empty strings are used as defaults to maintain a consistent structure
|
|
111
|
+
// for downstream presenters and mutation builders
|
|
112
|
+
fixUpdates[section][field] = payload[field] ?? ''
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Store the structured updates in the session under the appropriate key
|
|
117
|
+
sessionData[updateKey] = fixUpdates
|
|
118
|
+
// Persist the updated session data
|
|
119
|
+
yar.set(journeyKey, sessionData)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export {
|
|
123
|
+
setFixSessionDataService
|
|
124
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates fix payload data for personal or business details.
|
|
3
|
+
*
|
|
4
|
+
* This service validates the payload for each section the user is fixing
|
|
5
|
+
* (e.g. name, date of birth, email, business details), running each provided
|
|
6
|
+
* Joi schema separately and collecting any validation errors.
|
|
7
|
+
*
|
|
8
|
+
* The schemas are passed into the service and validated individually rather
|
|
9
|
+
* than being combined into a single Joi schema. Combining schemas previously
|
|
10
|
+
* caused issues with custom validation logic. For example, the date of birth
|
|
11
|
+
* schema includes custom validation to check for real and valid dates. When
|
|
12
|
+
* schemas were combined, failures in other schemas could prevent this custom
|
|
13
|
+
* validation from running, meaning some errors were not surfaced.
|
|
14
|
+
*
|
|
15
|
+
* By validating each schema independently (and allowing unknown fields), we
|
|
16
|
+
* ensure that all section-specific validation logic runs correctly and that
|
|
17
|
+
* all relevant errors are returned to the user.
|
|
18
|
+
*
|
|
19
|
+
* @module validateFixDetailsService
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Validates payload against multiple schemas for different sections.
|
|
24
|
+
*
|
|
25
|
+
* @param {Object} payload - The form data to validate
|
|
26
|
+
* @param {Array<string>} orderedSectionsToFix - List of sections being fixed
|
|
27
|
+
* @param {Object} schemas - Map of section names to Joi schemas
|
|
28
|
+
* @returns {Object} Joi validation result with combined errors
|
|
29
|
+
*/
|
|
30
|
+
const validateFixDetailsService = (payload, orderedSectionsToFix, schemas) => {
|
|
31
|
+
const errors = []
|
|
32
|
+
|
|
33
|
+
for (const section of orderedSectionsToFix) {
|
|
34
|
+
const schema = schemas[section]
|
|
35
|
+
|
|
36
|
+
const result = schema.validate(payload, {
|
|
37
|
+
abortEarly: false,
|
|
38
|
+
allowUnknown: true
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
if (result.error) {
|
|
42
|
+
errors.push(...result.error.details)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (errors.length > 0) {
|
|
47
|
+
return {
|
|
48
|
+
error: {
|
|
49
|
+
details: errors
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return { value: payload }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export {
|
|
58
|
+
validateFixDetailsService
|
|
59
|
+
}
|