@gov-cy/govcy-express-services 1.3.0-alpha.4 → 1.3.0-alpha.6
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
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.6",
|
|
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",
|
|
@@ -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 */
|
|
@@ -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)) {
|
|
@@ -162,6 +175,9 @@ export async function govcyUpdateMyDetailsHandler(req, res, next, page, serviceC
|
|
|
162
175
|
}
|
|
163
176
|
}
|
|
164
177
|
|
|
178
|
+
// Deep copy pageTemplate to avoid modifying the original
|
|
179
|
+
const pageTemplateCopy = JSON.parse(JSON.stringify(pageTemplate));
|
|
180
|
+
|
|
165
181
|
// if the page variant is 1 or 2 which means it has a form
|
|
166
182
|
if (pageVariant === 1 || pageVariant === 2) {
|
|
167
183
|
// Handle form data
|
|
@@ -181,7 +197,7 @@ export async function govcyUpdateMyDetailsHandler(req, res, next, page, serviceC
|
|
|
181
197
|
|
|
182
198
|
|
|
183
199
|
populateFormData(
|
|
184
|
-
|
|
200
|
+
pageTemplateCopy.sections[0].elements[0].params.elements,
|
|
185
201
|
theData,
|
|
186
202
|
validationErrors,
|
|
187
203
|
req.session,
|
|
@@ -194,18 +210,18 @@ export async function govcyUpdateMyDetailsHandler(req, res, next, page, serviceC
|
|
|
194
210
|
|
|
195
211
|
// if there are validation errors, add an error summary
|
|
196
212
|
if (validationErrors?.errorSummary?.length > 0) {
|
|
197
|
-
|
|
213
|
+
pageTemplateCopy.sections[0].elements[0].params.elements.unshift(govcyResources.errorSummary(validationErrors.errorSummary));
|
|
198
214
|
}
|
|
199
215
|
}
|
|
200
216
|
|
|
201
217
|
// Add topElements if provided
|
|
202
218
|
if (Array.isArray(umdConfig.topElements)) {
|
|
203
|
-
|
|
219
|
+
pageTemplateCopy.sections[0].elements[0].params.elements.unshift(...umdConfig.topElements);
|
|
204
220
|
}
|
|
205
221
|
|
|
206
222
|
//if hasBackLink == true add section beforeMain with backlink element
|
|
207
223
|
if (umdConfig?.hasBackLink == true) {
|
|
208
|
-
|
|
224
|
+
pageTemplateCopy.sections.unshift({
|
|
209
225
|
name: "beforeMain",
|
|
210
226
|
elements: [
|
|
211
227
|
{
|
|
@@ -226,7 +242,7 @@ export async function govcyUpdateMyDetailsHandler(req, res, next, page, serviceC
|
|
|
226
242
|
mainLayout: page?.pageData?.mainLayout || "two-third"
|
|
227
243
|
}
|
|
228
244
|
},
|
|
229
|
-
pageTemplate:
|
|
245
|
+
pageTemplate: pageTemplateCopy
|
|
230
246
|
};
|
|
231
247
|
|
|
232
248
|
logger.debug("Processed `govcyUpdateMyDetailsHandler` page data:", req.processedPage, req);
|
|
@@ -372,8 +388,21 @@ export function govcyUpdateMyDetailsPostHandler() {
|
|
|
372
388
|
// Special case for address
|
|
373
389
|
if (element === "address") {
|
|
374
390
|
key = "addressInfo";
|
|
375
|
-
|
|
376
|
-
|
|
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
|
+
}
|
|
377
406
|
|
|
378
407
|
// Check if the key exists
|
|
379
408
|
if (!Object.prototype.hasOwnProperty.call(response.Data || {}, key)) {
|
|
@@ -387,8 +416,18 @@ export function govcyUpdateMyDetailsPostHandler() {
|
|
|
387
416
|
hasData = false;
|
|
388
417
|
userDetails[element] = "";
|
|
389
418
|
} else {
|
|
390
|
-
|
|
391
|
-
|
|
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
|
+
}
|
|
392
431
|
}
|
|
393
432
|
}
|
|
394
433
|
|
|
@@ -567,6 +606,12 @@ function createUmdHasDataPageTemplate(siteId, lang, page, req, userDetails) {
|
|
|
567
606
|
}
|
|
568
607
|
//for each element in the scope array
|
|
569
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
|
+
}
|
|
570
615
|
// add the key and value to the summaryList
|
|
571
616
|
summaryList.params.items.push({
|
|
572
617
|
key: govcyResources.staticResources.text.updateMyDetailsScopes[element],
|
|
@@ -576,7 +621,7 @@ function createUmdHasDataPageTemplate(siteId, lang, page, req, userDetails) {
|
|
|
576
621
|
params: {
|
|
577
622
|
type: "span",
|
|
578
623
|
classes: "govcy-whitespace-pre-line",
|
|
579
|
-
text: govcyResources.getSameMultilingualObject(null,
|
|
624
|
+
text: govcyResources.getSameMultilingualObject(null, value)
|
|
580
625
|
}
|
|
581
626
|
}
|
|
582
627
|
]
|
|
@@ -744,3 +789,4 @@ export function constructUpdateMyDetailsRedirect(req, userId, umdBaseURL, return
|
|
|
744
789
|
// Construct redirect URL
|
|
745
790
|
return `${umdBaseURL}/ReturnUrl/SetReturnUrl?Url=${encodedReturnUrl}&UserProfileId=${encodedUserId}&lang=${lang}`;
|
|
746
791
|
}
|
|
792
|
+
|
|
@@ -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
|
}
|