@defra/forms-model 3.0.644 → 3.0.646

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 (46) hide show
  1. package/dist/module/components/component-types.js +2 -1
  2. package/dist/module/components/component-types.js.map +1 -1
  3. package/dist/module/components/types.js.map +1 -1
  4. package/dist/module/form/form-definition/index.js +13 -2
  5. package/dist/module/form/form-definition/index.js.map +1 -1
  6. package/dist/module/form/form-metrics/enums.js +7 -0
  7. package/dist/module/form/form-metrics/enums.js.map +1 -0
  8. package/dist/module/form/form-metrics/types.js +2 -0
  9. package/dist/module/form/form-metrics/types.js.map +1 -0
  10. package/dist/module/index.js +2 -0
  11. package/dist/module/index.js.map +1 -1
  12. package/dist/module/pages/helpers.js +38 -2
  13. package/dist/module/pages/helpers.js.map +1 -1
  14. package/dist/module/pages/index.js +1 -1
  15. package/dist/module/pages/index.js.map +1 -1
  16. package/dist/types/components/component-types.d.ts.map +1 -1
  17. package/dist/types/components/types.d.ts +5 -0
  18. package/dist/types/components/types.d.ts.map +1 -1
  19. package/dist/types/form/form-definition/index.d.ts.map +1 -1
  20. package/dist/types/form/form-metrics/enums.d.ts +6 -0
  21. package/dist/types/form/form-metrics/enums.d.ts.map +1 -0
  22. package/dist/types/form/form-metrics/types.d.ts +32 -0
  23. package/dist/types/form/form-metrics/types.d.ts.map +1 -0
  24. package/dist/types/index.d.ts +2 -0
  25. package/dist/types/index.d.ts.map +1 -1
  26. package/dist/types/pages/helpers.d.ts +9 -0
  27. package/dist/types/pages/helpers.d.ts.map +1 -1
  28. package/dist/types/pages/index.d.ts +1 -1
  29. package/dist/types/pages/index.d.ts.map +1 -1
  30. package/package.json +1 -1
  31. package/schemas/component-schema-v2.json +35 -2
  32. package/schemas/component-schema.json +35 -2
  33. package/schemas/form-definition-schema.json +105 -6
  34. package/schemas/form-definition-v2-schema.json +175 -10
  35. package/schemas/list-schema-v2.json +70 -4
  36. package/schemas/list-schema.json +70 -4
  37. package/schemas/page-schema-v2.json +105 -6
  38. package/schemas/page-schema.json +35 -2
  39. package/src/components/component-types.ts +2 -1
  40. package/src/components/types.ts +5 -0
  41. package/src/form/form-definition/index.ts +31 -3
  42. package/src/form/form-metrics/enums.ts +5 -0
  43. package/src/form/form-metrics/types.ts +39 -0
  44. package/src/index.ts +2 -0
  45. package/src/pages/helpers.ts +43 -0
  46. package/src/pages/index.ts +2 -0
@@ -198,7 +198,8 @@ export const ComponentTypes: readonly ComponentDef[] = Object.freeze([
198
198
  hint: '',
199
199
  options: {
200
200
  amount: 1,
201
- description: 'payment desc'
201
+ description: 'payment desc',
202
+ conditionalAmounts: []
202
203
  }
203
204
  } as PaymentFieldComponent,
204
205
  {
@@ -260,6 +260,11 @@ export interface PaymentFieldComponent extends FormFieldBase {
260
260
  options: FormFieldBase['options'] & {
261
261
  amount: number
262
262
  description: string
263
+ conditionalAmounts?: {
264
+ condition: string
265
+ amount: number
266
+ }[]
267
+ emailField?: string
263
268
  }
264
269
  }
265
270
 
@@ -580,10 +580,10 @@ export const componentSchema = Joi.object<ComponentDef>()
580
580
  amount: Joi.when('type', {
581
581
  is: Joi.string().trim().valid(ComponentType.PaymentField).required(),
582
582
  then: Joi.number()
583
- .min(0.3)
583
+ .min(0)
584
584
  .max(100000)
585
585
  .required()
586
- .description('Payment amount in GBP (£0.30 - £100,000)')
586
+ .description('Payment amount in GBP (£0 - £100,000)')
587
587
  }).description('Payment amount - for PaymentField only'),
588
588
  description: Joi.when('type', {
589
589
  is: Joi.string().trim().valid(ComponentType.PaymentField).required(),
@@ -591,7 +591,35 @@ export const componentSchema = Joi.object<ComponentDef>()
591
591
  .max(230)
592
592
  .required()
593
593
  .description('Payment description (max 230 chars)')
594
- }).description('Payment description - for PaymentField only')
594
+ }).description('Payment description - for PaymentField only'),
595
+ conditionalAmounts: Joi.when('type', {
596
+ is: Joi.string().trim().valid(ComponentType.PaymentField).required(),
597
+ then: Joi.array()
598
+ .items(
599
+ Joi.object({
600
+ condition: Joi.string()
601
+ .trim()
602
+ .required()
603
+ .description('Condition ID for this amount'),
604
+ amount: Joi.number()
605
+ .min(0.3)
606
+ .max(100000)
607
+ .required()
608
+ .description('Amount in GBP when condition is true (min £0.30)')
609
+ })
610
+ )
611
+ .optional()
612
+ .description('Conditional payment amounts evaluated in order')
613
+ }).description('Conditional amounts - for PaymentField only'),
614
+ emailField: Joi.when('type', {
615
+ is: Joi.string().trim().valid(ComponentType.PaymentField).required(),
616
+ then: Joi.string()
617
+ .trim()
618
+ .optional()
619
+ .description(
620
+ 'Name of EmailAddressField to prepopulate GOV.UK Pay email'
621
+ )
622
+ }).description('Email field reference - for PaymentField only')
595
623
  })
