@defra/forms-engine-plugin 4.0.43 → 4.0.44

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.
Files changed (142) hide show
  1. package/.public/stylesheets/application.min.css +1 -1
  2. package/.public/stylesheets/application.min.css.map +1 -1
  3. package/.server/client/stylesheets/_payment-field.scss +8 -0
  4. package/.server/client/stylesheets/application.scss +2 -0
  5. package/.server/index.js +3 -1
  6. package/.server/index.js.map +1 -1
  7. package/.server/server/constants.d.ts +1 -0
  8. package/.server/server/constants.js +1 -0
  9. package/.server/server/constants.js.map +1 -1
  10. package/.server/server/forms/payment-test.yaml +42 -0
  11. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +14 -0
  12. package/.server/server/plugins/engine/components/FormComponent.d.ts +1 -0
  13. package/.server/server/plugins/engine/components/FormComponent.js +1 -0
  14. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  15. package/.server/server/plugins/engine/components/PaymentField.d.ts +135 -0
  16. package/.server/server/plugins/engine/components/PaymentField.js +228 -0
  17. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -0
  18. package/.server/server/plugins/engine/components/PaymentField.types.d.ts +21 -0
  19. package/.server/server/plugins/engine/components/PaymentField.types.js +2 -0
  20. package/.server/server/plugins/engine/components/PaymentField.types.js.map +1 -0
  21. package/.server/server/plugins/engine/components/UkAddressField.d.ts +1 -1
  22. package/.server/server/plugins/engine/components/UkAddressField.js +3 -1
  23. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  24. package/.server/server/plugins/engine/components/helpers/components.d.ts +1 -1
  25. package/.server/server/plugins/engine/components/helpers/components.js +3 -0
  26. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  27. package/.server/server/plugins/engine/components/index.d.ts +1 -0
  28. package/.server/server/plugins/engine/components/index.js +1 -0
  29. package/.server/server/plugins/engine/components/index.js.map +1 -1
  30. package/.server/server/plugins/engine/helpers.d.ts +1 -0
  31. package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +3 -0
  32. package/.server/server/plugins/engine/models/SummaryViewModel.js +7 -0
  33. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  34. package/.server/server/plugins/engine/outputFormatters/human/v1.js +34 -1
  35. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
  36. package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +22 -0
  37. package/.server/server/plugins/engine/outputFormatters/machine/v2.js +43 -1
  38. package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
  39. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +29 -8
  40. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  41. package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +2 -0
  42. package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +17 -0
  43. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +173 -51
  44. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  45. package/.server/server/plugins/engine/pageControllers/errors.d.ts +31 -0
  46. package/.server/server/plugins/engine/pageControllers/errors.js +59 -2
  47. package/.server/server/plugins/engine/pageControllers/errors.js.map +1 -1
  48. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +27 -0
  49. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +77 -0
  50. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -0
  51. package/.server/server/plugins/engine/plugin.js +4 -1
  52. package/.server/server/plugins/engine/plugin.js.map +1 -1
  53. package/.server/server/plugins/engine/routes/index.js +8 -4
  54. package/.server/server/plugins/engine/routes/index.js.map +1 -1
  55. package/.server/server/plugins/engine/routes/payment-helper.d.ts +14 -0
  56. package/.server/server/plugins/engine/routes/payment-helper.js +41 -0
  57. package/.server/server/plugins/engine/routes/payment-helper.js.map +1 -0
  58. package/.server/server/plugins/engine/routes/payment-helper.test.js +81 -0
  59. package/.server/server/plugins/engine/routes/payment-helper.test.js.map +1 -0
  60. package/.server/server/plugins/engine/routes/payment.d.ts +8 -0
  61. package/.server/server/plugins/engine/routes/payment.js +140 -0
  62. package/.server/server/plugins/engine/routes/payment.js.map +1 -0
  63. package/.server/server/plugins/engine/routes/payment.test.js +187 -0
  64. package/.server/server/plugins/engine/routes/payment.test.js.map +1 -0
  65. package/.server/server/plugins/engine/services/localFormsService.js +6 -0
  66. package/.server/server/plugins/engine/services/localFormsService.js.map +1 -1
  67. package/.server/server/plugins/engine/types/schema.js +7 -0
  68. package/.server/server/plugins/engine/types/schema.js.map +1 -1
  69. package/.server/server/plugins/engine/types.d.ts +19 -1
  70. package/.server/server/plugins/engine/types.js +4 -0
  71. package/.server/server/plugins/engine/types.js.map +1 -1
  72. package/.server/server/plugins/engine/validationHelpers.d.ts +1 -1
  73. package/.server/server/plugins/engine/validationHelpers.js.map +1 -1
  74. package/.server/server/plugins/engine/views/components/paymentfield.html +42 -0
  75. package/.server/server/plugins/engine/views/index.html +9 -1
  76. package/.server/server/plugins/engine/views/partials/form.html +20 -5
  77. package/.server/server/plugins/engine/views/summary.html +17 -1
  78. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  79. package/.server/server/plugins/payment/helper.d.ts +30 -0
  80. package/.server/server/plugins/payment/helper.js +49 -0
  81. package/.server/server/plugins/payment/helper.js.map +1 -0
  82. package/.server/server/plugins/payment/helper.test.js +37 -0
  83. package/.server/server/plugins/payment/helper.test.js.map +1 -0
  84. package/.server/server/plugins/payment/service.d.ts +40 -0
  85. package/.server/server/plugins/payment/service.js +129 -0
  86. package/.server/server/plugins/payment/service.js.map +1 -0
  87. package/.server/server/plugins/payment/service.test.js +162 -0
  88. package/.server/server/plugins/payment/service.test.js.map +1 -0
  89. package/.server/server/plugins/payment/types.d.ts +172 -0
  90. package/.server/server/plugins/payment/types.js +78 -0
  91. package/.server/server/plugins/payment/types.js.map +1 -0
  92. package/.server/server/types.d.ts +2 -0
  93. package/.server/server/types.js.map +1 -1
  94. package/.server/typings/hapi/index.d.js.map +1 -1
  95. package/README.md +12 -9
  96. package/package.json +2 -2
  97. package/src/client/stylesheets/_payment-field.scss +8 -0
  98. package/src/client/stylesheets/application.scss +2 -0
  99. package/src/index.ts +5 -1
  100. package/src/server/constants.js +1 -0
  101. package/src/server/forms/payment-test.yaml +42 -0
  102. package/src/server/forms/register-as-a-unicorn-breeder.yaml +14 -0
  103. package/src/server/plugins/engine/components/FormComponent.ts +1 -0
  104. package/src/server/plugins/engine/components/PaymentField.test.ts +611 -0
  105. package/src/server/plugins/engine/components/PaymentField.ts +367 -0
  106. package/src/server/plugins/engine/components/PaymentField.types.ts +21 -0
  107. package/src/server/plugins/engine/components/UkAddressField.ts +2 -1
  108. package/src/server/plugins/engine/components/helpers/components.ts +5 -0
  109. package/src/server/plugins/engine/components/index.ts +1 -0
  110. package/src/server/plugins/engine/models/SummaryViewModel.ts +8 -0
  111. package/src/server/plugins/engine/outputFormatters/human/v1.payment.test.ts +147 -0
  112. package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +105 -103
  113. package/src/server/plugins/engine/outputFormatters/human/v1.ts +61 -2
  114. package/src/server/plugins/engine/outputFormatters/machine/v2.payment.test.ts +115 -0
  115. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +60 -1
  116. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +32 -6
  117. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +247 -72
  118. package/src/server/plugins/engine/pageControllers/errors.test.ts +13 -1
  119. package/src/server/plugins/engine/pageControllers/errors.ts +79 -4
  120. package/src/server/plugins/engine/pageControllers/helpers/submission.test.ts +299 -0
  121. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +110 -0
  122. package/src/server/plugins/engine/plugin.ts +11 -6
  123. package/src/server/plugins/engine/routes/index.ts +17 -16
  124. package/src/server/plugins/engine/routes/payment-helper.js +39 -0
  125. package/src/server/plugins/engine/routes/payment-helper.test.js +90 -0
  126. package/src/server/plugins/engine/routes/payment.js +151 -0
  127. package/src/server/plugins/engine/routes/payment.test.js +180 -0
  128. package/src/server/plugins/engine/services/localFormsService.js +7 -0
  129. package/src/server/plugins/engine/types/schema.ts +9 -0
  130. package/src/server/plugins/engine/types.ts +24 -1
  131. package/src/server/plugins/engine/validationHelpers.ts +1 -1
  132. package/src/server/plugins/engine/views/components/paymentfield.html +42 -0
  133. package/src/server/plugins/engine/views/index.html +9 -1
  134. package/src/server/plugins/engine/views/partials/form.html +20 -5
  135. package/src/server/plugins/engine/views/summary.html +17 -1
  136. package/src/server/plugins/payment/helper.js +56 -0
  137. package/src/server/plugins/payment/helper.test.js +52 -0
  138. package/src/server/plugins/payment/service.js +171 -0
  139. package/src/server/plugins/payment/service.test.js +205 -0
  140. package/src/server/plugins/payment/types.js +77 -0
  141. package/src/server/types.ts +2 -0
  142. package/src/typings/hapi/index.d.ts +1 -0
@@ -1,5 +1,11 @@
1
1
  import { config } from "../../../../../config/index.js";
2
- import { FileUploadField } from "../../components/index.js";
2
+ import { FileUploadField, PaymentField } from "../../components/index.js";
3
+
4
+ /**
5
+ * Payment data for the machine output format
6
+ * Defined locally to avoid circular dependency with types.ts
7
+ */
8
+
3
9
  const designerUrl = config.get('designerUrl');
4
10
  export function format(context, items, model, _submitResponse, _formStatus) {
5
11
  const now = new Date();
@@ -43,6 +49,15 @@ export function format(context, items, model, _submitResponse, _formStatus) {
43
49
  * userDownloadLink: 'https://forms-designer/file-download/123-456-789'
44
50
  * }
45
51
  * ]
52
+ * },
53
+ * payments: {
54
+ * paymentComponentName: {
55
+ * paymentId: 'abc123',
56
+ * reference: 'REF-123',
57
+ * amount: 10.00,
58
+ * description: 'Application fee',
59
+ * createdAt: '2025-01-23T10:30:00.000Z'
60
+ * }
46
61
  * }
47
62
  * }
48
63
  */
@@ -61,6 +76,11 @@ export function categoriseData(items) {
61
76
  output.repeaters[name] = extractRepeaters(item);
62
77
  } else if (isFileUploadFieldItem(item)) {
63
78
  output.files[name] = extractFileUploads(item);
79
+ } else if (isPaymentFieldItem(item)) {
80
+ const payment = extractPayment(item);
81
+ if (payment) {
82
+ output.payment = payment;
83
+ }
64
84
  } else {
65
85
  output.main[name] = item.field.getFormValueFromState(state);
66
86
  }
