@gov-cy/govcy-express-services 1.3.0-alpha.5 → 1.3.0-alpha.7
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/README.md +158 -2
- package/package.json +1 -1
- package/src/middleware/govcyFileDeleteHandler.mjs +3 -1
- package/src/middleware/govcyFileUpload.mjs +3 -1
- package/src/middleware/govcyHttpErrorHandler.mjs +5 -0
- package/src/middleware/govcyReviewPostHandler.mjs +13 -10
- package/src/middleware/govcyServiceEligibilityHandler.mjs +15 -12
- package/src/middleware/govcySuccessPageHandler.mjs +10 -1
- package/src/middleware/govcyUpdateMyDetails.mjs +51 -8
- package/src/resources/govcyResources.mjs +78 -5
- package/src/utils/govcyUtils.mjs +12 -0
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@ The APIs used for submission, temporary save and file uploads are not part of th
|
|
|
33
33
|
- [🧩 Dynamic services](#-dynamic-services)
|
|
34
34
|
- [Pages](#pages)
|
|
35
35
|
- [Form vs static pages](#form-vs-static-pages)
|
|
36
|
+
- [Update my details pages](#update-my-details-pages)
|
|
36
37
|
- [Multiple things pages (repeating group of inputs)](#multiple-things-pages-repeating-group-of-inputs)
|
|
37
38
|
- [Review page](#review-page)
|
|
38
39
|
- [Success page](#success-page)
|
|
@@ -755,6 +756,8 @@ flowchart LR
|
|
|
755
756
|
|
|
756
757
|
Some pages are generated automatically by the project, such as the `review` and `success` pages.
|
|
757
758
|
|
|
759
|
+
------------------------------------------
|
|
760
|
+
|
|
758
761
|
#### Pages
|
|
759
762
|
|
|
760
763
|
Pages defined in the JSON file under the `pages` array, they rendered based on the [govcy-frontend-renderer](https://github.com/gov-cy/govcy-frontend-renderer) library, and they are served by the `/:siteId/:pageUrl` route. The `pageData.nextPage` field is used to determine the next page to render.
|
|
@@ -876,6 +879,8 @@ Lets break down the JSON config for this page:
|
|
|
876
879
|
- `sections` is an array of sections, which is an array of elements. Sections allowed: `beforeMain`, `main`, `afterMain`.
|
|
877
880
|
- `elements` is an array of elements for the said section. Seem more details on the [govcy-frontend-renderer's design elements documentation](https://github.com/gov-cy/govcy-frontend-renderer/blob/main/DESIGN_ELEMENTS.md).
|
|
878
881
|
|
|
882
|
+
------------------------------------------
|
|
883
|
+
|
|
879
884
|
#### Form vs static pages
|
|
880
885
|
|
|
881
886
|
- If the `pageTemplate` includes a `form` element in the `main` section and `button` element, the system will treat it as form and will:
|
|
@@ -909,6 +914,147 @@ The [start page](https://gov-cy.github.io/govcy-design-system-docs/patterns/serv
|
|
|
909
914
|
- Check out the [govcy-frontend-renderer's design elements](https://github.com/gov-cy/govcy-frontend-renderer/blob/main/DESIGN_ELEMENTS.md) for more details on the supported elements and their parameters.
|
|
910
915
|
- Check out the [input validations section](#-input-validations) for more details on how to add validations to the JSON file.
|
|
911
916
|
|
|
917
|
+
-------------------------------------------
|
|
918
|
+
|
|
919
|
+
#### Update my details pages
|
|
920
|
+
|
|
921
|
+

|
|
922
|
+
|
|
923
|
+
Update my details pages are pages that can integrate the [Update My Personal Details service](https://update-my-details.service.gov.cy/) to fetch or update a user’s name, email, mobile number, or correspondence address, without breaking the user journey. The implementation of these pages follow the instructuctions described in the [Use ‘Update my personal details’ in Your Service](https://dsf.dmrid.gov.cy/2025/05/20/use-update-my-personal-details-in-your-service/) post.
|
|
924
|
+
|
|
925
|
+
If the `scope` also includes the `email` element, the system will also use that email address to send the email to the user on submition.
|
|
926
|
+
|
|
927
|
+
**Update my details - example JSON config**
|
|
928
|
+
```json
|
|
929
|
+
{
|
|
930
|
+
"pageData": {
|
|
931
|
+
"url": "index", // Page URL
|
|
932
|
+
"layout": "layouts/govcyBase.njk",
|
|
933
|
+
"mainLayout": "two-third",
|
|
934
|
+
"nextPage": "next-page"
|
|
935
|
+
},
|
|
936
|
+
"updateMyDetails": {
|
|
937
|
+
"APIEndpoint": { // API endpoint for fetching user details from the Update My Details service
|
|
938
|
+
"url": "CIVIL_REGISTRY_CONTACT_API_URL", // URL
|
|
939
|
+
"method": "GET", // HTTP method
|
|
940
|
+
"clientKey": "DSF_API_GTW_CLIENT_ID", // Client key
|
|
941
|
+
"serviceId": "DSF_API_GTW_SERVICE_ID", // Service ID
|
|
942
|
+
"dsfgtwApiKey": "DSF_API_GTW_SECRET" // DSF GTW API key
|
|
943
|
+
},
|
|
944
|
+
"updateMyDetailsURL": "UPDATE_MY_DETAILS_URL", // DOMAIN URL for redirecting to the Update My Details service
|
|
945
|
+
"topElements": [ // Elements to be displayed on the top of the page
|
|
946
|
+
{
|
|
947
|
+
"element": "progressList",
|
|
948
|
+
"params": {
|
|
949
|
+
"id": "steps",
|
|
950
|
+
"current": "4",
|
|
951
|
+
"total": "4",
|
|
952
|
+
"showSteps": true
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
],
|
|
956
|
+
"scope": [ // Scope of the form. What elenents to collect
|
|
957
|
+
"fullName",
|
|
958
|
+
"email",
|
|
959
|
+
"mobile",
|
|
960
|
+
"address"
|
|
961
|
+
],
|
|
962
|
+
"hasBackLink": true // Whether the hub page has a back link
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
Lets break down the JSON config for Update my details:
|
|
969
|
+
|
|
970
|
+
- **updateMyDetails** are the page's definition for the integration with the Update My Details service.
|
|
971
|
+
- `updateMyDetails.APIEndpoint` is the API endpoint for fetching user details from the Update My Details service.
|
|
972
|
+
- `updateMyDetails.updateMyDetailsURL` is the DOMAIN URL for redirecting to the Update My Details service.
|
|
973
|
+
- `updateMyDetails.scope` is the scope of the form. What elenents to collect. It can be one or more of the following:
|
|
974
|
+
- `fullName`
|
|
975
|
+
- `dob`
|
|
976
|
+
- `email`
|
|
977
|
+
- `mobile`
|
|
978
|
+
- `address`
|
|
979
|
+
- `updateMyDetails.hasBackLink` is a boolean that indicates whether the hub page has a back link.
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
The above config references the following environment variables that need to be set:
|
|
983
|
+
|
|
984
|
+
```dotenv
|
|
985
|
+
### Update my details
|
|
986
|
+
CIVIL_REGISTRY_CONTACT_API_URL=http://localhost:3002/get-update-my-details
|
|
987
|
+
DSF_API_GTW_CLIENT_ID=your-DSF-API-gateway-client-id
|
|
988
|
+
DSF_API_GTW_SERVICE_ID=your-DSF-API-gateway-service-id
|
|
989
|
+
DSF_API_GTW_SECRET=your-DSF-API-gateway-secret
|
|
990
|
+
|
|
991
|
+
UPDATE_MY_DETAILS_URL=https://update-my-details.staging.service.gov.cy # FOR TESTING
|
|
992
|
+
```
|
|
993
|
+
|
|
994
|
+
The DSF team has developed an API that performs standard eligibility checks against the Civil Registry. More details at [Update-my-details.md](docs/Update-my-details.md)
|
|
995
|
+
|
|
996
|
+
**Update my details - users' flow**
|
|
997
|
+
|
|
998
|
+
The update my details behaves like a normal page and it is accessed through the url `:siteId/:pageUrl`. As a best practice you should set this as your `index` page and the first one in your pages array. Depending on the user it can have 3 variants:
|
|
999
|
+
|
|
1000
|
+
**Variant 1: Manual form for non-eligible users (no access to UMD)**
|
|
1001
|
+
|
|
1002
|
+
When a user is either:
|
|
1003
|
+
- Not a Cypriot citizen
|
|
1004
|
+
- Or Cypriot citizen under 18
|
|
1005
|
+
|
|
1006
|
+
The user gets a data entry page.
|
|
1007
|
+
|
|
1008
|
+

|
|
1009
|
+
|
|
1010
|
+
**Variant 2: Eligible users (access to UMD) with existing details**
|
|
1011
|
+
|
|
1012
|
+
When a user is :
|
|
1013
|
+
- A Cypriot citizen over 18
|
|
1014
|
+
- AND has data in Update my Details
|
|
1015
|
+
|
|
1016
|
+
The users get a page with the data from UMD and asks if its ok to use those data.
|
|
1017
|
+
|
|
1018
|
+

|
|
1019
|
+
|
|
1020
|
+
If the user selects:
|
|
1021
|
+
- `YES`: the data are stored in the data layer and continues to the next page (or review page depending where the user came from)
|
|
1022
|
+
- `NO`: the users are redirected to the Update my details service in seamless mode. When users finish with that, they are redirected back to the page with variant 2 and are asked again if it's ok to use the updated data.
|
|
1023
|
+
|
|
1024
|
+
**Variant 3: Eligible users (access to UMD) without existing details**
|
|
1025
|
+
|
|
1026
|
+
When a user is :
|
|
1027
|
+
- A Cypriot citizen over 18
|
|
1028
|
+
- AND has no data in Update my Details
|
|
1029
|
+
|
|
1030
|
+
The users get a continue button that redirects to the Update my details service in seamless mode.
|
|
1031
|
+
|
|
1032
|
+

|
|
1033
|
+
|
|
1034
|
+
When users finish with that, they are redirected back to the page with variant 2 and are asked if it's ok to use the updated data.
|
|
1035
|
+
|
|
1036
|
+
**Update my details - data storage**
|
|
1037
|
+
|
|
1038
|
+
The form data for a `updateMyDetails` page is stored as a normal page as an **object** in the session data layer:
|
|
1039
|
+
```json
|
|
1040
|
+
{
|
|
1041
|
+
"index": {
|
|
1042
|
+
"formData":
|
|
1043
|
+
{
|
|
1044
|
+
"fullName": "John Smith",
|
|
1045
|
+
"email": "email@example.com",
|
|
1046
|
+
"mobile": "+35712345678",
|
|
1047
|
+
"address": "123 Some Street\n Nicosia\nCyprus",
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
```
|
|
1052
|
+
|
|
1053
|
+
**Notes on Update my details**
|
|
1054
|
+
- There `pageData.title` is not used. Instead the page title is generated by the system.
|
|
1055
|
+
|
|
1056
|
+
------------------------------------------
|
|
1057
|
+
|
|
912
1058
|
#### Multiple things pages (repeating group of inputs)
|
|
913
1059
|

|
|
914
1060
|
|
|
@@ -1129,6 +1275,8 @@ Form data for a `multipleThings` page is stored as an **array** in the session d
|
|
|
1129
1275
|
- `multipleDraft` is used internally to store file's data while the user is adding a new item.
|
|
1130
1276
|
|
|
1131
1277
|
|
|
1278
|
+
------------------------------------------
|
|
1279
|
+
|
|
1132
1280
|
#### Review page
|
|
1133
1281
|
|
|
1134
1282
|
The `review` page is automatically generated by the project and includes the following sections:
|
|
@@ -1145,6 +1293,8 @@ When the user clicks a change link, the user is redirected to the corresponding
|
|
|
1145
1293
|
|
|
1146
1294
|
When the user clicks the `Submit` button, all the data gathered from the site's forms within this session are validated based on the validation definition in the JSON file, and if they pass they are submitted to the configured API endpoint.
|
|
1147
1295
|
|
|
1296
|
+
------------------------------------------
|
|
1297
|
+
|
|
1148
1298
|
#### Success page
|
|
1149
1299
|
|
|
1150
1300
|
The `success` page is automatically generated by the project, is accessible only when a submission is made successfully, and includes the following sections:
|
|
@@ -1157,6 +1307,8 @@ Here's an example screenshot of success page
|
|
|
1157
1307
|
|
|
1158
1308
|

|
|
1159
1309
|
|
|
1310
|
+
--------------------------------
|
|
1311
|
+
|
|
1160
1312
|
### 🛡️ Site eligibility checks
|
|
1161
1313
|
|
|
1162
1314
|
The project uses an array of API endpoints to check the eligibility of a service/site. To use this feature, you need to configure the following in your JSON file under the `site` object:
|
|
@@ -2479,7 +2631,7 @@ The environment variables are defined in:
|
|
|
2479
2631
|
- `.env.production` for production
|
|
2480
2632
|
|
|
2481
2633
|
#### Secret environment variables
|
|
2482
|
-
The following secret environment variables are used to configure the server:
|
|
2634
|
+
The following secret environment variables are used to configure the server (note the values below are examples, you need to replace them with your own values):
|
|
2483
2635
|
|
|
2484
2636
|
```dotenv
|
|
2485
2637
|
# 🔐 Session
|
|
@@ -2553,9 +2705,13 @@ TEST_FILE_DELETE_API_URL=http://localhost:3002/fileDelete
|
|
|
2553
2705
|
# Eligibility checks (optional test APIs)
|
|
2554
2706
|
TEST_ELIGIBILITY_1_API_URL=http://localhost:3002/eligibility1
|
|
2555
2707
|
TEST_ELIGIBILITY_2_API_URL=http://localhost:3002/eligibility2
|
|
2708
|
+
|
|
2709
|
+
# Update my details
|
|
2710
|
+
CIVIL_REGISTRY_CONTACT_API_URL=http://localhost:3002/get-update-my-details
|
|
2711
|
+
UPDATE_MY_DETAILS_URL=https://update-my-details.staging.service.gov.cy
|
|
2556
2712
|
```
|
|
2557
2713
|
#### Non secret environment variables
|
|
2558
|
-
The following non-secret environment variables are used to configure the server defined in `.env.development` for local development, `.env.staging` for staging, and `.env.production` for production
|
|
2714
|
+
The following non-secret environment variables are used to configure the server defined in `.env.development` for local development, `.env.staging` for staging, and `.env.production` for production:
|
|
2559
2715
|
|
|
2560
2716
|
```dotenv
|
|
2561
2717
|
#### Matomo web analytics environment variables
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gov-cy/govcy-express-services",
|
|
3
|
-
"version": "1.3.0-alpha.
|
|
3
|
+
"version": "1.3.0-alpha.7",
|
|
4
4
|
"description": "An Express-based system that dynamically renders services using @gov-cy/govcy-frontend-renderer and posts data to a submission API.",
|
|
5
5
|
"author": "DMRID - DSF Team",
|
|
6
6
|
"license": "MIT",
|
|
@@ -53,7 +53,9 @@ export function govcyFileDeletePageHandler() {
|
|
|
53
53
|
|
|
54
54
|
// Guard if still nothing found
|
|
55
55
|
if (!elementData || !elementData.fileId || !elementData.sha256) {
|
|
56
|
-
|
|
56
|
+
logger.info(`govcyFileDeletePageHandler: File data not found for element [${elementName}] on page [${pageUrl}] in site [${siteId}]. Redirecting to "${siteId}/${pageUrl}".`);
|
|
57
|
+
return res.redirect(govcyResources.constructPageUrl(siteId, pageUrl, (req.query.route === "review" ? "review" : "")))
|
|
58
|
+
// return handleMiddlewareError(`File input [${elementName}] data not found on this page`, 404, next);
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
|
|
@@ -4,6 +4,7 @@ import { successResponse, errorResponse } from '../utils/govcyApiResponse.mjs';
|
|
|
4
4
|
import { ALLOWED_MULTER_FILE_SIZE_MB } from "../utils/govcyConstants.mjs";
|
|
5
5
|
import { handleFileUpload } from "../utils/govcyHandleFiles.mjs";
|
|
6
6
|
|
|
7
|
+
/* c8 ignore start */
|
|
7
8
|
// Configure multer to store the file in memory (not disk) and limit the size to 10MB
|
|
8
9
|
const upload = multer({
|
|
9
10
|
storage: multer.memoryStorage(),
|
|
@@ -46,4 +47,5 @@ export const govcyFileUpload = [
|
|
|
46
47
|
|
|
47
48
|
return res.json(successResponse(result.data));
|
|
48
49
|
}
|
|
49
|
-
];
|
|
50
|
+
];
|
|
51
|
+
/* c8 ignore end */
|
|
@@ -52,6 +52,11 @@ export function govcyHttpErrorHandler(err, req, res, next) {
|
|
|
52
52
|
res.status(statusCode);
|
|
53
53
|
|
|
54
54
|
if (isApiRequest(req)) {
|
|
55
|
+
if (err.code === `LIMIT_FILE_SIZE` && err.name === `MulterError`) {
|
|
56
|
+
statusCode = 409;
|
|
57
|
+
message = "File exceeds allowed size";
|
|
58
|
+
return res.status(400).json(errorResponse(statusCode, message));
|
|
59
|
+
}
|
|
55
60
|
return res.status(statusCode).json(errorResponse(statusCode, message));
|
|
56
61
|
}
|
|
57
62
|
|
|
@@ -163,6 +163,18 @@ export function govcyReviewPostHandler() {
|
|
|
163
163
|
// Add the reference number to the submission data
|
|
164
164
|
submissionData.referenceNumber = referenceNo;
|
|
165
165
|
logger.info("✅ Data submitted", siteId, referenceNo);
|
|
166
|
+
|
|
167
|
+
// Get the user email address
|
|
168
|
+
let emailAddress = "";
|
|
169
|
+
// if Update my details not provided the use user email
|
|
170
|
+
if (!updateMyDetailsData || !updateMyDetailsData.email) {
|
|
171
|
+
emailAddress = dataLayer.getUser(req.session).email;
|
|
172
|
+
} else {
|
|
173
|
+
emailAddress = updateMyDetailsData.email;
|
|
174
|
+
}
|
|
175
|
+
// add contact email to submission data
|
|
176
|
+
submissionData.contactEmailAddress = emailAddress;
|
|
177
|
+
|
|
166
178
|
// handle data layer submission
|
|
167
179
|
dataLayer.storeSiteSubmissionData(
|
|
168
180
|
req.session,
|
|
@@ -172,16 +184,7 @@ export function govcyReviewPostHandler() {
|
|
|
172
184
|
//-- Send email to user
|
|
173
185
|
// Generate the email body
|
|
174
186
|
let emailBody = generateSubmitEmail(service, submissionData.printFriendlyData, referenceNo, req);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
let emailAddress = "";
|
|
178
|
-
// if Update my details not provided the use user email
|
|
179
|
-
if (!updateMyDetailsData || !updateMyDetailsData.email) {
|
|
180
|
-
emailAddress = dataLayer.getUser(req.session).email;
|
|
181
|
-
} else {
|
|
182
|
-
emailAddress = updateMyDetailsData.email;
|
|
183
|
-
}
|
|
184
|
-
|
|
187
|
+
|
|
185
188
|
// Send the email
|
|
186
189
|
sendEmail(
|
|
187
190
|
service.site.title[service.site.lang],
|
|
@@ -26,19 +26,22 @@ export function govcyServiceEligibilityHandler(checkForForm = false) {
|
|
|
26
26
|
if (!pageUrl) pageUrl = "index";
|
|
27
27
|
// 🔍 Find the page by pageUrl
|
|
28
28
|
const page = getPageConfigData(service, pageUrl);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
section
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
29
|
+
// ----- `updateMyDetails` handling. always run eligibility for updateMyDetails
|
|
30
|
+
if (!page.updateMyDetails) {
|
|
31
|
+
if (!page || !page.pageTemplate) return next(); // Defensive: skip if no template
|
|
32
|
+
// Deep copy pageTemplate to avoid modifying the original
|
|
33
|
+
const pageTemplateCopy = JSON.parse(JSON.stringify(page.pageTemplate));
|
|
34
|
+
|
|
35
|
+
// Check if any section contains a form element
|
|
36
|
+
const hasForm = pageTemplateCopy.sections?.some(section =>
|
|
37
|
+
section.elements?.some(el => el.element === "form")
|
|
38
|
+
);
|
|
39
|
+
if (!hasForm) {
|
|
40
|
+
// No form found, skip eligibility check
|
|
41
|
+
return next();
|
|
42
|
+
}
|
|
43
|
+
// else: continue with eligibility check
|
|
40
44
|
}
|
|
41
|
-
// else: continue with eligibility check
|
|
42
45
|
}
|
|
43
46
|
const eligibilityEndpoints = service?.site?.eligibilityAPIEndpoints || [];
|
|
44
47
|
const user = dataLayer.getUser(req.session); // Get the user from the session;
|
|
@@ -44,12 +44,21 @@ export function govcySuccessPageHandler(isPDF = false) {
|
|
|
44
44
|
// }
|
|
45
45
|
]
|
|
46
46
|
};
|
|
47
|
+
|
|
48
|
+
let weHaveSendYouAnEmailText = JSON.parse(JSON.stringify(govcyResources.staticResources.text.weHaveSendYouAnEmail));
|
|
49
|
+
// Replace label placeholders for email
|
|
50
|
+
for (const lang of Object.keys(weHaveSendYouAnEmailText)) {
|
|
51
|
+
weHaveSendYouAnEmailText[lang] = weHaveSendYouAnEmailText[lang].replace("{{email}}",
|
|
52
|
+
submissionData.contactEmailAddress || ""
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
47
56
|
// Construct page title
|
|
48
57
|
const weHaveSendYouAnEmail = {
|
|
49
58
|
element: "textElement",
|
|
50
59
|
params: {
|
|
51
60
|
type: "p",
|
|
52
|
-
text:
|
|
61
|
+
text: weHaveSendYouAnEmailText
|
|
53
62
|
}
|
|
54
63
|
};
|
|
55
64
|
|
|
@@ -14,7 +14,7 @@ import { getEnvVariable, getEnvVariableBool, isProdOrStaging } from "../utils/go
|
|
|
14
14
|
import * as govcyResources from "../resources/govcyResources.mjs";
|
|
15
15
|
import * as dataLayer from "../utils/govcyDataLayer.mjs";
|
|
16
16
|
import { logger } from '../utils/govcyLogger.mjs';
|
|
17
|
-
import { handleMiddlewareError } from "../utils/govcyUtils.mjs";
|
|
17
|
+
import { handleMiddlewareError, dateStringISOtoDMY } from "../utils/govcyUtils.mjs";
|
|
18
18
|
import { govcyApiRequest } from "../utils/govcyApiRequest.mjs";
|
|
19
19
|
import { isUnder18, isValidCypriotCitizen, validateFormElements } from "../utils/govcyValidator.mjs";
|
|
20
20
|
import { populateFormData, getFormData } from "../utils/govcyFormHandling.mjs";
|
|
@@ -128,8 +128,21 @@ export async function govcyUpdateMyDetailsHandler(req, res, next, page, serviceC
|
|
|
128
128
|
// Special case for address
|
|
129
129
|
if (element === "address") {
|
|
130
130
|
key = "addressInfo";
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
//if response.Data.addressInfo is an array
|
|
132
|
+
if (response.Data.addressInfo && Array.isArray(response.Data.addressInfo)) {
|
|
133
|
+
value = response.Data?.addressInfo?.[0]?.addressText || "";
|
|
134
|
+
}
|
|
135
|
+
// else if response.Data.addressInfoUnstructured is not null and is an array
|
|
136
|
+
else if (response.Data.addressInfoUnstructured && Array.isArray(response.Data.addressInfoUnstructured)) {
|
|
137
|
+
value = response.Data?.addressInfoUnstructured?.[0]?.addressText || "";
|
|
138
|
+
}
|
|
139
|
+
// else if response.Data.poBoxAddress is not null and is not an array
|
|
140
|
+
else if (response.Data.poBoxAddress && Array.isArray(response.Data.poBoxAddress)) {
|
|
141
|
+
value = response.Data?.poBoxAddress?.[0]?.poBoxText || "";
|
|
142
|
+
} else {
|
|
143
|
+
value = "";
|
|
144
|
+
}
|
|
145
|
+
}
|
|
133
146
|
|
|
134
147
|
// Check if the key exists
|
|
135
148
|
if (!Object.prototype.hasOwnProperty.call(response.Data || {}, key)) {
|
|
@@ -375,8 +388,21 @@ export function govcyUpdateMyDetailsPostHandler() {
|
|
|
375
388
|
// Special case for address
|
|
376
389
|
if (element === "address") {
|
|
377
390
|
key = "addressInfo";
|
|
378
|
-
|
|
379
|
-
|
|
391
|
+
//if response.Data.addressInfo is an array
|
|
392
|
+
if (response.Data.addressInfo && Array.isArray(response.Data.addressInfo)) {
|
|
393
|
+
value = response.Data?.addressInfo?.[0]?.addressText || "";
|
|
394
|
+
}
|
|
395
|
+
// else if response.Data.addressInfoUnstructured is not null and is an array
|
|
396
|
+
else if (response.Data.addressInfoUnstructured && Array.isArray(response.Data.addressInfoUnstructured)) {
|
|
397
|
+
value = response.Data?.addressInfoUnstructured?.[0]?.addressText || "";
|
|
398
|
+
}
|
|
399
|
+
// else if response.Data.poBoxAddress is not null and is not an array
|
|
400
|
+
else if (response.Data.poBoxAddress && Array.isArray(response.Data.poBoxAddress)) {
|
|
401
|
+
value = response.Data?.poBoxAddress?.[0]?.poBoxText || "";
|
|
402
|
+
} else {
|
|
403
|
+
value = "";
|
|
404
|
+
}
|
|
405
|
+
}
|
|
380
406
|
|
|
381
407
|
// Check if the key exists
|
|
382
408
|
if (!Object.prototype.hasOwnProperty.call(response.Data || {}, key)) {
|
|
@@ -390,8 +416,18 @@ export function govcyUpdateMyDetailsPostHandler() {
|
|
|
390
416
|
hasData = false;
|
|
391
417
|
userDetails[element] = "";
|
|
392
418
|
} else {
|
|
393
|
-
|
|
394
|
-
|
|
419
|
+
if (element === "dob") {
|
|
420
|
+
key = "dob";
|
|
421
|
+
// value = response.Data?.[key] || "";
|
|
422
|
+
// Store different for ${element}_day, ${element}_month, ${element}_year
|
|
423
|
+
const [year, month, day] = value.split("-").map(Number);
|
|
424
|
+
userDetails[`${element}_day`] = day;
|
|
425
|
+
userDetails[`${element}_month`] = month;
|
|
426
|
+
userDetails[`${element}_year`] = year;
|
|
427
|
+
} else {
|
|
428
|
+
// Set the value as it is
|
|
429
|
+
userDetails[element] = value;
|
|
430
|
+
}
|
|
395
431
|
}
|
|
396
432
|
}
|
|
397
433
|
|
|
@@ -570,6 +606,12 @@ function createUmdHasDataPageTemplate(siteId, lang, page, req, userDetails) {
|
|
|
570
606
|
}
|
|
571
607
|
//for each element in the scope array
|
|
572
608
|
umdConfig?.scope.forEach(element => {
|
|
609
|
+
let value = userDetails?.[element] || "";
|
|
610
|
+
|
|
611
|
+
//if element is dob
|
|
612
|
+
if (element === "dob") {
|
|
613
|
+
value = dateStringISOtoDMY(value);
|
|
614
|
+
}
|
|
573
615
|
// add the key and value to the summaryList
|
|
574
616
|
summaryList.params.items.push({
|
|
575
617
|
key: govcyResources.staticResources.text.updateMyDetailsScopes[element],
|
|
@@ -579,7 +621,7 @@ function createUmdHasDataPageTemplate(siteId, lang, page, req, userDetails) {
|
|
|
579
621
|
params: {
|
|
580
622
|
type: "span",
|
|
581
623
|
classes: "govcy-whitespace-pre-line",
|
|
582
|
-
text: govcyResources.getSameMultilingualObject(null,
|
|
624
|
+
text: govcyResources.getSameMultilingualObject(null, value)
|
|
583
625
|
}
|
|
584
626
|
}
|
|
585
627
|
]
|
|
@@ -747,3 +789,4 @@ export function constructUpdateMyDetailsRedirect(req, userId, umdBaseURL, return
|
|
|
747
789
|
// Construct redirect URL
|
|
748
790
|
return `${umdBaseURL}/ReturnUrl/SetReturnUrl?Url=${encodedReturnUrl}&UserProfileId=${encodedUserId}&lang=${lang}`;
|
|
749
791
|
}
|
|
792
|
+
|
|
@@ -102,9 +102,9 @@ export const staticResources = {
|
|
|
102
102
|
tr: "Your reference number: "
|
|
103
103
|
},
|
|
104
104
|
weHaveSendYouAnEmail: {
|
|
105
|
-
en: "We have sent you a confirmation email.",
|
|
106
|
-
el: "Έχουμε στείλει email
|
|
107
|
-
tr: "We have sent you a confirmation email."
|
|
105
|
+
en: "We have sent you a confirmation email at \"{{email}}\".",
|
|
106
|
+
el: "Έχουμε στείλει email επιβεβαιωσης στο \"{{email}}\".",
|
|
107
|
+
tr: "We have sent you a confirmation email at \"{{email}}\"."
|
|
108
108
|
},
|
|
109
109
|
theDataFromYourRequest: {
|
|
110
110
|
en: "The data from your request: ",
|
|
@@ -239,7 +239,7 @@ export const staticResources = {
|
|
|
239
239
|
updateMyDetailsScopes : {
|
|
240
240
|
fullName :
|
|
241
241
|
{
|
|
242
|
-
el: "
|
|
242
|
+
el: "Ονοματεπώνυμο",
|
|
243
243
|
en: "Full name",
|
|
244
244
|
tr: "Full name"
|
|
245
245
|
},
|
|
@@ -261,6 +261,12 @@ export const staticResources = {
|
|
|
261
261
|
en: "Mailing address",
|
|
262
262
|
tr: "Mailing address"
|
|
263
263
|
},
|
|
264
|
+
dob :
|
|
265
|
+
{
|
|
266
|
+
el: "Ημερομηνία γέννησης",
|
|
267
|
+
en: "Date of birth",
|
|
268
|
+
tr: "Date of birth"
|
|
269
|
+
},
|
|
264
270
|
}
|
|
265
271
|
},
|
|
266
272
|
//remderer sections
|
|
@@ -312,7 +318,7 @@ export const staticResources = {
|
|
|
312
318
|
name: "useTheseDetails",
|
|
313
319
|
legend: {
|
|
314
320
|
el: "Να χρησιμοποιήσουμε αυτά τα στοιχεία;",
|
|
315
|
-
en: "Should we use these
|
|
321
|
+
en: "Should we use these details?"
|
|
316
322
|
},
|
|
317
323
|
items: [
|
|
318
324
|
{
|
|
@@ -329,6 +335,11 @@ export const staticResources = {
|
|
|
329
335
|
el: "Όχι, θα αλλάξω αυτά τα στοιχεία",
|
|
330
336
|
en: "No, I will change these details",
|
|
331
337
|
tr: ""
|
|
338
|
+
},
|
|
339
|
+
hint: {
|
|
340
|
+
el: "Μπορείτε να αλλάξετε μόνο τα στοιχεία επικοινωνίας",
|
|
341
|
+
en: "You can only change your contact details",
|
|
342
|
+
tr: ""
|
|
332
343
|
}
|
|
333
344
|
}
|
|
334
345
|
],
|
|
@@ -603,6 +614,68 @@ export const staticResources = {
|
|
|
603
614
|
}
|
|
604
615
|
}
|
|
605
616
|
]
|
|
617
|
+
},
|
|
618
|
+
"dob" : {
|
|
619
|
+
element: "dateInput",
|
|
620
|
+
params: {
|
|
621
|
+
id: "dob",
|
|
622
|
+
name: "dob",
|
|
623
|
+
legend: {
|
|
624
|
+
el: "Ημερομηνία γέννησης",
|
|
625
|
+
en: "Date of birth"
|
|
626
|
+
},
|
|
627
|
+
isPageHeading: false,
|
|
628
|
+
hint: {
|
|
629
|
+
el: "Για παράδειγμα, 13 8 2001",
|
|
630
|
+
en: "For example, 13 8 2001"
|
|
631
|
+
}
|
|
632
|
+
},
|
|
633
|
+
validations: [
|
|
634
|
+
{
|
|
635
|
+
check: "required",
|
|
636
|
+
params: {
|
|
637
|
+
checkValue: "",
|
|
638
|
+
message: {
|
|
639
|
+
el: "Εισαγάγετε την ημερομηνία γέννησης",
|
|
640
|
+
en: "Enter the date of birth",
|
|
641
|
+
tr: ""
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
check: "valid",
|
|
647
|
+
params: {
|
|
648
|
+
checkValue: "dateISO",
|
|
649
|
+
message: {
|
|
650
|
+
el: "Η ημερομηνία γέννησης πρέπει να είναι σωστή ημερομηνία",
|
|
651
|
+
en: "The date of birth must be an valid date",
|
|
652
|
+
tr: ""
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
check: "minValueDate",
|
|
658
|
+
params: {
|
|
659
|
+
checkValue: "1900-01-01",
|
|
660
|
+
message: {
|
|
661
|
+
el: "Η ημερομηνία γέννησης πρέπει να είναι μετά από τις 1/1/1990",
|
|
662
|
+
en: "The date of birth must be after 1/1/1900",
|
|
663
|
+
tr: ""
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
check: "valid",
|
|
669
|
+
params: {
|
|
670
|
+
checkValue: "maxCurrentDate",
|
|
671
|
+
message: {
|
|
672
|
+
el: "Η ημερομηνία γέννησης δεν πρέπει να είναι στο μέλλον",
|
|
673
|
+
en: "The date of birth must not be in the future",
|
|
674
|
+
tr: ""
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
]
|
|
606
679
|
}
|
|
607
680
|
},
|
|
608
681
|
govcyFormsJs: {
|
package/src/utils/govcyUtils.mjs
CHANGED
|
@@ -10,4 +10,16 @@ export function handleMiddlewareError(message, status, next) {
|
|
|
10
10
|
const error = new Error(message);
|
|
11
11
|
error.status = status;
|
|
12
12
|
return next(error);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Helper function to format a date in the format D/M/YYYY.
|
|
17
|
+
*
|
|
18
|
+
* @param {string} dateString - The date string in the format YYYY-MM-DD.
|
|
19
|
+
* @returns {string} The formatted date in the format D/M/YYYY.
|
|
20
|
+
*/
|
|
21
|
+
export function dateStringISOtoDMY(dateString) {
|
|
22
|
+
if (typeof dateString !== "string" || !dateString.trim()) return "";
|
|
23
|
+
const [year, month, day] = dateString.trim().split("-");
|
|
24
|
+
return `${parseInt(day)}/${parseInt(month)}/${year}`;
|
|
13
25
|
}
|