596
624
  .default({})
597
625
  .unknown(true)
@@ -0,0 +1,5 @@
1
+ export enum FormMetricType {
2
+ HeadlineMetric = 'headline-metric',
3
+ OverviewMetric = 'overview-metric',
4
+ TimelineMetric = 'timeline-metric'
5
+ }
@@ -0,0 +1,39 @@
1
+ import { type FormStatus } from '~/src/common/enums.js'
2
+ import { type FormMetricType } from '~/src/form/form-metrics/enums.js'
3
+
4
+ export interface FormHeadlineDetail {
5
+ count: number
6
+ countSevenDaysAgo: number
7
+ countThirtyDaysAgo: number
8
+ countOneYearAgo: number
9
+ }
10
+
11
+ export interface FormHeadlineMetric {
12
+ type: FormMetricType.HeadlineMetric
13
+ headlineCounts: Record<string, FormHeadlineDetail>
14
+ updatedAt: Date
15
+ }
16
+
17
+ export interface FormOverviewMetric {
18
+ type: FormMetricType.OverviewMetric
19
+ formId: string
20
+ formStatus: FormStatus
21
+ summaryMetrics: Record<string, number | string | string[]>
22
+ featureCounts: Record<string, number>
23
+ submissionsCount: number
24
+ updatedAt: Date
25
+ }
26
+
27
+ export interface FormTimelineMetric {
28
+ type: FormMetricType.TimelineMetric
29
+ formId: string
30
+ formStatus: FormStatus
31
+ metricName: string
32
+ metricValue: number
33
+ createdAt: Date
34
+ }
35
+
36
+ export type FormMetric =
37
+ | FormHeadlineMetric
38
+ | FormOverviewMetric
39
+ | FormTimelineMetric
package/src/index.ts CHANGED
@@ -10,6 +10,8 @@ export * from '~/src/form/form-definition/index.js'
10
10
  export * from '~/src/form/form-definition/types.js'
11
11
  export * from '~/src/form/form-definition/helpers.js'
12
12
  export * from '~/src/form/form-metadata/index.js'
13
+ export * from '~/src/form/form-metrics/enums.js'
14
+ export * from '~/src/form/form-metrics/types.js'
13
15
  export * from '~/src/form/form-submission/index.js'
14
16
  export * from '~/src/form/form-submission/enums.js'
15
17
  export * from '~/src/form/utils/index.js'
@@ -135,6 +135,47 @@ export function includesPaymentField(components: ComponentDef[]): boolean {
135
135
  )
136
136
  }
137
137
 
138
+ /**
139
+ * Helper function to determine if a payment question already exists in the form
140
+ */
141
+ export function hasPaymentQuestionInForm(definition: FormDefinition) {
142
+ if (definition.pages.length === 0) {
143
+ return false
144
+ }
145
+
146
+ for (const page of definition.pages) {
147
+ const hasPayment = hasComponents(page)
148
+ ? includesPaymentField(page.components)
149
+ : false
150
+ if (hasPayment) {
151
+ return true
152
+ }
153
+ }
154
+ return false
155
+ }
156
+
157
+ /**
158
+ * Helper function to determine if a specific question type exists in the form
159
+ */
160
+ export function hasSpecificQuestionTypeInForm(
161
+ definition: FormDefinition,
162
+ componentType: ComponentType
163
+ ) {
164
+ if (definition.pages.length === 0) {
165
+ return false
166
+ }
167
+
168
+ for (const page of definition.pages) {
169
+ const hasPayment = hasComponents(page)
170
+ ? page.components.some((component) => component.type === componentType)
171
+ : false
172
+ if (hasPayment) {
173
+ return true
174
+ }
175
+ }
176
+ return false
177
+ }
178
+
138
179
  const SHOW_REPEATER_CONTROLLERS = [ControllerType.Page, ControllerType.Repeat]
139
180
 
140
181
  export function showRepeaterSettings(page: Page): boolean {
@@ -207,6 +248,7 @@ export function replaceCustomControllers(definition: FormDefinition) {
207
248
  const standardControllers = new Set(
208
249
  Object.values(ControllerType)
209
250
  .filter((x) => x !== ControllerType.SummaryWithConfirmationEmail)
251
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion
210
252
  .map((x) => x.toString())
211
253
  )
212
254
 
@@ -215,6 +257,7 @@ export function replaceCustomControllers(definition: FormDefinition) {
215
257
  pages: definition.pages.map((page) => {
216
258
  if (
217
259
  !standardControllers.has(
260
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion
218
261
  (page.controller ?? ControllerType.Page).toString()
219
262
  )
220
263
  ) {
@@ -14,7 +14,9 @@ export {
14
14
  hasComponentsEvenIfNoNext,
15
15
  hasFormComponents,
16
16
  hasNext,
17
+ hasPaymentQuestionInForm,
17
18
  hasRepeater,
19
+ hasSpecificQuestionTypeInForm,
18
20
  includesFileUploadField,
19
21
  includesPaymentField,
20
22
  isControllerName,