@@ -110,4 +130,26 @@ function extractFileUploads(item) {
110
130
  function isFileUploadFieldItem(item) {
111
131
  return item.field instanceof FileUploadField;
112
132
  }
133
+ function isPaymentFieldItem(item) {
134
+ return item.field instanceof PaymentField;
135
+ }
136
+
137
+ /**
138
+ * Returns the "payments" section of the response body
139
+ * @param item - the payment item in the form
140
+ * @returns the payment data
141
+ */
142
+ function extractPayment(item) {
143
+ const paymentState = item.field.getPaymentStateFromState(item.state);
144
+ if (!paymentState) {
145
+ return undefined;
146
+ }
147
+ return {
148
+ paymentId: paymentState.paymentId,
149
+ reference: paymentState.reference,
150
+ amount: paymentState.amount,
151
+ description: paymentState.description,
152
+ createdAt: paymentState.preAuth?.createdAt ?? ''
153
+ };
154
+ }
113
155
  //# sourceMappingURL=v2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"v2.js","names":["config","FileUploadField","designerUrl","get","format","context","items","model","_submitResponse","_formStatus","now","Date","categorisedData","categoriseData","meta","schemaVersion","timestamp","toISOString","definition","def","referenceNumber","data","body","JSON","stringify","output","main","repeaters","files","forEach","item","name","state","extractRepeaters","isFileUploadFieldItem","extractFileUploads","field","getFormValueFromState","subItems","inputRepeaterItem","outputRepeaterItem","repeaterComponent","push","fileUploadState","map","fileState","file","status","form","fileId","fileName","filename","userDownloadLink"],"sources":["../../../../../../src/server/plugins/engine/outputFormatters/machine/v2.ts"],"sourcesContent":["import { type SubmitResponsePayload } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { FileUploadField } from '~/src/server/plugins/engine/components/index.js'\nimport { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport {\n type DetailItem,\n type DetailItemField,\n type DetailItemRepeat\n} from '~/src/server/plugins/engine/models/types.js'\nimport {\n type FileUploadFieldDetailitem,\n type FormAdapterFile,\n type FormContext,\n type RichFormValue\n} from '~/src/server/plugins/engine/types.js'\n\nconst designerUrl = config.get('designerUrl')\n\nexport function format(\n context: FormContext,\n items: DetailItem[],\n model: FormModel,\n _submitResponse: SubmitResponsePayload,\n _formStatus: ReturnType<typeof checkFormStatus>\n) {\n const now = new Date()\n\n const categorisedData = categoriseData(items)\n\n const meta: Record<string, unknown> = {\n schemaVersion: '2',\n timestamp: now.toISOString(),\n definition: model.def,\n referenceNumber: context.referenceNumber\n }\n\n const data = {\n meta,\n data: categorisedData\n }\n\n const body = JSON.stringify(data)\n\n return body\n}\n\n/**\n * Categories the form submission data into the \"main\" body and \"repeaters\".\n *\n * {\n * main: {\n * componentName: 'componentValue',\n * },\n * repeaters: {\n * repeaterName: [\n * {\n * textComponentName: 'componentValue'\n * },\n * {\n * richComponentName: { foo: 'bar', 'baz': true }\n * }\n * ]\n * },\n * files: {\n * fileComponentName: [\n * {\n * fileId: '123-456-789',\n * fileName: 'example.pdf',\n * userDownloadLink: 'https://forms-designer/file-download/123-456-789'\n * }\n * ]\n * }\n * }\n */\nexport function categoriseData(items: DetailItem[]) {\n const output: {\n main: Record<string, RichFormValue>\n repeaters: Record<string, Record<string, RichFormValue>[]>\n files: Record<\n string,\n { fileId: string; fileName: string; userDownloadLink: string }[]\n >\n } = { main: {}, repeaters: {}, files: {} }\n\n items.forEach((item) => {\n const { name, state } = item\n\n if ('subItems' in item) {\n output.repeaters[name] = extractRepeaters(item)\n } else if (isFileUploadFieldItem(item)) {\n output.files[name] = extractFileUploads(item)\n } else {\n output.main[name] = item.field.getFormValueFromState(state)\n }\n })\n\n return output\n}\n\n/**\n * Returns the \"repeaters\" section of the response body\n * @param item - the repeater item\n * @returns the repeater item\n */\nfunction extractRepeaters(item: DetailItemRepeat) {\n const repeaters: Record<string, RichFormValue>[] = []\n\n item.subItems.forEach((inputRepeaterItem) => {\n const outputRepeaterItem: Record<string, RichFormValue> = {}\n\n inputRepeaterItem.forEach((repeaterComponent) => {\n const { field, state } = repeaterComponent\n\n outputRepeaterItem[repeaterComponent.name] =\n field.getFormValueFromState(state)\n })\n\n repeaters.push(outputRepeaterItem)\n })\n\n return repeaters\n}\n\n/**\n * Returns the \"files\" section of the response body\n * @param item - the file upload item in the form\n * @returns the file upload data\n */\nfunction extractFileUploads(\n item: FileUploadFieldDetailitem\n): FormAdapterFile[] {\n const fileUploadState = item.field.getFormValueFromState(item.state) ?? []\n\n return fileUploadState.map((fileState) => {\n const { file } = fileState.status.form\n return {\n fileId: file.fileId,\n fileName: file.filename,\n userDownloadLink: `${designerUrl}/file-download/${file.fileId}`\n }\n })\n}\n\nfunction isFileUploadFieldItem(\n item: DetailItemField\n): item is FileUploadFieldDetailitem {\n return item.field instanceof FileUploadField\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"v2.js","names":["config","FileUploadField","PaymentField","designerUrl","get","format","context","items","model","_submitResponse","_formStatus","now","Date","categorisedData","categoriseData","meta","schemaVersion","timestamp","toISOString","definition","def","referenceNumber","data","body","JSON","stringify","output","main","repeaters","files","forEach","item","name","state","extractRepeaters","isFileUploadFieldItem","extractFileUploads","isPaymentFieldItem","payment","extractPayment","field","getFormValueFromState","subItems","inputRepeaterItem","outputRepeaterItem","repeaterComponent","push","fileUploadState","map","fileState","file","status","form","fileId","fileName","filename","userDownloadLink","paymentState","getPaymentStateFromState","undefined","paymentId","reference","amount","description","createdAt","preAuth"],"sources":["../../../../../../src/server/plugins/engine/outputFormatters/machine/v2.ts"],"sourcesContent":["import { type SubmitResponsePayload } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport {\n FileUploadField,\n PaymentField\n} from '~/src/server/plugins/engine/components/index.js'\nimport { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport {\n type DetailItem,\n type DetailItemField,\n type DetailItemRepeat\n} from '~/src/server/plugins/engine/models/types.js'\nimport {\n type FileUploadFieldDetailitem,\n type FormAdapterFile,\n type FormContext,\n type RichFormValue\n} from '~/src/server/plugins/engine/types.js'\n\n/**\n * Payment data for the machine output format\n * Defined locally to avoid circular dependency with types.ts\n */\ninterface PaymentOutput {\n paymentId: string\n reference: string\n amount: number\n description: string\n createdAt: string\n}\n\nconst designerUrl = config.get('designerUrl')\n\nexport function format(\n context: FormContext,\n items: DetailItem[],\n model: FormModel,\n _submitResponse: SubmitResponsePayload,\n _formStatus: ReturnType<typeof checkFormStatus>\n) {\n const now = new Date()\n\n const categorisedData = categoriseData(items)\n\n const meta: Record<string, unknown> = {\n schemaVersion: '2',\n timestamp: now.toISOString(),\n definition: model.def,\n referenceNumber: context.referenceNumber\n }\n\n const data = {\n meta,\n data: categorisedData\n }\n\n const body = JSON.stringify(data)\n\n return body\n}\n\n/**\n * Categories the form submission data into the \"main\" body and \"repeaters\".\n *\n * {\n * main: {\n * componentName: 'componentValue',\n * },\n * repeaters: {\n * repeaterName: [\n * {\n * textComponentName: 'componentValue'\n * },\n * {\n * richComponentName: { foo: 'bar', 'baz': true }\n * }\n * ]\n * },\n * files: {\n * fileComponentName: [\n * {\n * fileId: '123-456-789',\n * fileName: 'example.pdf',\n * userDownloadLink: 'https://forms-designer/file-download/123-456-789'\n * }\n * ]\n * },\n * payments: {\n * paymentComponentName: {\n * paymentId: 'abc123',\n * reference: 'REF-123',\n * amount: 10.00,\n * description: 'Application fee',\n * createdAt: '2025-01-23T10:30:00.000Z'\n * }\n * }\n * }\n */\nexport function categoriseData(items: DetailItem[]) {\n const output: {\n main: Record<string, RichFormValue>\n repeaters: Record<string, Record<string, RichFormValue>[]>\n files: Record<\n string,\n { fileId: string; fileName: string; userDownloadLink: string }[]\n >\n payment?: PaymentOutput\n } = { main: {}, repeaters: {}, files: {} }\n\n items.forEach((item) => {\n const { name, state } = item\n\n if ('subItems' in item) {\n output.repeaters[name] = extractRepeaters(item)\n } else if (isFileUploadFieldItem(item)) {\n output.files[name] = extractFileUploads(item)\n } else if (isPaymentFieldItem(item)) {\n const payment = extractPayment(item)\n if (payment) {\n output.payment = payment\n }\n } else {\n output.main[name] = item.field.getFormValueFromState(state)\n }\n })\n\n return output\n}\n\n/**\n * Returns the \"repeaters\" section of the response body\n * @param item - the repeater item\n * @returns the repeater item\n */\nfunction extractRepeaters(item: DetailItemRepeat) {\n const repeaters: Record<string, RichFormValue>[] = []\n\n item.subItems.forEach((inputRepeaterItem) => {\n const outputRepeaterItem: Record<string, RichFormValue> = {}\n\n inputRepeaterItem.forEach((repeaterComponent) => {\n const { field, state } = repeaterComponent\n\n outputRepeaterItem[repeaterComponent.name] =\n field.getFormValueFromState(state)\n })\n\n repeaters.push(outputRepeaterItem)\n })\n\n return repeaters\n}\n\n/**\n * Returns the \"files\" section of the response body\n * @param item - the file upload item in the form\n * @returns the file upload data\n */\nfunction extractFileUploads(\n item: FileUploadFieldDetailitem\n): FormAdapterFile[] {\n const fileUploadState = item.field.getFormValueFromState(item.state) ?? []\n\n return fileUploadState.map((fileState) => {\n const { file } = fileState.status.form\n return {\n fileId: file.fileId,\n fileName: file.filename,\n userDownloadLink: `${designerUrl}/file-download/${file.fileId}`\n }\n })\n}\n\nfunction isFileUploadFieldItem(\n item: DetailItemField\n): item is FileUploadFieldDetailitem {\n return item.field instanceof FileUploadField\n}\n\nfunction isPaymentFieldItem(item: DetailItemField): item is DetailItemField & {\n field: PaymentField\n} {\n return item.field instanceof PaymentField\n}\n\n/**\n * Returns the \"payments\" section of the response body\n * @param item - the payment item in the form\n * @returns the payment data\n */\nfunction extractPayment(\n item: DetailItemField & { field: PaymentField }\n): PaymentOutput | undefined {\n const paymentState = item.field.getPaymentStateFromState(item.state)\n\n if (!paymentState) {\n return undefined\n }\n\n return {\n paymentId: paymentState.paymentId,\n reference: paymentState.reference,\n amount: paymentState.amount,\n description: paymentState.description,\n createdAt: paymentState.preAuth?.createdAt ?? ''\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,13 +1,13 @@
1
1
  import { ComponentType, ControllerType, Engine, hasComponents, hasNext, hasRepeater } from '@defra/forms-model';
2
2
  import Boom from '@hapi/boom';
3
- import { COMPONENT_STATE_ERROR, EXTERNAL_STATE_APPENDAGE, EXTERNAL_STATE_PAYLOAD } from "../../../constants.js";
3
+ import { COMPONENT_STATE_ERROR, EXTERNAL_STATE_APPENDAGE, EXTERNAL_STATE_PAYLOAD, PAYMENT_EXPIRED_NOTIFICATION } from "../../../constants.js";
4
4
  import { ComponentCollection } from "../components/ComponentCollection.js";
5
5
  import { optionalText } from "../components/constants.js";
6
- import { getCacheService, getErrors, getSaveAndExitHelpers, normalisePath, proceed } from "../helpers.js";
6
+ import { checkFormStatus, getCacheService, getErrors, getSaveAndExitHelpers, normalisePath, proceed } from "../helpers.js";
7
7
  import { PageController } from "./PageController.js";
8
8
  import { clearNotYetValidatedState, prefillStateFromQueryParameters } from "./helpers/state.js";
9
9
  import { getComponentsByType } from "../validationHelpers.js";
10
- import { FormAction } from "../../../routes/types.js";
10
+ import { FormAction, FormStatus } from "../../../routes/types.js";
11
11
  import { actionSchema, crumbSchema, paramsSchema } from "../../../schemas/index.js";
12
12
  import { merge } from "../../../services/cacheService.js";
13
13
  export class QuestionPageController extends PageController {
@@ -132,6 +132,15 @@ export class QuestionPageController extends PageController {
132
132
  }
133
133
  }
134
134
  }
135
+ const hasIncompletePayment = components.some(({
136
+ model
137
+ }) => {
138
+ if ('paymentState' in model) {
139
+ const paymentState = model.paymentState;
140
+ return !paymentState?.preAuth?.status;
141
+ }
142
+ return false;
143
+ });
135
144
  return {
136
145
  ...viewModel,
137
146
  backLink: this.getBackLink(request, context),
@@ -139,7 +148,8 @@ export class QuestionPageController extends PageController {
139
148
  showTitle,
140
149
  components,
141
150
  errors,
142
- allowSaveAndExit: this.shouldShowSaveAndExit(request.server)
151
+ allowSaveAndExit: this.shouldShowSaveAndExit(request.server),
152
+ showSubmitButton: !hasIncompletePayment
143
153
  };
144
154
  }
145
155
  getRelevantPath(request, context) {
@@ -336,6 +346,8 @@ export class QuestionPageController extends PageController {
336
346
  const flashedError = request.yar.flash(COMPONENT_STATE_ERROR);
337
347
  const flashedErrors = !Array.isArray(flashedError) ? [flashedError] : [];
338
348
  viewModel.errors = (viewModel.errors ?? []).concat(flashedErrors);
349
+ const paymentExpiredFlash = request.yar.flash(PAYMENT_EXPIRED_NOTIFICATION);
350
+ viewModel.showPaymentExpiredNotification = !Array.isArray(paymentExpiredFlash);
339
351
 
340
352
  /**
341
353
  * Content components can be hidden based on a condition. If the condition evaluates to true, it is safe to be kept, otherwise discard it
@@ -432,7 +444,7 @@ export class QuestionPageController extends PageController {
432
444
  } = context;
433
445
  const action = request.payload.action;
434
446
  if (action?.startsWith(FormAction.External)) {
435
- return this.dispatchExternal(request, h, context);
447
+ return await this.dispatchExternal(request, h, context);
436
448
  }
437
449
 
438
450
  /**
@@ -460,7 +472,7 @@ export class QuestionPageController extends PageController {
460
472
  return this.proceed(request, h, this.getNextPath(context));
461
473
  };
462
474
  }
463
- dispatchExternal(request, h, context) {
475
+ async dispatchExternal(request, h, context) {
464
476
  const {
465
477
  externalComponents
466
478
  } = getComponentsByType();
@@ -493,11 +505,20 @@ export class QuestionPageController extends PageController {
493
505
 
494
506
  // Clear any previous state appendage
495
507
  request.yar.clear(EXTERNAL_STATE_APPENDAGE);
496
- return selectedComponent.dispatcher(request, h, {
508
+
509
+ // Determine if this is a live form (not preview/draft)
510
+ const {
511
+ state,
512
+ isPreview
513
+ } = checkFormStatus(request.params);
514
+ const isLive = state === FormStatus.Live;
515
+ return await selectedComponent.dispatcher(request, h, {
497
516
  component,
498
517
  controller: this,
499
518
  sourceUrl: request.url.toString(),
500
- actionArgs: args
519
+ actionArgs: args,
520
+ isLive,
521
+ isPreview
501
522
  });
502
523
  }
503
524
  proceed(request, h, nextPath) {
@@ -1 +1 @@
1
- {"version":3,"file":"QuestionPageController.js","names":["ComponentType","ControllerType","Engine","hasComponents","hasNext","hasRepeater","Boom","COMPONENT_STATE_ERROR","EXTERNAL_STATE_APPENDAGE","EXTERNAL_STATE_PAYLOAD","ComponentCollection","optionalText","getCacheService","getErrors","getSaveAndExitHelpers","normalisePath","proceed","PageController","clearNotYetValidatedState","prefillStateFromQueryParameters","getComponentsByType","FormAction","actionSchema","crumbSchema","paramsSchema","merge","QuestionPageController","collection","errorSummaryTitle","allowSaveAndExit","constructor","model","pageDef","components","page","formSchema","keys","crumb","action","next","def","filter","path","linkPath","pages","some","pagePath","allowContinue","engine","V2","controller","Terminal","length","getItemId","request","itemId","getFormParams","params","getViewModel","context","viewModel","query","payload","errors","pageTitle","showTitle","formComponents","isFormComponent","fieldset","label","isPageHeading","labelOrLegend","legend","size","classes","isOptional","fields","at","options","required","text","backLink","getBackLink","shouldShowSaveAndExit","server","getRelevantPath","paths","startPath","getStartPath","relevantPath","getNextPath","evaluationState","summaryPath","getSummaryPath","statusPath","getStatusPath","defaultPath","undefined","pageIndex","indexOf","nextPage","slice","find","condition","conditionResult","fn","nextLink","link","conditions","getFormDataFromState","state","result","validate","abortEarly","stripUnknown","value","getStateFromValidForm","details","getState","cacheService","setState","mergeState","update","updated","filterConditionalComponents","filtered","component","content","type","Details","map","evaluatedComponent","Array","isArray","item","items","makeGetRouteHandler","h","viewName","redirect","url","origin","pathname","getViewErrors","flashedError","yar","flash","flashedErrors","concat","hasMissingNotificationEmail","view","isForceAccess","formsService","services","getFormMetadata","includes","notificationEmail","slug","returnUrl","href","backPath","endsWith","getHref","makePostRouteHandler","startsWith","External","dispatchExternal","SaveAndExit","handleSaveAndExit","externalComponents","externalActionsWithArgs","split","externalActionArgs","arg","args","Object","fromEntries","componentName","componentDefMap","get","componentType","internal","selectedComponent","stashedPayload","clear","dispatcher","sourceUrl","toString","actionArgs","nextPath","nextUrl","saveAndExit","getRouteOptions","ext","onPostHandler","method","_request","continue","postRouteOptions","parse","maxBytes","Number","MAX_SAFE_INTEGER","failAction"],"sources":["../../../../../src/server/plugins/engine/pageControllers/QuestionPageController.ts"],"sourcesContent":["import {\n ComponentType,\n ControllerType,\n Engine,\n hasComponents,\n hasNext,\n hasRepeater,\n type Link,\n type Page\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type RouteOptions } from '@hapi/hapi'\nimport { type ValidationErrorItem } from 'joi'\n\nimport {\n COMPONENT_STATE_ERROR,\n EXTERNAL_STATE_APPENDAGE,\n EXTERNAL_STATE_PAYLOAD\n} from '~/src/server/constants.js'\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport { optionalText } from '~/src/server/plugins/engine/components/constants.js'\nimport { type BackLink } from '~/src/server/plugins/engine/components/types.js'\nimport {\n getCacheService,\n getErrors,\n getSaveAndExitHelpers,\n normalisePath,\n proceed\n} from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport {\n clearNotYetValidatedState,\n prefillStateFromQueryParameters\n} from '~/src/server/plugins/engine/pageControllers/helpers/state.js'\nimport {\n type AnyFormRequest,\n type FormContext,\n type FormContextRequest,\n type FormPageViewModel,\n type FormPayload,\n type FormPayloadParams,\n type FormState,\n type FormStateValue,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport { getComponentsByType } from '~/src/server/plugins/engine/validationHelpers.js'\nimport {\n FormAction,\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormRequestRefs,\n type FormResponseToolkit\n} from '~/src/server/routes/types.js'\nimport {\n actionSchema,\n crumbSchema,\n paramsSchema\n} from '~/src/server/schemas/index.js'\nimport { merge } from '~/src/server/services/cacheService.js'\n\nexport class QuestionPageController extends PageController {\n collection: ComponentCollection\n errorSummaryTitle = 'There is a problem'\n allowSaveAndExit = true\n\n constructor(model: FormModel, pageDef: Page) {\n super(model, pageDef)\n\n // Components collection\n this.collection = new ComponentCollection(\n hasComponents(pageDef) ? pageDef.components : [],\n { model, page: this }\n )\n\n this.collection.formSchema = this.collection.formSchema.keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n }\n\n get next(): Link[] {\n const { def, pageDef } = this\n\n if (!hasNext(pageDef)) {\n return []\n }\n\n // Remove stale links\n return pageDef.next.filter(({ path }) => {\n const linkPath = normalisePath(path)\n\n return def.pages.some((page) => {\n const pagePath = normalisePath(page.path)\n return pagePath === linkPath\n })\n })\n }\n\n get allowContinue(): boolean {\n if (this.model.engine === Engine.V2) {\n return this.pageDef.controller !== ControllerType.Terminal\n }\n\n return this.next.length > 0\n }\n\n getItemId(request?: FormContextRequest) {\n const { itemId } = this.getFormParams(request)\n return itemId ?? request?.params.itemId\n }\n\n /**\n * Used for mapping form payloads and errors to govuk-frontend's template api, so a page can be rendered\n * @param request - the hapi request\n * @param context - the form context\n */\n getViewModel(\n request: FormContextRequest,\n context: FormContext\n ): FormPageViewModel {\n const { collection, viewModel } = this\n const { query } = request\n const { payload, errors } = context\n\n let { pageTitle, showTitle } = viewModel\n\n const components = collection.getViewModel(payload, errors, query)\n const formComponents = components.filter(\n ({ isFormComponent }) => isFormComponent\n )\n\n // Single form component? Hide title and customise label or legend instead\n if (formComponents.length === 1) {\n const { model } = formComponents[0]\n const { fieldset, label } = model\n\n // Set as page heading when not following other content\n const isPageHeading = formComponents[0] === components[0]\n\n // Check for legend or label\n const labelOrLegend = fieldset?.legend ?? label\n\n // Use legend or label as page heading\n if (labelOrLegend) {\n const size = isPageHeading ? 'l' : 'm'\n\n labelOrLegend.classes =\n labelOrLegend === label\n ? `govuk-label--${size}`\n : `govuk-fieldset__legend--${size}`\n\n if (isPageHeading) {\n labelOrLegend.isPageHeading = isPageHeading\n\n // Check for optional in label\n const isOptional =\n this.collection.fields.at(0)?.options.required === false\n\n if (pageTitle) {\n labelOrLegend.text = isOptional\n ? `${pageTitle}${optionalText}`\n : pageTitle\n }\n\n pageTitle = pageTitle || labelOrLegend.text\n }\n }\n\n showTitle = !isPageHeading\n } else if (formComponents.length > 1) {\n // When there is more than one form component,\n // adjust the label/legends to give equal prominence\n for (const { model } of formComponents) {\n if (model.fieldset?.legend) {\n model.fieldset.legend.classes = 'govuk-fieldset__legend--m'\n }\n if (model.label) {\n model.label.classes = 'govuk-label--m'\n }\n }\n }\n\n return {\n ...viewModel,\n backLink: this.getBackLink(request, context),\n context,\n showTitle,\n components,\n errors,\n allowSaveAndExit: this.shouldShowSaveAndExit(request.server)\n }\n }\n\n getRelevantPath(request: AnyFormRequest, context: FormContext) {\n const { paths } = context\n\n const startPath = this.getStartPath()\n const relevantPath = paths.at(-1) ?? startPath\n\n return !paths.length\n ? startPath // First possible path\n : relevantPath // Last possible path\n }\n\n /**\n * Apply conditions to evaluation state to determine next page path\n */\n getNextPath(context: FormContext) {\n const { model, next, path } = this\n const { evaluationState } = context\n\n const summaryPath = this.getSummaryPath()\n const statusPath = this.getStatusPath()\n\n // Walk from summary page (no next links) to status page\n let defaultPath = path === summaryPath ? statusPath : undefined\n\n if (model.engine === Engine.V2) {\n if (this.pageDef.controller !== ControllerType.Terminal) {\n const { pages } = this.model\n const pageIndex = pages.indexOf(this)\n\n // The \"next\" page is the first found after the current which is\n // either unconditional or has a condition that evaluates to \"true\"\n const nextPage = pages.slice(pageIndex + 1).find((page) => {\n const { condition } = page\n\n if (condition) {\n const conditionResult = condition.fn(evaluationState)\n\n if (!conditionResult) {\n return false\n }\n }\n\n return true\n })\n\n return nextPage?.path ?? defaultPath\n } else {\n return defaultPath\n }\n }\n\n const nextLink = next.find((link) => {\n const { condition } = link\n\n if (condition) {\n return model.conditions[condition]?.fn(evaluationState) ?? false\n }\n\n defaultPath = link.path\n return false\n })\n\n return nextLink?.path ?? defaultPath\n }\n\n /**\n * Gets the form payload (from state) for this page only\n */\n getFormDataFromState(\n request: FormContextRequest | undefined,\n state: FormSubmissionState\n ): FormPayload {\n const { collection } = this\n\n // Form params from request\n const params = this.getFormParams(request)\n\n // Form payload from state\n const payload = collection.getFormDataFromState(state)\n\n return {\n ...params,\n ...payload\n }\n }\n\n /**\n * Gets form params (from payload) for this page only\n */\n getFormParams(request?: FormContextRequest): FormPayloadParams {\n const { payload } = request ?? {}\n\n const result = paramsSchema.validate(payload, {\n abortEarly: false,\n stripUnknown: true\n })\n\n return result.value as FormPayloadParams\n }\n\n getStateFromValidForm(\n request: FormContextRequest,\n state: FormSubmissionState,\n payload: FormPayload\n ): FormState {\n return this.collection.getStateFromValidForm(payload)\n }\n\n getErrors(details?: ValidationErrorItem[]) {\n return getErrors(details)\n }\n\n async getState(request: AnyFormRequest) {\n const { query } = request\n\n // Skip get for preview URL direct access\n if ('force' in query) {\n return {}\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.getState(request)\n }\n\n async setState(request: AnyFormRequest, state: FormSubmissionState) {\n const { query } = request\n\n // Skip set for preview URL direct access\n if ('force' in query) {\n return state\n }\n\n const cacheService = getCacheService(request.server)\n\n // Clear any 'not yet validated' state before saving to cache\n return cacheService.setState(request, clearNotYetValidatedState(state))\n }\n\n async mergeState(\n request: AnyFormRequest,\n state: FormSubmissionState,\n update: object\n ) {\n const { query } = request\n\n // Merge state before set\n const updated = merge(state, update)\n\n // Skip set for preview URL direct access\n if ('force' in query) {\n return updated\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.setState(request, updated)\n }\n\n filterConditionalComponents(\n viewModel: FormPageViewModel,\n model: FormModel,\n evaluationState: Partial<Record<string, FormStateValue>>\n ) {\n // Filter our components based on their conditions using our evaluated state\n let filtered = viewModel.components.filter((component) => {\n if (\n (!!component.model.content ||\n component.type === ComponentType.Details) &&\n component.model.condition\n ) {\n const condition = model.conditions[component.model.condition]\n return condition?.fn(evaluationState)\n }\n return true\n })\n\n /**\n * For conditional reveal components (which we no longer support until GDS resolves the related accessibility issues {@link https://github.com/alphagov/govuk-frontend/issues/1991}\n */\n filtered = filtered.map((component) => {\n const evaluatedComponent = component\n const content = evaluatedComponent.model.content\n if (Array.isArray(content)) {\n evaluatedComponent.model.content = content.filter((item) =>\n item.condition\n ? model.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n }\n // apply condition to items for radios, checkboxes etc\n const items = evaluatedComponent.model.items\n\n if (Array.isArray(items)) {\n evaluatedComponent.model.items = items.filter((item) =>\n item.condition\n ? model.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n }\n\n return evaluatedComponent\n })\n\n return filtered\n }\n\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { collection, model, viewName } = this\n const { evaluationState } = context\n\n // Copy any URL params into the form state (if not already done so)\n if (await prefillStateFromQueryParameters(request, this)) {\n // Forward to same page without query string\n return h.redirect(`${request.url.origin}${request.url.pathname}`)\n }\n\n const viewModel = this.getViewModel(request, context)\n viewModel.errors = collection.getViewErrors(viewModel.errors)\n\n const flashedError = request.yar.flash(COMPONENT_STATE_ERROR)\n const flashedErrors = !Array.isArray(flashedError) ? [flashedError] : []\n\n viewModel.errors = (viewModel.errors ?? []).concat(flashedErrors)\n\n /**\n * Content components can be hidden based on a condition. If the condition evaluates to true, it is safe to be kept, otherwise discard it\n */\n\n // Filter our components based on their conditions using our evaluated state\n viewModel.components = this.filterConditionalComponents(\n viewModel,\n model,\n evaluationState\n )\n\n viewModel.hasMissingNotificationEmail =\n await this.hasMissingNotificationEmail(request, context)\n\n return h.view(viewName, viewModel)\n }\n }\n\n async hasMissingNotificationEmail(\n request: FormRequest,\n context: FormContext\n ) {\n const { path } = this\n const { params } = request\n const { isForceAccess } = context\n\n const startPath = this.getStartPath()\n const summaryPath = this.getSummaryPath()\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n // Warn the user if the form has no notification email set only on start page and summary page\n if ([startPath, summaryPath].includes(path) && !isForceAccess) {\n const { notificationEmail } = await getFormMetadata(params.slug)\n return !notificationEmail\n }\n\n return false\n }\n\n /**\n * Get the back link for a given progress.\n */\n protected getBackLink(\n request: FormContextRequest,\n context: FormContext\n ): BackLink | undefined {\n const { pageDef } = this\n const { path, query } = request\n const { returnUrl } = query\n const { paths } = context\n\n const itemId = this.getItemId(request)\n\n // Check answers back link\n if (returnUrl) {\n return {\n text:\n hasRepeater(pageDef) && itemId\n ? 'Go back to add another'\n : 'Go back to check answers',\n href: returnUrl\n }\n }\n\n // Item delete pages etc\n const backPath =\n itemId && !path.endsWith(itemId)\n ? paths.at(-1) // Back to main page\n : paths.at(-2) // Back to previous page\n\n // No back link\n if (!backPath) {\n return\n }\n\n // Default back link\n return {\n text: 'Back',\n href: this.getHref(backPath)\n }\n }\n\n makePostRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { collection, viewName, model } = this\n const { isForceAccess, state, evaluationState } = context\n const action = request.payload.action\n\n if (action?.startsWith(FormAction.External)) {\n return this.dispatchExternal(request, h, context)\n }\n\n /**\n * If there are any errors, render the page with the parsed errors\n * @todo Refactor to match POST REDIRECT GET pattern\n */\n if (context.errors || isForceAccess) {\n const viewModel = this.getViewModel(request, context)\n viewModel.errors = collection.getViewErrors(viewModel.errors)\n\n // Filter our components based on their conditions using our evaluated state\n viewModel.components = this.filterConditionalComponents(\n viewModel,\n model,\n evaluationState\n )\n\n return h.view(viewName, viewModel)\n }\n\n // Save state\n await this.setState(request, state)\n\n // Check if this is a save-and-exit action\n if (action === FormAction.SaveAndExit) {\n return this.handleSaveAndExit(request, context, h)\n }\n\n // Proceed to the next page\n return this.proceed(request, h, this.getNextPath(context))\n }\n }\n\n private dispatchExternal(\n request: FormRequestPayload,\n h: FormResponseToolkit,\n context: FormContext\n ) {\n const { externalComponents } = getComponentsByType()\n const action = request.payload.action ?? ''\n\n // Find the external action and arguments\n // `external-{componentName}--{argname1}:{argvalue1}--{argname2}:{argvalue2}`\n // E.g. external-abcdef--amount:10--step:manual\n const externalActionsWithArgs = action\n .slice(`${FormAction.External}-`.length)\n .split('--')\n\n const externalActionArgs = externalActionsWithArgs\n .slice(1)\n .map((arg) => arg.split(':'))\n\n const args = Object.fromEntries(externalActionArgs) as Record<\n string,\n string\n >\n\n const componentName = externalActionsWithArgs[0]\n const component = this.model.componentDefMap.get(componentName)\n const componentType = component?.type\n\n if (!componentType) {\n throw Boom.internal(\n `External component of type ${componentType} not found`\n )\n }\n\n const selectedComponent = externalComponents.get(componentType)\n\n if (!selectedComponent) {\n throw Boom.internal(`External component ${componentName} not found`)\n }\n\n // Stash payload without crumb and action\n const stashedPayload = {\n ...context.payload,\n crumb: undefined,\n action: undefined\n }\n request.yar.flash(EXTERNAL_STATE_PAYLOAD, stashedPayload, true)\n\n // Clear any previous state appendage\n request.yar.clear(EXTERNAL_STATE_APPENDAGE)\n\n return selectedComponent.dispatcher(request, h, {\n component,\n controller: this,\n sourceUrl: request.url.toString(),\n actionArgs: args\n })\n }\n\n proceed(\n request: FormContextRequest,\n h: FormResponseToolkit,\n nextPath?: string\n ) {\n const nextUrl = nextPath\n ? this.getHref(nextPath) // Redirect to next page\n : this.href // Redirect to current page (refresh)\n\n return proceed(request, h, nextUrl)\n }\n\n /**\n * Handle save-and-exit action\n */\n handleSaveAndExit(\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) {\n const saveAndExit = getSaveAndExitHelpers(request.server)\n\n if (!saveAndExit) {\n throw Boom.internal('Server misconfigured for save and exit')\n }\n\n return saveAndExit(request, h, context)\n }\n\n /**\n * {@link https://hapi.dev/api/?v=20.1.2#route-options}\n */\n get getRouteOptions(): RouteOptions<FormRequestRefs> {\n return {\n ext: {\n onPostHandler: {\n method(_request, h) {\n return h.continue\n }\n }\n }\n }\n }\n\n /**\n * {@link https://hapi.dev/api/?v=20.1.2#route-options}\n */\n get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {\n return {\n payload: {\n parse: true,\n maxBytes: Number.MAX_SAFE_INTEGER,\n failAction: 'ignore'\n },\n ext: {\n onPostHandler: {\n method(_request, h) {\n return h.continue\n }\n }\n }\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"QuestionPageController.js","names":["ComponentType","ControllerType","Engine","hasComponents","hasNext","hasRepeater","Boom","COMPONENT_STATE_ERROR","EXTERNAL_STATE_APPENDAGE","EXTERNAL_STATE_PAYLOAD","PAYMENT_EXPIRED_NOTIFICATION","ComponentCollection","optionalText","checkFormStatus","getCacheService","getErrors","getSaveAndExitHelpers","normalisePath","proceed","PageController","clearNotYetValidatedState","prefillStateFromQueryParameters","getComponentsByType","FormAction","FormStatus","actionSchema","crumbSchema","paramsSchema","merge","QuestionPageController","collection","errorSummaryTitle","allowSaveAndExit","constructor","model","pageDef","components","page","formSchema","keys","crumb","action","next","def","filter","path","linkPath","pages","some","pagePath","allowContinue","engine","V2","controller","Terminal","length","getItemId","request","itemId","getFormParams","params","getViewModel","context","viewModel","query","payload","errors","pageTitle","showTitle","formComponents","isFormComponent","fieldset","label","isPageHeading","labelOrLegend","legend","size","classes","isOptional","fields","at","options","required","text","hasIncompletePayment","paymentState","preAuth","status","backLink","getBackLink","shouldShowSaveAndExit","server","showSubmitButton","getRelevantPath","paths","startPath","getStartPath","relevantPath","getNextPath","evaluationState","summaryPath","getSummaryPath","statusPath","getStatusPath","defaultPath","undefined","pageIndex","indexOf","nextPage","slice","find","condition","conditionResult","fn","nextLink","link","conditions","getFormDataFromState","state","result","validate","abortEarly","stripUnknown","value","getStateFromValidForm","details","getState","cacheService","setState","mergeState","update","updated","filterConditionalComponents","filtered","component","content","type","Details","map","evaluatedComponent","Array","isArray","item","items","makeGetRouteHandler","h","viewName","redirect","url","origin","pathname","getViewErrors","flashedError","yar","flash","flashedErrors","concat","paymentExpiredFlash","showPaymentExpiredNotification","hasMissingNotificationEmail","view","isForceAccess","formsService","services","getFormMetadata","includes","notificationEmail","slug","returnUrl","href","backPath","endsWith","getHref","makePostRouteHandler","startsWith","External","dispatchExternal","SaveAndExit","handleSaveAndExit","externalComponents","externalActionsWithArgs","split","externalActionArgs","arg","args","Object","fromEntries","componentName","componentDefMap","get","componentType","internal","selectedComponent","stashedPayload","clear","isPreview","isLive","Live","dispatcher","sourceUrl","toString","actionArgs","nextPath","nextUrl","saveAndExit","getRouteOptions","ext","onPostHandler","method","_request","continue","postRouteOptions","parse","maxBytes","Number","MAX_SAFE_INTEGER","failAction"],"sources":["../../../../../src/server/plugins/engine/pageControllers/QuestionPageController.ts"],"sourcesContent":["import {\n ComponentType,\n ControllerType,\n Engine,\n hasComponents,\n hasNext,\n hasRepeater,\n type Link,\n type Page\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type RouteOptions } from '@hapi/hapi'\nimport { type ValidationErrorItem } from 'joi'\n\nimport {\n COMPONENT_STATE_ERROR,\n EXTERNAL_STATE_APPENDAGE,\n EXTERNAL_STATE_PAYLOAD,\n PAYMENT_EXPIRED_NOTIFICATION\n} from '~/src/server/constants.js'\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport { optionalText } from '~/src/server/plugins/engine/components/constants.js'\nimport { type BackLink } from '~/src/server/plugins/engine/components/types.js'\nimport {\n checkFormStatus,\n getCacheService,\n getErrors,\n getSaveAndExitHelpers,\n normalisePath,\n proceed\n} from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport {\n clearNotYetValidatedState,\n prefillStateFromQueryParameters\n} from '~/src/server/plugins/engine/pageControllers/helpers/state.js'\nimport {\n type AnyFormRequest,\n type FormContext,\n type FormContextRequest,\n type FormPageViewModel,\n type FormPayload,\n type FormPayloadParams,\n type FormState,\n type FormStateValue,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport { getComponentsByType } from '~/src/server/plugins/engine/validationHelpers.js'\nimport {\n FormAction,\n FormStatus,\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormRequestRefs,\n type FormResponseToolkit\n} from '~/src/server/routes/types.js'\nimport {\n actionSchema,\n crumbSchema,\n paramsSchema\n} from '~/src/server/schemas/index.js'\nimport { merge } from '~/src/server/services/cacheService.js'\n\nexport class QuestionPageController extends PageController {\n collection: ComponentCollection\n errorSummaryTitle = 'There is a problem'\n allowSaveAndExit = true\n\n constructor(model: FormModel, pageDef: Page) {\n super(model, pageDef)\n\n // Components collection\n this.collection = new ComponentCollection(\n hasComponents(pageDef) ? pageDef.components : [],\n { model, page: this }\n )\n\n this.collection.formSchema = this.collection.formSchema.keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n }\n\n get next(): Link[] {\n const { def, pageDef } = this\n\n if (!hasNext(pageDef)) {\n return []\n }\n\n // Remove stale links\n return pageDef.next.filter(({ path }) => {\n const linkPath = normalisePath(path)\n\n return def.pages.some((page) => {\n const pagePath = normalisePath(page.path)\n return pagePath === linkPath\n })\n })\n }\n\n get allowContinue(): boolean {\n if (this.model.engine === Engine.V2) {\n return this.pageDef.controller !== ControllerType.Terminal\n }\n\n return this.next.length > 0\n }\n\n getItemId(request?: FormContextRequest) {\n const { itemId } = this.getFormParams(request)\n return itemId ?? request?.params.itemId\n }\n\n /**\n * Used for mapping form payloads and errors to govuk-frontend's template api, so a page can be rendered\n * @param request - the hapi request\n * @param context - the form context\n */\n getViewModel(\n request: FormContextRequest,\n context: FormContext\n ): FormPageViewModel {\n const { collection, viewModel } = this\n const { query } = request\n const { payload, errors } = context\n\n let { pageTitle, showTitle } = viewModel\n\n const components = collection.getViewModel(payload, errors, query)\n const formComponents = components.filter(\n ({ isFormComponent }) => isFormComponent\n )\n\n // Single form component? Hide title and customise label or legend instead\n if (formComponents.length === 1) {\n const { model } = formComponents[0]\n const { fieldset, label } = model\n\n // Set as page heading when not following other content\n const isPageHeading = formComponents[0] === components[0]\n\n // Check for legend or label\n const labelOrLegend = fieldset?.legend ?? label\n\n // Use legend or label as page heading\n if (labelOrLegend) {\n const size = isPageHeading ? 'l' : 'm'\n\n labelOrLegend.classes =\n labelOrLegend === label\n ? `govuk-label--${size}`\n : `govuk-fieldset__legend--${size}`\n\n if (isPageHeading) {\n labelOrLegend.isPageHeading = isPageHeading\n\n // Check for optional in label\n const isOptional =\n this.collection.fields.at(0)?.options.required === false\n\n if (pageTitle) {\n labelOrLegend.text = isOptional\n ? `${pageTitle}${optionalText}`\n : pageTitle\n }\n\n pageTitle = pageTitle || labelOrLegend.text\n }\n }\n\n showTitle = !isPageHeading\n } else if (formComponents.length > 1) {\n // When there is more than one form component,\n // adjust the label/legends to give equal prominence\n for (const { model } of formComponents) {\n if (model.fieldset?.legend) {\n model.fieldset.legend.classes = 'govuk-fieldset__legend--m'\n }\n if (model.label) {\n model.label.classes = 'govuk-label--m'\n }\n }\n }\n\n const hasIncompletePayment = components.some(({ model }) => {\n if ('paymentState' in model) {\n const paymentState = model.paymentState as\n | { preAuth?: { status?: string } }\n | undefined\n return !paymentState?.preAuth?.status\n }\n return false\n })\n\n return {\n ...viewModel,\n backLink: this.getBackLink(request, context),\n context,\n showTitle,\n components,\n errors,\n allowSaveAndExit: this.shouldShowSaveAndExit(request.server),\n showSubmitButton: !hasIncompletePayment\n }\n }\n\n getRelevantPath(request: AnyFormRequest, context: FormContext) {\n const { paths } = context\n\n const startPath = this.getStartPath()\n const relevantPath = paths.at(-1) ?? startPath\n\n return !paths.length\n ? startPath // First possible path\n : relevantPath // Last possible path\n }\n\n /**\n * Apply conditions to evaluation state to determine next page path\n */\n getNextPath(context: FormContext) {\n const { model, next, path } = this\n const { evaluationState } = context\n\n const summaryPath = this.getSummaryPath()\n const statusPath = this.getStatusPath()\n\n // Walk from summary page (no next links) to status page\n let defaultPath = path === summaryPath ? statusPath : undefined\n\n if (model.engine === Engine.V2) {\n if (this.pageDef.controller !== ControllerType.Terminal) {\n const { pages } = this.model\n const pageIndex = pages.indexOf(this)\n\n // The \"next\" page is the first found after the current which is\n // either unconditional or has a condition that evaluates to \"true\"\n const nextPage = pages.slice(pageIndex + 1).find((page) => {\n const { condition } = page\n\n if (condition) {\n const conditionResult = condition.fn(evaluationState)\n\n if (!conditionResult) {\n return false\n }\n }\n\n return true\n })\n\n return nextPage?.path ?? defaultPath\n } else {\n return defaultPath\n }\n }\n\n const nextLink = next.find((link) => {\n const { condition } = link\n\n if (condition) {\n return model.conditions[condition]?.fn(evaluationState) ?? false\n }\n\n defaultPath = link.path\n return false\n })\n\n return nextLink?.path ?? defaultPath\n }\n\n /**\n * Gets the form payload (from state) for this page only\n */\n getFormDataFromState(\n request: FormContextRequest | undefined,\n state: FormSubmissionState\n ): FormPayload {\n const { collection } = this\n\n // Form params from request\n const params = this.getFormParams(request)\n\n // Form payload from state\n const payload = collection.getFormDataFromState(state)\n\n return {\n ...params,\n ...payload\n }\n }\n\n /**\n * Gets form params (from payload) for this page only\n */\n getFormParams(request?: FormContextRequest): FormPayloadParams {\n const { payload } = request ?? {}\n\n const result = paramsSchema.validate(payload, {\n abortEarly: false,\n stripUnknown: true\n })\n\n return result.value as FormPayloadParams\n }\n\n getStateFromValidForm(\n request: FormContextRequest,\n state: FormSubmissionState,\n payload: FormPayload\n ): FormState {\n return this.collection.getStateFromValidForm(payload)\n }\n\n getErrors(details?: ValidationErrorItem[]) {\n return getErrors(details)\n }\n\n async getState(request: AnyFormRequest) {\n const { query } = request\n\n // Skip get for preview URL direct access\n if ('force' in query) {\n return {}\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.getState(request)\n }\n\n async setState(request: AnyFormRequest, state: FormSubmissionState) {\n const { query } = request\n\n // Skip set for preview URL direct access\n if ('force' in query) {\n return state\n }\n\n const cacheService = getCacheService(request.server)\n\n // Clear any 'not yet validated' state before saving to cache\n return cacheService.setState(request, clearNotYetValidatedState(state))\n }\n\n async mergeState(\n request: AnyFormRequest,\n state: FormSubmissionState,\n update: object\n ) {\n const { query } = request\n\n // Merge state before set\n const updated = merge(state, update)\n\n // Skip set for preview URL direct access\n if ('force' in query) {\n return updated\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.setState(request, updated)\n }\n\n filterConditionalComponents(\n viewModel: FormPageViewModel,\n model: FormModel,\n evaluationState: Partial<Record<string, FormStateValue>>\n ) {\n // Filter our components based on their conditions using our evaluated state\n let filtered = viewModel.components.filter((component) => {\n if (\n (!!component.model.content ||\n component.type === ComponentType.Details) &&\n component.model.condition\n ) {\n const condition = model.conditions[component.model.condition]\n return condition?.fn(evaluationState)\n }\n return true\n })\n\n /**\n * For conditional reveal components (which we no longer support until GDS resolves the related accessibility issues {@link https://github.com/alphagov/govuk-frontend/issues/1991}\n */\n filtered = filtered.map((component) => {\n const evaluatedComponent = component\n const content = evaluatedComponent.model.content\n if (Array.isArray(content)) {\n evaluatedComponent.model.content = content.filter((item) =>\n item.condition\n ? model.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n }\n // apply condition to items for radios, checkboxes etc\n const items = evaluatedComponent.model.items\n\n if (Array.isArray(items)) {\n evaluatedComponent.model.items = items.filter((item) =>\n item.condition\n ? model.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n }\n\n return evaluatedComponent\n })\n\n return filtered\n }\n\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { collection, model, viewName } = this\n const { evaluationState } = context\n\n // Copy any URL params into the form state (if not already done so)\n if (await prefillStateFromQueryParameters(request, this)) {\n // Forward to same page without query string\n return h.redirect(`${request.url.origin}${request.url.pathname}`)\n }\n\n const viewModel = this.getViewModel(request, context)\n viewModel.errors = collection.getViewErrors(viewModel.errors)\n\n const flashedError = request.yar.flash(COMPONENT_STATE_ERROR)\n const flashedErrors = !Array.isArray(flashedError) ? [flashedError] : []\n\n viewModel.errors = (viewModel.errors ?? []).concat(flashedErrors)\n\n const paymentExpiredFlash = request.yar.flash(\n PAYMENT_EXPIRED_NOTIFICATION\n )\n viewModel.showPaymentExpiredNotification =\n !Array.isArray(paymentExpiredFlash)\n\n /**\n * Content components can be hidden based on a condition. If the condition evaluates to true, it is safe to be kept, otherwise discard it\n */\n\n // Filter our components based on their conditions using our evaluated state\n viewModel.components = this.filterConditionalComponents(\n viewModel,\n model,\n evaluationState\n )\n\n viewModel.hasMissingNotificationEmail =\n await this.hasMissingNotificationEmail(request, context)\n\n return h.view(viewName, viewModel)\n }\n }\n\n async hasMissingNotificationEmail(\n request: FormRequest,\n context: FormContext\n ) {\n const { path } = this\n const { params } = request\n const { isForceAccess } = context\n\n const startPath = this.getStartPath()\n const summaryPath = this.getSummaryPath()\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n // Warn the user if the form has no notification email set only on start page and summary page\n if ([startPath, summaryPath].includes(path) && !isForceAccess) {\n const { notificationEmail } = await getFormMetadata(params.slug)\n return !notificationEmail\n }\n\n return false\n }\n\n /**\n * Get the back link for a given progress.\n */\n protected getBackLink(\n request: FormContextRequest,\n context: FormContext\n ): BackLink | undefined {\n const { pageDef } = this\n const { path, query } = request\n const { returnUrl } = query\n const { paths } = context\n\n const itemId = this.getItemId(request)\n\n // Check answers back link\n if (returnUrl) {\n return {\n text:\n hasRepeater(pageDef) && itemId\n ? 'Go back to add another'\n : 'Go back to check answers',\n href: returnUrl\n }\n }\n\n // Item delete pages etc\n const backPath =\n itemId && !path.endsWith(itemId)\n ? paths.at(-1) // Back to main page\n : paths.at(-2) // Back to previous page\n\n // No back link\n if (!backPath) {\n return\n }\n\n // Default back link\n return {\n text: 'Back',\n href: this.getHref(backPath)\n }\n }\n\n makePostRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { collection, viewName, model } = this\n const { isForceAccess, state, evaluationState } = context\n const action = request.payload.action\n\n if (action?.startsWith(FormAction.External)) {\n return await this.dispatchExternal(request, h, context)\n }\n\n /**\n * If there are any errors, render the page with the parsed errors\n * @todo Refactor to match POST REDIRECT GET pattern\n */\n if (context.errors || isForceAccess) {\n const viewModel = this.getViewModel(request, context)\n viewModel.errors = collection.getViewErrors(viewModel.errors)\n\n // Filter our components based on their conditions using our evaluated state\n viewModel.components = this.filterConditionalComponents(\n viewModel,\n model,\n evaluationState\n )\n\n return h.view(viewName, viewModel)\n }\n\n // Save state\n await this.setState(request, state)\n\n // Check if this is a save-and-exit action\n if (action === FormAction.SaveAndExit) {\n return this.handleSaveAndExit(request, context, h)\n }\n\n // Proceed to the next page\n return this.proceed(request, h, this.getNextPath(context))\n }\n }\n\n private async dispatchExternal(\n request: FormRequestPayload,\n h: FormResponseToolkit,\n context: FormContext\n ) {\n const { externalComponents } = getComponentsByType()\n const action = request.payload.action ?? ''\n\n // Find the external action and arguments\n // `external-{componentName}--{argname1}:{argvalue1}--{argname2}:{argvalue2}`\n // E.g. external-abcdef--amount:10--step:manual\n const externalActionsWithArgs = action\n .slice(`${FormAction.External}-`.length)\n .split('--')\n\n const externalActionArgs = externalActionsWithArgs\n .slice(1)\n .map((arg) => arg.split(':'))\n\n const args = Object.fromEntries(externalActionArgs) as Record<\n string,\n string\n >\n\n const componentName = externalActionsWithArgs[0]\n const component = this.model.componentDefMap.get(componentName)\n const componentType = component?.type\n\n if (!componentType) {\n throw Boom.internal(\n `External component of type ${componentType} not found`\n )\n }\n\n const selectedComponent = externalComponents.get(componentType)\n\n if (!selectedComponent) {\n throw Boom.internal(`External component ${componentName} not found`)\n }\n\n // Stash payload without crumb and action\n const stashedPayload = {\n ...context.payload,\n crumb: undefined,\n action: undefined\n }\n request.yar.flash(EXTERNAL_STATE_PAYLOAD, stashedPayload, true)\n\n // Clear any previous state appendage\n request.yar.clear(EXTERNAL_STATE_APPENDAGE)\n\n // Determine if this is a live form (not preview/draft)\n const { state, isPreview } = checkFormStatus(request.params)\n const isLive = state === FormStatus.Live\n\n return await selectedComponent.dispatcher(request, h, {\n component,\n controller: this,\n sourceUrl: request.url.toString(),\n actionArgs: args,\n isLive,\n isPreview\n })\n }\n\n proceed(\n request: FormContextRequest,\n h: FormResponseToolkit,\n nextPath?: string\n ) {\n const nextUrl = nextPath\n ? this.getHref(nextPath) // Redirect to next page\n : this.href // Redirect to current page (refresh)\n\n return proceed(request, h, nextUrl)\n }\n\n /**\n * Handle save-and-exit action\n */\n handleSaveAndExit(\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) {\n const saveAndExit = getSaveAndExitHelpers(request.server)\n\n if (!saveAndExit) {\n throw Boom.internal('Server misconfigured for save and exit')\n }\n\n return saveAndExit(request, h, context)\n }\n\n /**\n * {@link https://hapi.dev/api/?v=20.1.2#route-options}\n */\n get getRouteOptions(): RouteOptions<FormRequestRefs> {\n return {\n ext: {\n onPostHandler: {\n method(_request, h) {\n return h.continue\n }\n }\n }\n }\n }\n\n /**\n * {@link https://hapi.dev/api/?v=20.1.2#route-options}\n */\n get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {\n return {\n payload: {\n parse: true,\n maxBytes: Number.MAX_SAFE_INTEGER,\n failAction: 'ignore'\n },\n ext: {\n onPostHandler: {\n method(_request, h) {\n return h.continue\n }\n }\n }\n }\n }\n}\n"],"mappings":"AAAA,SACEA,aAAa,EACbC,cAAc,EACdC,MAAM,EACNC,aAAa,EACbC,OAAO,EACPC,WAAW,QAGN,oBAAoB;AAC3B,OAAOC,IAAI,MAAM,YAAY;AAI7B,SACEC,qBAAqB,EACrBC,wBAAwB,EACxBC,sBAAsB,EACtBC,4BAA4B;AAE9B,SAASC,mBAAmB;AAC5B,SAASC,YAAY;AAErB,SACEC,eAAe,EACfC,eAAe,EACfC,SAAS,EACTC,qBAAqB,EACrBC,aAAa,EACbC,OAAO;AAGT,SAASC,cAAc;AACvB,SACEC,yBAAyB,EACzBC,+BAA+B;AAajC,SAASC,mBAAmB;AAC5B,SACEC,UAAU,EACVC,UAAU;AAOZ,SACEC,YAAY,EACZC,WAAW,EACXC,YAAY;AAEd,SAASC,KAAK;AAEd,OAAO,MAAMC,sBAAsB,SAASV,cAAc,CAAC;EACzDW,UAAU;EACVC,iBAAiB,GAAG,oBAAoB;EACxCC,gBAAgB,GAAG,IAAI;EAEvBC,WAAWA,CAACC,KAAgB,EAAEC,OAAa,EAAE;IAC3C,KAAK,CAACD,KAAK,EAAEC,OAAO,CAAC;;IAErB;IACA,IAAI,CAACL,UAAU,GAAG,IAAInB,mBAAmB,CACvCR,aAAa,CAACgC,OAAO,CAAC,GAAGA,OAAO,CAACC,UAAU,GAAG,EAAE,EAChD;MAAEF,KAAK;MAAEG,IAAI,EAAE;IAAK,CACtB,CAAC;IAED,IAAI,CAACP,UAAU,CAACQ,UAAU,GAAG,IAAI,CAACR,UAAU,CAACQ,UAAU,CAACC,IAAI,CAAC;MAC3DC,KAAK,EAAEd,WAAW;MAClBe,MAAM,EAAEhB;IACV,CAAC,CAAC;EACJ;EAEA,IAAIiB,IAAIA,CAAA,EAAW;IACjB,MAAM;MAAEC,GAAG;MAAER;IAAQ,CAAC,GAAG,IAAI;IAE7B,IAAI,CAAC/B,OAAO,CAAC+B,OAAO,CAAC,EAAE;MACrB,OAAO,EAAE;IACX;;IAEA;IACA,OAAOA,OAAO,CAACO,IAAI,CAACE,MAAM,CAAC,CAAC;MAAEC;IAAK,CAAC,KAAK;MACvC,MAAMC,QAAQ,GAAG7B,aAAa,CAAC4B,IAAI,CAAC;MAEpC,OAAOF,GAAG,CAACI,KAAK,CAACC,IAAI,CAAEX,IAAI,IAAK;QAC9B,MAAMY,QAAQ,GAAGhC,aAAa,CAACoB,IAAI,CAACQ,IAAI,CAAC;QACzC,OAAOI,QAAQ,KAAKH,QAAQ;MAC9B,CAAC,CAAC;IACJ,CAAC,CAAC;EACJ;EAEA,IAAII,aAAaA,CAAA,EAAY;IAC3B,IAAI,IAAI,CAAChB,KAAK,CAACiB,MAAM,KAAKjD,MAAM,CAACkD,EAAE,EAAE;MACnC,OAAO,IAAI,CAACjB,OAAO,CAACkB,UAAU,KAAKpD,cAAc,CAACqD,QAAQ;IAC5D;IAEA,OAAO,IAAI,CAACZ,IAAI,CAACa,MAAM,GAAG,CAAC;EAC7B;EAEAC,SAASA,CAACC,OAA4B,EAAE;IACtC,MAAM;MAAEC;IAAO,CAAC,GAAG,IAAI,CAACC,aAAa,CAACF,OAAO,CAAC;IAC9C,OAAOC,MAAM,IAAID,OAAO,EAAEG,MAAM,CAACF,MAAM;EACzC;;EAEA;AACF;AACA;AACA;AACA;EACEG,YAAYA,CACVJ,OAA2B,EAC3BK,OAAoB,EACD;IACnB,MAAM;MAAEhC,UAAU;MAAEiC;IAAU,CAAC,GAAG,IAAI;IACtC,MAAM;MAAEC;IAAM,CAAC,GAAGP,OAAO;IACzB,MAAM;MAAEQ,OAAO;MAAEC;IAAO,CAAC,GAAGJ,OAAO;IAEnC,IAAI;MAAEK,SAAS;MAAEC;IAAU,CAAC,GAAGL,SAAS;IAExC,MAAM3B,UAAU,GAAGN,UAAU,CAAC+B,YAAY,CAACI,OAAO,EAAEC,MAAM,EAAEF,KAAK,CAAC;IAClE,MAAMK,cAAc,GAAGjC,UAAU,CAACQ,MAAM,CACtC,CAAC;MAAE0B;IAAgB,CAAC,KAAKA,eAC3B,CAAC;;IAED;IACA,IAAID,cAAc,CAACd,MAAM,KAAK,CAAC,EAAE;MAC/B,MAAM;QAAErB;MAAM,CAAC,GAAGmC,cAAc,CAAC,CAAC,CAAC;MACnC,MAAM;QAAEE,QAAQ;QAAEC;MAAM,CAAC,GAAGtC,KAAK;;MAEjC;MACA,MAAMuC,aAAa,GAAGJ,cAAc,CAAC,CAAC,CAAC,KAAKjC,UAAU,CAAC,CAAC,CAAC;;MAEzD;MACA,MAAMsC,aAAa,GAAGH,QAAQ,EAAEI,MAAM,IAAIH,KAAK;;MAE/C;MACA,IAAIE,aAAa,EAAE;QACjB,MAAME,IAAI,GAAGH,aAAa,GAAG,GAAG,GAAG,GAAG;QAEtCC,aAAa,CAACG,OAAO,GACnBH,aAAa,KAAKF,KAAK,GACnB,gBAAgBI,IAAI,EAAE,GACtB,2BAA2BA,IAAI,EAAE;QAEvC,IAAIH,aAAa,EAAE;UACjBC,aAAa,CAACD,aAAa,GAAGA,aAAa;;UAE3C;UACA,MAAMK,UAAU,GACd,IAAI,CAAChD,UAAU,CAACiD,MAAM,CAACC,EAAE,CAAC,CAAC,CAAC,EAAEC,OAAO,CAACC,QAAQ,KAAK,KAAK;UAE1D,IAAIf,SAAS,EAAE;YACbO,aAAa,CAACS,IAAI,GAAGL,UAAU,GAC3B,GAAGX,SAAS,GAAGvD,YAAY,EAAE,GAC7BuD,SAAS;UACf;UAEAA,SAAS,GAAGA,SAAS,IAAIO,aAAa,CAACS,IAAI;QAC7C;MACF;MAEAf,SAAS,GAAG,CAACK,aAAa;IAC5B,CAAC,MAAM,IAAIJ,cAAc,CAACd,MAAM,GAAG,CAAC,EAAE;MACpC;MACA;MACA,KAAK,MAAM;QAAErB;MAAM,CAAC,IAAImC,cAAc,EAAE;QACtC,IAAInC,KAAK,CAACqC,QAAQ,EAAEI,MAAM,EAAE;UAC1BzC,KAAK,CAACqC,QAAQ,CAACI,MAAM,CAACE,OAAO,GAAG,2BAA2B;QAC7D;QACA,IAAI3C,KAAK,CAACsC,KAAK,EAAE;UACftC,KAAK,CAACsC,KAAK,CAACK,OAAO,GAAG,gBAAgB;QACxC;MACF;IACF;IAEA,MAAMO,oBAAoB,GAAGhD,UAAU,CAACY,IAAI,CAAC,CAAC;MAAEd;IAAM,CAAC,KAAK;MAC1D,IAAI,cAAc,IAAIA,KAAK,EAAE;QAC3B,MAAMmD,YAAY,GAAGnD,KAAK,CAACmD,YAEd;QACb,OAAO,CAACA,YAAY,EAAEC,OAAO,EAAEC,MAAM;MACvC;MACA,OAAO,KAAK;IACd,CAAC,CAAC;IAEF,OAAO;MACL,GAAGxB,SAAS;MACZyB,QAAQ,EAAE,IAAI,CAACC,WAAW,CAAChC,OAAO,EAAEK,OAAO,CAAC;MAC5CA,OAAO;MACPM,SAAS;MACThC,UAAU;MACV8B,MAAM;MACNlC,gBAAgB,EAAE,IAAI,CAAC0D,qBAAqB,CAACjC,OAAO,CAACkC,MAAM,CAAC;MAC5DC,gBAAgB,EAAE,CAACR;IACrB,CAAC;EACH;EAEAS,eAAeA,CAACpC,OAAuB,EAAEK,OAAoB,EAAE;IAC7D,MAAM;MAAEgC;IAAM,CAAC,GAAGhC,OAAO;IAEzB,MAAMiC,SAAS,GAAG,IAAI,CAACC,YAAY,CAAC,CAAC;IACrC,MAAMC,YAAY,GAAGH,KAAK,CAACd,EAAE,CAAC,CAAC,CAAC,CAAC,IAAIe,SAAS;IAE9C,OAAO,CAACD,KAAK,CAACvC,MAAM,GAChBwC,SAAS,CAAC;IAAA,EACVE,YAAY,EAAC;EACnB;;EAEA;AACF;AACA;EACEC,WAAWA,CAACpC,OAAoB,EAAE;IAChC,MAAM;MAAE5B,KAAK;MAAEQ,IAAI;MAAEG;IAAK,CAAC,GAAG,IAAI;IAClC,MAAM;MAAEsD;IAAgB,CAAC,GAAGrC,OAAO;IAEnC,MAAMsC,WAAW,GAAG,IAAI,CAACC,cAAc,CAAC,CAAC;IACzC,MAAMC,UAAU,GAAG,IAAI,CAACC,aAAa,CAAC,CAAC;;IAEvC;IACA,IAAIC,WAAW,GAAG3D,IAAI,KAAKuD,WAAW,GAAGE,UAAU,GAAGG,SAAS;IAE/D,IAAIvE,KAAK,CAACiB,MAAM,KAAKjD,MAAM,CAACkD,EAAE,EAAE;MAC9B,IAAI,IAAI,CAACjB,OAAO,CAACkB,UAAU,KAAKpD,cAAc,CAACqD,QAAQ,EAAE;QACvD,MAAM;UAAEP;QAAM,CAAC,GAAG,IAAI,CAACb,KAAK;QAC5B,MAAMwE,SAAS,GAAG3D,KAAK,CAAC4D,OAAO,CAAC,IAAI,CAAC;;QAErC;QACA;QACA,MAAMC,QAAQ,GAAG7D,KAAK,CAAC8D,KAAK,CAACH,SAAS,GAAG,CAAC,CAAC,CAACI,IAAI,CAAEzE,IAAI,IAAK;UACzD,MAAM;YAAE0E;UAAU,CAAC,GAAG1E,IAAI;UAE1B,IAAI0E,SAAS,EAAE;YACb,MAAMC,eAAe,GAAGD,SAAS,CAACE,EAAE,CAACd,eAAe,CAAC;YAErD,IAAI,CAACa,eAAe,EAAE;cACpB,OAAO,KAAK;YACd;UACF;UAEA,OAAO,IAAI;QACb,CAAC,CAAC;QAEF,OAAOJ,QAAQ,EAAE/D,IAAI,IAAI2D,WAAW;MACtC,CAAC,MAAM;QACL,OAAOA,WAAW;MACpB;IACF;IAEA,MAAMU,QAAQ,GAAGxE,IAAI,CAACoE,IAAI,CAAEK,IAAI,IAAK;MACnC,MAAM;QAAEJ;MAAU,CAAC,GAAGI,IAAI;MAE1B,IAAIJ,SAAS,EAAE;QACb,OAAO7E,KAAK,CAACkF,UAAU,CAACL,SAAS,CAAC,EAAEE,EAAE,CAACd,eAAe,CAAC,IAAI,KAAK;MAClE;MAEAK,WAAW,GAAGW,IAAI,CAACtE,IAAI;MACvB,OAAO,KAAK;IACd,CAAC,CAAC;IAEF,OAAOqE,QAAQ,EAAErE,IAAI,IAAI2D,WAAW;EACtC;;EAEA;AACF;AACA;EACEa,oBAAoBA,CAClB5D,OAAuC,EACvC6D,KAA0B,EACb;IACb,MAAM;MAAExF;IAAW,CAAC,GAAG,IAAI;;IAE3B;IACA,MAAM8B,MAAM,GAAG,IAAI,CAACD,aAAa,CAACF,OAAO,CAAC;;IAE1C;IACA,MAAMQ,OAAO,GAAGnC,UAAU,CAACuF,oBAAoB,CAACC,KAAK,CAAC;IAEtD,OAAO;MACL,GAAG1D,MAAM;MACT,GAAGK;IACL,CAAC;EACH;;EAEA;AACF;AACA;EACEN,aAAaA,CAACF,OAA4B,EAAqB;IAC7D,MAAM;MAAEQ;IAAQ,CAAC,GAAGR,OAAO,IAAI,CAAC,CAAC;IAEjC,MAAM8D,MAAM,GAAG5F,YAAY,CAAC6F,QAAQ,CAACvD,OAAO,EAAE;MAC5CwD,UAAU,EAAE,KAAK;MACjBC,YAAY,EAAE;IAChB,CAAC,CAAC;IAEF,OAAOH,MAAM,CAACI,KAAK;EACrB;EAEAC,qBAAqBA,CACnBnE,OAA2B,EAC3B6D,KAA0B,EAC1BrD,OAAoB,EACT;IACX,OAAO,IAAI,CAACnC,UAAU,CAAC8F,qBAAqB,CAAC3D,OAAO,CAAC;EACvD;EAEAlD,SAASA,CAAC8G,OAA+B,EAAE;IACzC,OAAO9G,SAAS,CAAC8G,OAAO,CAAC;EAC3B;EAEA,MAAMC,QAAQA,CAACrE,OAAuB,EAAE;IACtC,MAAM;MAAEO;IAAM,CAAC,GAAGP,OAAO;;IAEzB;IACA,IAAI,OAAO,IAAIO,KAAK,EAAE;MACpB,OAAO,CAAC,CAAC;IACX;IAEA,MAAM+D,YAAY,GAAGjH,eAAe,CAAC2C,OAAO,CAACkC,MAAM,CAAC;IAEpD,OAAOoC,YAAY,CAACD,QAAQ,CAACrE,OAAO,CAAC;EACvC;EAEA,MAAMuE,QAAQA,CAACvE,OAAuB,EAAE6D,KAA0B,EAAE;IAClE,MAAM;MAAEtD;IAAM,CAAC,GAAGP,OAAO;;IAEzB;IACA,IAAI,OAAO,IAAIO,KAAK,EAAE;MACpB,OAAOsD,KAAK;IACd;IAEA,MAAMS,YAAY,GAAGjH,eAAe,CAAC2C,OAAO,CAACkC,MAAM,CAAC;;IAEpD;IACA,OAAOoC,YAAY,CAACC,QAAQ,CAACvE,OAAO,EAAErC,yBAAyB,CAACkG,KAAK,CAAC,CAAC;EACzE;EAEA,MAAMW,UAAUA,CACdxE,OAAuB,EACvB6D,KAA0B,EAC1BY,MAAc,EACd;IACA,MAAM;MAAElE;IAAM,CAAC,GAAGP,OAAO;;IAEzB;IACA,MAAM0E,OAAO,GAAGvG,KAAK,CAAC0F,KAAK,EAAEY,MAAM,CAAC;;IAEpC;IACA,IAAI,OAAO,IAAIlE,KAAK,EAAE;MACpB,OAAOmE,OAAO;IAChB;IAEA,MAAMJ,YAAY,GAAGjH,eAAe,CAAC2C,OAAO,CAACkC,MAAM,CAAC;IAEpD,OAAOoC,YAAY,CAACC,QAAQ,CAACvE,OAAO,EAAE0E,OAAO,CAAC;EAChD;EAEAC,2BAA2BA,CACzBrE,SAA4B,EAC5B7B,KAAgB,EAChBiE,eAAwD,EACxD;IACA;IACA,IAAIkC,QAAQ,GAAGtE,SAAS,CAAC3B,UAAU,CAACQ,MAAM,CAAE0F,SAAS,IAAK;MACxD,IACE,CAAC,CAAC,CAACA,SAAS,CAACpG,KAAK,CAACqG,OAAO,IACxBD,SAAS,CAACE,IAAI,KAAKxI,aAAa,CAACyI,OAAO,KAC1CH,SAAS,CAACpG,KAAK,CAAC6E,SAAS,EACzB;QACA,MAAMA,SAAS,GAAG7E,KAAK,CAACkF,UAAU,CAACkB,SAAS,CAACpG,KAAK,CAAC6E,SAAS,CAAC;QAC7D,OAAOA,SAAS,EAAEE,EAAE,CAACd,eAAe,CAAC;MACvC;MACA,OAAO,IAAI;IACb,CAAC,CAAC;;IAEF;AACJ;AACA;IACIkC,QAAQ,GAAGA,QAAQ,CAACK,GAAG,CAAEJ,SAAS,IAAK;MACrC,MAAMK,kBAAkB,GAAGL,SAAS;MACpC,MAAMC,OAAO,GAAGI,kBAAkB,CAACzG,KAAK,CAACqG,OAAO;MAChD,IAAIK,KAAK,CAACC,OAAO,CAACN,OAAO,CAAC,EAAE;QAC1BI,kBAAkB,CAACzG,KAAK,CAACqG,OAAO,GAAGA,OAAO,CAAC3F,MAAM,CAAEkG,IAAI,IACrDA,IAAI,CAAC/B,SAAS,GACV7E,KAAK,CAACkF,UAAU,CAAC0B,IAAI,CAAC/B,SAAS,CAAC,EAAEE,EAAE,CAACd,eAAe,CAAC,GACrD,IACN,CAAC;MACH;MACA;MACA,MAAM4C,KAAK,GAAGJ,kBAAkB,CAACzG,KAAK,CAAC6G,KAAK;MAE5C,IAAIH,KAAK,CAACC,OAAO,CAACE,KAAK,CAAC,EAAE;QACxBJ,kBAAkB,CAACzG,KAAK,CAAC6G,KAAK,GAAGA,KAAK,CAACnG,MAAM,CAAEkG,IAAI,IACjDA,IAAI,CAAC/B,SAAS,GACV7E,KAAK,CAACkF,UAAU,CAAC0B,IAAI,CAAC/B,SAAS,CAAC,EAAEE,EAAE,CAACd,eAAe,CAAC,GACrD,IACN,CAAC;MACH;MAEA,OAAOwC,kBAAkB;IAC3B,CAAC,CAAC;IAEF,OAAON,QAAQ;EACjB;EAEAW,mBAAmBA,CAAA,EAAG;IACpB,OAAO,OACLvF,OAAoB,EACpBK,OAAoB,EACpBmF,CAAsB,KACnB;MACH,MAAM;QAAEnH,UAAU;QAAEI,KAAK;QAAEgH;MAAS,CAAC,GAAG,IAAI;MAC5C,MAAM;QAAE/C;MAAgB,CAAC,GAAGrC,OAAO;;MAEnC;MACA,IAAI,MAAMzC,+BAA+B,CAACoC,OAAO,EAAE,IAAI,CAAC,EAAE;QACxD;QACA,OAAOwF,CAAC,CAACE,QAAQ,CAAC,GAAG1F,OAAO,CAAC2F,GAAG,CAACC,MAAM,GAAG5F,OAAO,CAAC2F,GAAG,CAACE,QAAQ,EAAE,CAAC;MACnE;MAEA,MAAMvF,SAAS,GAAG,IAAI,CAACF,YAAY,CAACJ,OAAO,EAAEK,OAAO,CAAC;MACrDC,SAAS,CAACG,MAAM,GAAGpC,UAAU,CAACyH,aAAa,CAACxF,SAAS,CAACG,MAAM,CAAC;MAE7D,MAAMsF,YAAY,GAAG/F,OAAO,CAACgG,GAAG,CAACC,KAAK,CAACnJ,qBAAqB,CAAC;MAC7D,MAAMoJ,aAAa,GAAG,CAACf,KAAK,CAACC,OAAO,CAACW,YAAY,CAAC,GAAG,CAACA,YAAY,CAAC,GAAG,EAAE;MAExEzF,SAAS,CAACG,MAAM,GAAG,CAACH,SAAS,CAACG,MAAM,IAAI,EAAE,EAAE0F,MAAM,CAACD,aAAa,CAAC;MAEjE,MAAME,mBAAmB,GAAGpG,OAAO,CAACgG,GAAG,CAACC,KAAK,CAC3ChJ,4BACF,CAAC;MACDqD,SAAS,CAAC+F,8BAA8B,GACtC,CAAClB,KAAK,CAACC,OAAO,CAACgB,mBAAmB,CAAC;;MAErC;AACN;AACA;;MAEM;MACA9F,SAAS,CAAC3B,UAAU,GAAG,IAAI,CAACgG,2BAA2B,CACrDrE,SAAS,EACT7B,KAAK,EACLiE,eACF,CAAC;MAEDpC,SAAS,CAACgG,2BAA2B,GACnC,MAAM,IAAI,CAACA,2BAA2B,CAACtG,OAAO,EAAEK,OAAO,CAAC;MAE1D,OAAOmF,CAAC,CAACe,IAAI,CAACd,QAAQ,EAAEnF,SAAS,CAAC;IACpC,CAAC;EACH;EAEA,MAAMgG,2BAA2BA,CAC/BtG,OAAoB,EACpBK,OAAoB,EACpB;IACA,MAAM;MAAEjB;IAAK,CAAC,GAAG,IAAI;IACrB,MAAM;MAAEe;IAAO,CAAC,GAAGH,OAAO;IAC1B,MAAM;MAAEwG;IAAc,CAAC,GAAGnG,OAAO;IAEjC,MAAMiC,SAAS,GAAG,IAAI,CAACC,YAAY,CAAC,CAAC;IACrC,MAAMI,WAAW,GAAG,IAAI,CAACC,cAAc,CAAC,CAAC;IACzC,MAAM;MAAE6D;IAAa,CAAC,GAAG,IAAI,CAAChI,KAAK,CAACiI,QAAQ;IAC5C,MAAM;MAAEC;IAAgB,CAAC,GAAGF,YAAY;;IAExC;IACA,IAAI,CAACnE,SAAS,EAAEK,WAAW,CAAC,CAACiE,QAAQ,CAACxH,IAAI,CAAC,IAAI,CAACoH,aAAa,EAAE;MAC7D,MAAM;QAAEK;MAAkB,CAAC,GAAG,MAAMF,eAAe,CAACxG,MAAM,CAAC2G,IAAI,CAAC;MAChE,OAAO,CAACD,iBAAiB;IAC3B;IAEA,OAAO,KAAK;EACd;;EAEA;AACF;AACA;EACY7E,WAAWA,CACnBhC,OAA2B,EAC3BK,OAAoB,EACE;IACtB,MAAM;MAAE3B;IAAQ,CAAC,GAAG,IAAI;IACxB,MAAM;MAAEU,IAAI;MAAEmB;IAAM,CAAC,GAAGP,OAAO;IAC/B,MAAM;MAAE+G;IAAU,CAAC,GAAGxG,KAAK;IAC3B,MAAM;MAAE8B;IAAM,CAAC,GAAGhC,OAAO;IAEzB,MAAMJ,MAAM,GAAG,IAAI,CAACF,SAAS,CAACC,OAAO,CAAC;;IAEtC;IACA,IAAI+G,SAAS,EAAE;MACb,OAAO;QACLrF,IAAI,EACF9E,WAAW,CAAC8B,OAAO,CAAC,IAAIuB,MAAM,GAC1B,wBAAwB,GACxB,0BAA0B;QAChC+G,IAAI,EAAED;MACR,CAAC;IACH;;IAEA;IACA,MAAME,QAAQ,GACZhH,MAAM,IAAI,CAACb,IAAI,CAAC8H,QAAQ,CAACjH,MAAM,CAAC,GAC5BoC,KAAK,CAACd,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAAA,EACbc,KAAK,CAACd,EAAE,CAAC,CAAC,CAAC,CAAC,EAAC;;IAEnB;IACA,IAAI,CAAC0F,QAAQ,EAAE;MACb;IACF;;IAEA;IACA,OAAO;MACLvF,IAAI,EAAE,MAAM;MACZsF,IAAI,EAAE,IAAI,CAACG,OAAO,CAACF,QAAQ;IAC7B,CAAC;EACH;EAEAG,oBAAoBA,CAAA,EAAG;IACrB,OAAO,OACLpH,OAA2B,EAC3BK,OAAoB,EACpBmF,CAAsB,KACnB;MACH,MAAM;QAAEnH,UAAU;QAAEoH,QAAQ;QAAEhH;MAAM,CAAC,GAAG,IAAI;MAC5C,MAAM;QAAE+H,aAAa;QAAE3C,KAAK;QAAEnB;MAAgB,CAAC,GAAGrC,OAAO;MACzD,MAAMrB,MAAM,GAAGgB,OAAO,CAACQ,OAAO,CAACxB,MAAM;MAErC,IAAIA,MAAM,EAAEqI,UAAU,CAACvJ,UAAU,CAACwJ,QAAQ,CAAC,EAAE;QAC3C,OAAO,MAAM,IAAI,CAACC,gBAAgB,CAACvH,OAAO,EAAEwF,CAAC,EAAEnF,OAAO,CAAC;MACzD;;MAEA;AACN;AACA;AACA;MACM,IAAIA,OAAO,CAACI,MAAM,IAAI+F,aAAa,EAAE;QACnC,MAAMlG,SAAS,GAAG,IAAI,CAACF,YAAY,CAACJ,OAAO,EAAEK,OAAO,CAAC;QACrDC,SAAS,CAACG,MAAM,GAAGpC,UAAU,CAACyH,aAAa,CAACxF,SAAS,CAACG,MAAM,CAAC;;QAE7D;QACAH,SAAS,CAAC3B,UAAU,GAAG,IAAI,CAACgG,2BAA2B,CACrDrE,SAAS,EACT7B,KAAK,EACLiE,eACF,CAAC;QAED,OAAO8C,CAAC,CAACe,IAAI,CAACd,QAAQ,EAAEnF,SAAS,CAAC;MACpC;;MAEA;MACA,MAAM,IAAI,CAACiE,QAAQ,CAACvE,OAAO,EAAE6D,KAAK,CAAC;;MAEnC;MACA,IAAI7E,MAAM,KAAKlB,UAAU,CAAC0J,WAAW,EAAE;QACrC,OAAO,IAAI,CAACC,iBAAiB,CAACzH,OAAO,EAAEK,OAAO,EAAEmF,CAAC,CAAC;MACpD;;MAEA;MACA,OAAO,IAAI,CAAC/H,OAAO,CAACuC,OAAO,EAAEwF,CAAC,EAAE,IAAI,CAAC/C,WAAW,CAACpC,OAAO,CAAC,CAAC;IAC5D,CAAC;EACH;EAEA,MAAckH,gBAAgBA,CAC5BvH,OAA2B,EAC3BwF,CAAsB,EACtBnF,OAAoB,EACpB;IACA,MAAM;MAAEqH;IAAmB,CAAC,GAAG7J,mBAAmB,CAAC,CAAC;IACpD,MAAMmB,MAAM,GAAGgB,OAAO,CAACQ,OAAO,CAACxB,MAAM,IAAI,EAAE;;IAE3C;IACA;IACA;IACA,MAAM2I,uBAAuB,GAAG3I,MAAM,CACnCoE,KAAK,CAAC,GAAGtF,UAAU,CAACwJ,QAAQ,GAAG,CAACxH,MAAM,CAAC,CACvC8H,KAAK,CAAC,IAAI,CAAC;IAEd,MAAMC,kBAAkB,GAAGF,uBAAuB,CAC/CvE,KAAK,CAAC,CAAC,CAAC,CACR6B,GAAG,CAAE6C,GAAG,IAAKA,GAAG,CAACF,KAAK,CAAC,GAAG,CAAC,CAAC;IAE/B,MAAMG,IAAI,GAAGC,MAAM,CAACC,WAAW,CAACJ,kBAAkB,CAGjD;IAED,MAAMK,aAAa,GAAGP,uBAAuB,CAAC,CAAC,CAAC;IAChD,MAAM9C,SAAS,GAAG,IAAI,CAACpG,KAAK,CAAC0J,eAAe,CAACC,GAAG,CAACF,aAAa,CAAC;IAC/D,MAAMG,aAAa,GAAGxD,SAAS,EAAEE,IAAI;IAErC,IAAI,CAACsD,aAAa,EAAE;MAClB,MAAMxL,IAAI,CAACyL,QAAQ,CACjB,8BAA8BD,aAAa,YAC7C,CAAC;IACH;IAEA,MAAME,iBAAiB,GAAGb,kBAAkB,CAACU,GAAG,CAACC,aAAa,CAAC;IAE/D,IAAI,CAACE,iBAAiB,EAAE;MACtB,MAAM1L,IAAI,CAACyL,QAAQ,CAAC,sBAAsBJ,aAAa,YAAY,CAAC;IACtE;;IAEA;IACA,MAAMM,cAAc,GAAG;MACrB,GAAGnI,OAAO,CAACG,OAAO;MAClBzB,KAAK,EAAEiE,SAAS;MAChBhE,MAAM,EAAEgE;IACV,CAAC;IACDhD,OAAO,CAACgG,GAAG,CAACC,KAAK,CAACjJ,sBAAsB,EAAEwL,cAAc,EAAE,IAAI,CAAC;;IAE/D;IACAxI,OAAO,CAACgG,GAAG,CAACyC,KAAK,CAAC1L,wBAAwB,CAAC;;IAE3C;IACA,MAAM;MAAE8G,KAAK;MAAE6E;IAAU,CAAC,GAAGtL,eAAe,CAAC4C,OAAO,CAACG,MAAM,CAAC;IAC5D,MAAMwI,MAAM,GAAG9E,KAAK,KAAK9F,UAAU,CAAC6K,IAAI;IAExC,OAAO,MAAML,iBAAiB,CAACM,UAAU,CAAC7I,OAAO,EAAEwF,CAAC,EAAE;MACpDX,SAAS;MACTjF,UAAU,EAAE,IAAI;MAChBkJ,SAAS,EAAE9I,OAAO,CAAC2F,GAAG,CAACoD,QAAQ,CAAC,CAAC;MACjCC,UAAU,EAAEjB,IAAI;MAChBY,MAAM;MACND;IACF,CAAC,CAAC;EACJ;EAEAjL,OAAOA,CACLuC,OAA2B,EAC3BwF,CAAsB,EACtByD,QAAiB,EACjB;IACA,MAAMC,OAAO,GAAGD,QAAQ,GACpB,IAAI,CAAC9B,OAAO,CAAC8B,QAAQ,CAAC,CAAC;IAAA,EACvB,IAAI,CAACjC,IAAI,EAAC;;IAEd,OAAOvJ,OAAO,CAACuC,OAAO,EAAEwF,CAAC,EAAE0D,OAAO,CAAC;EACrC;;EAEA;AACF;AACA;EACEzB,iBAAiBA,CACfzH,OAA2B,EAC3BK,OAAoB,EACpBmF,CAAsB,EACtB;IACA,MAAM2D,WAAW,GAAG5L,qBAAqB,CAACyC,OAAO,CAACkC,MAAM,CAAC;IAEzD,IAAI,CAACiH,WAAW,EAAE;MAChB,MAAMtM,IAAI,CAACyL,QAAQ,CAAC,wCAAwC,CAAC;IAC/D;IAEA,OAAOa,WAAW,CAACnJ,OAAO,EAAEwF,CAAC,EAAEnF,OAAO,CAAC;EACzC;;EAEA;AACF;AACA;EACE,IAAI+I,eAAeA,CAAA,EAAkC;IACnD,OAAO;MACLC,GAAG,EAAE;QACHC,aAAa,EAAE;UACbC,MAAMA,CAACC,QAAQ,EAAEhE,CAAC,EAAE;YAClB,OAAOA,CAAC,CAACiE,QAAQ;UACnB;QACF;MACF;IACF,CAAC;EACH;;EAEA;AACF;AACA;EACE,IAAIC,gBAAgBA,CAAA,EAAyC;IAC3D,OAAO;MACLlJ,OAAO,EAAE;QACPmJ,KAAK,EAAE,IAAI;QACXC,QAAQ,EAAEC,MAAM,CAACC,gBAAgB;QACjCC,UAAU,EAAE;MACd,CAAC;MACDV,GAAG,EAAE;QACHC,aAAa,EAAE;UACbC,MAAMA,CAACC,QAAQ,EAAEhE,CAAC,EAAE;YAClB,OAAOA,CAAC,CAACiE,QAAQ;UACnB;QACF;MACF;IACF,CAAC;EACH;AACF","ignoreList":[]}
@@ -15,6 +15,8 @@ export declare class StartPageController extends QuestionPageController {
15
15
  errors?: import("~/src/server/plugins/engine/types.js").FormSubmissionError[];
16
16
  hasMissingNotificationEmail?: boolean;
17
17
  allowSaveAndExit: boolean;
18
+ showSubmitButton?: boolean;
19
+ showPaymentExpiredNotification?: boolean;
18
20
  page: import("./PageController.js").PageController;
19
21
  name?: string;
20
22
  pageTitle: string;
@@ -13,6 +13,7 @@ export declare class SummaryPageController extends QuestionPageController {
13
13
  */
14
14
  constructor(model: FormModel, pageDef: Page);
15
15
  getSummaryViewModel(request: FormContextRequest, context: FormContext): SummaryViewModel;
16
+ private buildPaymentDetails;
16
17
  /**
17
18
  * Returns an async function. This is called in plugin.ts when there is a GET request at `/{id}/{path*}`,
18
19
  */
@@ -23,6 +24,22 @@ export declare class SummaryPageController extends QuestionPageController {
23
24
  */
24
25
  makePostRouteHandler(): (request: FormRequestPayload, context: FormContext, h: FormResponseToolkit) => Promise<import("@hapi/hapi").ResponseObject>;
25
26
  handleFormSubmit(request: FormRequestPayload, context: FormContext, h: FormResponseToolkit): Promise<import("@hapi/hapi").ResponseObject>;
27
+ /**
28
+ * Handles errors during form submission
29
+ */
30
+ private handleSubmissionError;
31
+ /**
32
+ * Handles InvalidComponentStateError during submission
33
+ */
34
+ private handleInvalidComponentStateError;
35
+ /**
36
+ * Handles PaymentPreAuthError during submission
37
+ */
38
+ private handlePaymentPreAuthError;
39
+ /**
40
+ * Handles PaymentSubmissionError during submission
41
+ */
42
+ private handlePaymentSubmissionError;
26
43
  get postRouteOptions(): RouteOptions<FormRequestPayloadRefs>;
27
44
  }
28
45
  export declare function submitForm(context: FormContext, metadata: FormMetadata, request: FormRequestPayload, summaryViewModel: SummaryViewModel, model: FormModel, emailAddress: string, formMetadata: FormMetadata): Promise<void>;