@pega/cosmos-react-demos 4.0.0-dev.17.1 → 4.0.0-dev.18.1

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 (149) hide show
  1. package/jsx/core/AIButton/AIButton.stories.d.ts +5 -1
  2. package/jsx/core/AIButton/AIButton.stories.d.ts.map +1 -1
  3. package/jsx/core/AIButton/AIButton.stories.jsx +55 -28
  4. package/jsx/core/AIButton/AIButton.stories.jsx.map +1 -1
  5. package/jsx/core/AppShell/AppShell.stories.d.ts.map +1 -1
  6. package/jsx/core/AppShell/AppShell.stories.jsx +8 -54
  7. package/jsx/core/AppShell/AppShell.stories.jsx.map +1 -1
  8. package/jsx/core/Banner/Banner.stories.d.ts.map +1 -1
  9. package/jsx/core/Banner/Banner.stories.jsx +17 -11
  10. package/jsx/core/Banner/Banner.stories.jsx.map +1 -1
  11. package/jsx/core/Dialog/FormDialog.mocks.d.ts.map +1 -1
  12. package/jsx/core/Dialog/FormDialog.mocks.jsx +4 -2
  13. package/jsx/core/Dialog/FormDialog.mocks.jsx.map +1 -1
  14. package/jsx/core/Dialog/InfoDialog.mocks.d.ts.map +1 -1
  15. package/jsx/core/Dialog/InfoDialog.mocks.jsx +2 -1
  16. package/jsx/core/Dialog/InfoDialog.mocks.jsx.map +1 -1
  17. package/jsx/core/Modal/Modal.stories.d.ts.map +1 -1
  18. package/jsx/core/Modal/Modal.stories.jsx +2 -1
  19. package/jsx/core/Modal/Modal.stories.jsx.map +1 -1
  20. package/jsx/core/MultiStepForm/MultiStepForm.mocks.d.ts +36 -3
  21. package/jsx/core/MultiStepForm/MultiStepForm.mocks.d.ts.map +1 -1
  22. package/jsx/core/MultiStepForm/MultiStepForm.mocks.jsx +294 -39
  23. package/jsx/core/MultiStepForm/MultiStepForm.mocks.jsx.map +1 -1
  24. package/jsx/core/MultiStepForm/MultiStepForm.stories.d.ts +2 -5
  25. package/jsx/core/MultiStepForm/MultiStepForm.stories.d.ts.map +1 -1
  26. package/jsx/core/MultiStepForm/MultiStepForm.stories.jsx +59 -172
  27. package/jsx/core/MultiStepForm/MultiStepForm.stories.jsx.map +1 -1
  28. package/jsx/core/Progress/Progress.mocks.d.ts +2 -0
  29. package/jsx/core/Progress/Progress.mocks.d.ts.map +1 -0
  30. package/jsx/core/Progress/Progress.mocks.js +2 -0
  31. package/jsx/core/Progress/Progress.mocks.js.map +1 -0
  32. package/jsx/core/Progress/Progress.stories.d.ts.map +1 -1
  33. package/jsx/core/Progress/Progress.stories.jsx +2 -2
  34. package/jsx/core/Progress/Progress.stories.jsx.map +1 -1
  35. package/jsx/cs/Article/Article.mocks.js +4 -4
  36. package/jsx/cs/Article/Article.mocks.js.map +1 -1
  37. package/jsx/cs/Article/Article.stories.d.ts +13 -2
  38. package/jsx/cs/Article/Article.stories.d.ts.map +1 -1
  39. package/jsx/cs/Article/Article.stories.jsx +167 -92
  40. package/jsx/cs/Article/Article.stories.jsx.map +1 -1
  41. package/jsx/cs/ArticleList/ArticleList.mocks.d.ts +129 -10
  42. package/jsx/cs/ArticleList/ArticleList.mocks.d.ts.map +1 -1
  43. package/jsx/cs/ArticleList/ArticleList.mocks.js +362 -50
  44. package/jsx/cs/ArticleList/ArticleList.mocks.js.map +1 -1
  45. package/jsx/cs/ArticleList/ArticleList.stories.d.ts +10 -2
  46. package/jsx/cs/ArticleList/ArticleList.stories.d.ts.map +1 -1
  47. package/jsx/cs/ArticleList/ArticleList.stories.jsx +243 -92
  48. package/jsx/cs/ArticleList/ArticleList.stories.jsx.map +1 -1
  49. package/jsx/social/Chat/Chat.mocks.d.ts.map +1 -1
  50. package/jsx/social/Chat/Chat.mocks.js +5 -0
  51. package/jsx/social/Chat/Chat.mocks.js.map +1 -1
  52. package/jsx/social/Chat/Chat.stories.d.ts +5 -1
  53. package/jsx/social/Chat/Chat.stories.d.ts.map +1 -1
  54. package/jsx/social/Chat/Chat.stories.jsx +23 -10
  55. package/jsx/social/Chat/Chat.stories.jsx.map +1 -1
  56. package/jsx/work/Assignments/Assignments.stories.d.ts.map +1 -1
  57. package/jsx/work/Assignments/Assignments.stories.jsx +3 -29
  58. package/jsx/work/Assignments/Assignments.stories.jsx.map +1 -1
  59. package/jsx/work/CaseView/Attachments.mocks.d.ts.map +1 -1
  60. package/jsx/work/CaseView/Attachments.mocks.jsx +62 -60
  61. package/jsx/work/CaseView/Attachments.mocks.jsx.map +1 -1
  62. package/jsx/work/CaseView/CaseView.mocks.d.ts.map +1 -1
  63. package/jsx/work/CaseView/CaseView.mocks.jsx +97 -9
  64. package/jsx/work/CaseView/CaseView.mocks.jsx.map +1 -1
  65. package/jsx/work/CaseView/CaseView.stories.d.ts +2 -2
  66. package/jsx/work/CaseView/CaseView.stories.d.ts.map +1 -1
  67. package/jsx/work/CaseView/CaseView.stories.jsx +2 -2
  68. package/jsx/work/CaseView/CaseView.stories.jsx.map +1 -1
  69. package/jsx/work/CaseView/FileService.mock.d.ts.map +1 -1
  70. package/jsx/work/CaseView/FileService.mock.jsx +2 -6
  71. package/jsx/work/CaseView/FileService.mock.jsx.map +1 -1
  72. package/jsx/work/Tasks/Tasks.stories.d.ts.map +1 -1
  73. package/jsx/work/Tasks/Tasks.stories.jsx +3 -29
  74. package/jsx/work/Tasks/Tasks.stories.jsx.map +1 -1
  75. package/lib/core/AIButton/AIButton.stories.d.ts +5 -1
  76. package/lib/core/AIButton/AIButton.stories.d.ts.map +1 -1
  77. package/lib/core/AIButton/AIButton.stories.js +57 -29
  78. package/lib/core/AIButton/AIButton.stories.js.map +1 -1
  79. package/lib/core/AppShell/AppShell.stories.d.ts.map +1 -1
  80. package/lib/core/AppShell/AppShell.stories.js +9 -21
  81. package/lib/core/AppShell/AppShell.stories.js.map +1 -1
  82. package/lib/core/Banner/Banner.stories.d.ts.map +1 -1
  83. package/lib/core/Banner/Banner.stories.js +17 -11
  84. package/lib/core/Banner/Banner.stories.js.map +1 -1
  85. package/lib/core/Dialog/FormDialog.mocks.d.ts.map +1 -1
  86. package/lib/core/Dialog/FormDialog.mocks.js +4 -2
  87. package/lib/core/Dialog/FormDialog.mocks.js.map +1 -1
  88. package/lib/core/Dialog/InfoDialog.mocks.d.ts.map +1 -1
  89. package/lib/core/Dialog/InfoDialog.mocks.js +2 -1
  90. package/lib/core/Dialog/InfoDialog.mocks.js.map +1 -1
  91. package/lib/core/Modal/Modal.stories.d.ts.map +1 -1
  92. package/lib/core/Modal/Modal.stories.js +2 -1
  93. package/lib/core/Modal/Modal.stories.js.map +1 -1
  94. package/lib/core/MultiStepForm/MultiStepForm.mocks.d.ts +36 -3
  95. package/lib/core/MultiStepForm/MultiStepForm.mocks.d.ts.map +1 -1
  96. package/lib/core/MultiStepForm/MultiStepForm.mocks.js +269 -31
  97. package/lib/core/MultiStepForm/MultiStepForm.mocks.js.map +1 -1
  98. package/lib/core/MultiStepForm/MultiStepForm.stories.d.ts +2 -5
  99. package/lib/core/MultiStepForm/MultiStepForm.stories.d.ts.map +1 -1
  100. package/lib/core/MultiStepForm/MultiStepForm.stories.js +54 -170
  101. package/lib/core/MultiStepForm/MultiStepForm.stories.js.map +1 -1
  102. package/lib/core/Progress/Progress.mocks.d.ts +2 -0
  103. package/lib/core/Progress/Progress.mocks.d.ts.map +1 -0
  104. package/lib/core/Progress/Progress.mocks.js +2 -0
  105. package/lib/core/Progress/Progress.mocks.js.map +1 -0
  106. package/lib/core/Progress/Progress.stories.d.ts.map +1 -1
  107. package/lib/core/Progress/Progress.stories.js +2 -2
  108. package/lib/core/Progress/Progress.stories.js.map +1 -1
  109. package/lib/cs/Article/Article.mocks.js +4 -4
  110. package/lib/cs/Article/Article.mocks.js.map +1 -1
  111. package/lib/cs/Article/Article.stories.d.ts +13 -2
  112. package/lib/cs/Article/Article.stories.d.ts.map +1 -1
  113. package/lib/cs/Article/Article.stories.js +168 -53
  114. package/lib/cs/Article/Article.stories.js.map +1 -1
  115. package/lib/cs/ArticleList/ArticleList.mocks.d.ts +129 -10
  116. package/lib/cs/ArticleList/ArticleList.mocks.d.ts.map +1 -1
  117. package/lib/cs/ArticleList/ArticleList.mocks.js +362 -50
  118. package/lib/cs/ArticleList/ArticleList.mocks.js.map +1 -1
  119. package/lib/cs/ArticleList/ArticleList.stories.d.ts +10 -2
  120. package/lib/cs/ArticleList/ArticleList.stories.d.ts.map +1 -1
  121. package/lib/cs/ArticleList/ArticleList.stories.js +245 -70
  122. package/lib/cs/ArticleList/ArticleList.stories.js.map +1 -1
  123. package/lib/social/Chat/Chat.mocks.d.ts.map +1 -1
  124. package/lib/social/Chat/Chat.mocks.js +5 -0
  125. package/lib/social/Chat/Chat.mocks.js.map +1 -1
  126. package/lib/social/Chat/Chat.stories.d.ts +5 -1
  127. package/lib/social/Chat/Chat.stories.d.ts.map +1 -1
  128. package/lib/social/Chat/Chat.stories.js +23 -12
  129. package/lib/social/Chat/Chat.stories.js.map +1 -1
  130. package/lib/work/Assignments/Assignments.stories.d.ts.map +1 -1
  131. package/lib/work/Assignments/Assignments.stories.js +4 -10
  132. package/lib/work/Assignments/Assignments.stories.js.map +1 -1
  133. package/lib/work/CaseView/Attachments.mocks.d.ts.map +1 -1
  134. package/lib/work/CaseView/Attachments.mocks.js +77 -70
  135. package/lib/work/CaseView/Attachments.mocks.js.map +1 -1
  136. package/lib/work/CaseView/CaseView.mocks.d.ts.map +1 -1
  137. package/lib/work/CaseView/CaseView.mocks.js +61 -9
  138. package/lib/work/CaseView/CaseView.mocks.js.map +1 -1
  139. package/lib/work/CaseView/CaseView.stories.d.ts +2 -2
  140. package/lib/work/CaseView/CaseView.stories.d.ts.map +1 -1
  141. package/lib/work/CaseView/CaseView.stories.js +2 -2
  142. package/lib/work/CaseView/CaseView.stories.js.map +1 -1
  143. package/lib/work/CaseView/FileService.mock.d.ts.map +1 -1
  144. package/lib/work/CaseView/FileService.mock.js +2 -6
  145. package/lib/work/CaseView/FileService.mock.js.map +1 -1
  146. package/lib/work/Tasks/Tasks.stories.d.ts.map +1 -1
  147. package/lib/work/Tasks/Tasks.stories.js +4 -10
  148. package/lib/work/Tasks/Tasks.stories.js.map +1 -1
  149. package/package.json +9 -9
@@ -1,5 +1,23 @@
1
1
  /// <reference types="react" />
2
- export interface DemoFormDataType {
2
+ import { BannerMessage } from '@pega/cosmos-react-core';
3
+ import MultiStepFormProps from '@pega/cosmos-react-core/lib/components/MultiStepForm/MultiStepForm.types';
4
+ export interface MultiStepFormDemoProps {
5
+ heading?: MultiStepFormProps['heading'];
6
+ stepIndicator?: MultiStepFormProps['stepIndicator'];
7
+ }
8
+ export interface ReducerAction {
9
+ type: string;
10
+ payload?: any;
11
+ }
12
+ export interface DemoMultiStepState {
13
+ formData: DemoFormDataType;
14
+ formErrors: DemoFormErrorsType;
15
+ currentStepIndex: number;
16
+ numSteps: number;
17
+ cancelled: boolean;
18
+ finished: boolean;
19
+ }
20
+ interface DemoFormDataType {
3
21
  [key: string]: string | boolean | undefined;
4
22
  firstName?: string;
5
23
  lastName?: string;
@@ -18,8 +36,8 @@ export interface DemoFormDataType {
18
36
  finalRecommendation?: string;
19
37
  recommendationComments?: string;
20
38
  }
21
- export interface DemoFormErrorsType {
22
- [field: string]: string | undefined;
39
+ interface DemoFormErrorsType {
40
+ [field: string]: BannerMessage;
23
41
  }
24
42
  interface MockFormArgs {
25
43
  formData: DemoFormDataType;
@@ -29,9 +47,24 @@ interface MockFormArgs {
29
47
  payload?: any;
30
48
  }) => void;
31
49
  }
50
+ interface FieldData {
51
+ name: string;
52
+ label: string;
53
+ }
54
+ export declare const stepFields: FieldData[][];
55
+ export declare const initialState: DemoMultiStepState;
56
+ export declare const reducer: (state: DemoMultiStepState, action: ReducerAction) => DemoMultiStepState | {
57
+ currentStepIndex: any;
58
+ formErrors: {};
59
+ formData: DemoFormDataType;
60
+ numSteps: number;
61
+ cancelled: boolean;
62
+ finished: boolean;
63
+ };
32
64
  export declare const ApplicantDetailsFields: ({ formData, formErrors, dispatch }: MockFormArgs) => JSX.Element;
33
65
  export declare const InterviewNotesFields: ({ formData, formErrors, dispatch }: MockFormArgs) => JSX.Element;
34
66
  export declare const NextInterviewFields: ({ formData, formErrors, dispatch }: MockFormArgs) => JSX.Element;
35
67
  export declare const RecommendationsFields: ({ formData, formErrors, dispatch }: MockFormArgs) => JSX.Element;
68
+ export declare const MultiStepModal: (args: MultiStepFormDemoProps) => JSX.Element;
36
69
  export {};
37
70
  //# sourceMappingURL=MultiStepForm.mocks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MultiStepForm.mocks.d.ts","sourceRoot":"","sources":["../../../src/core/MultiStepForm/MultiStepForm.mocks.tsx"],"names":[],"mappings":";AAeA,MAAM,WAAW,gBAAgB;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,UAAU,YAAY;IACpB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,UAAU,EAAE,kBAAkB,CAAC;IAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,CAAA;KAAE,KAAK,IAAI,CAAC;CAC5D;AAED,eAAO,MAAM,sBAAsB,uCAAwC,YAAY,gBAuGtF,CAAC;AAEF,eAAO,MAAM,oBAAoB,uCAAwC,YAAY,gBA6BpF,CAAC;AAEF,eAAO,MAAM,mBAAmB,uCAAwC,YAAY,gBAuBnF,CAAC;AAEF,eAAO,MAAM,qBAAqB,uCAAwC,YAAY,gBAkKrF,CAAC"}
1
+ {"version":3,"file":"MultiStepForm.mocks.d.ts","sourceRoot":"","sources":["../../../src/core/MultiStepForm/MultiStepForm.mocks.tsx"],"names":[],"mappings":";AAYA,OAAO,EAGL,aAAa,EAgBd,MAAM,yBAAyB,CAAC;AACjC,OAAO,kBAEN,MAAM,0EAA0E,CAAC;AAIlF,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACxC,aAAa,CAAC,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,UAAU,EAAE,kBAAkB,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAQD,UAAU,gBAAgB;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,UAAU,kBAAkB;IAC1B,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC;CAChC;AAED,UAAU,YAAY;IACpB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,UAAU,EAAE,kBAAkB,CAAC;IAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,CAAA;KAAE,KAAK,IAAI,CAAC;CAC5D;AAED,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,UAAU,EAAE,SAAS,EAAE,EAwBnC,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,kBAY1B,CAAC;AA6BF,eAAO,MAAM,OAAO,UAAW,kBAAkB,UAAU,aAAa;;;cApH5D,gBAAgB;cAGhB,MAAM;eACL,OAAO;cACR,OAAO;CA8MlB,CAAC;AAEF,eAAO,MAAM,sBAAsB,uCAAwC,YAAY,gBAgGtF,CAAC;AAEF,eAAO,MAAM,oBAAoB,uCAAwC,YAAY,gBA2BpF,CAAC;AAEF,eAAO,MAAM,mBAAmB,uCAAwC,YAAY,gBAsBnF,CAAC;AAEF,eAAO,MAAM,qBAAqB,uCAAwC,YAAY,gBAiKrF,CAAC;AAEF,eAAO,MAAM,cAAc,SAAU,sBAAsB,gBA4K1D,CAAC"}
@@ -1,26 +1,179 @@
1
- import { Input, Grid, FieldGroup, TextArea, RadioButtonGroup, RadioButton, CurrencyInput, Select, Option, Checkbox } from '@pega/cosmos-react-core';
1
+ import { useEffect, useMemo, useReducer, useRef, useState } from 'react';
2
+ import { Banner, Button, Checkbox, CurrencyInput, FieldGroup, Grid, Input, Modal, MultiStepForm, Option, RadioButton, RadioButtonGroup, Select, TextArea, useModalContext, useToaster } from '@pega/cosmos-react-core';
3
+ import { loadingTimeoutMS } from '../Progress/Progress.mocks';
4
+ export const stepFields = [
5
+ [
6
+ { name: 'firstName', label: 'First name' },
7
+ { name: 'lastName', label: 'Last name' },
8
+ { name: 'currentTitle', label: 'Current title' },
9
+ { name: 'currentCompany', label: 'Current company' },
10
+ { name: 'salaryRequested', label: 'Salary requested' },
11
+ { name: 'experienceLevel', label: 'Experience level' },
12
+ { name: 'priorityOne', label: 'First' },
13
+ { name: 'priorityTwo', label: 'Second' },
14
+ { name: 'priorityThree', label: 'Third' }
15
+ ],
16
+ [
17
+ { name: 'interviewNotes', label: 'Impressions' },
18
+ { name: 'additionalInterview', label: 'Request additional interview' }
19
+ ],
20
+ [{ name: 'nextInterviewer', label: 'Next interviewer' }],
21
+ [
22
+ { name: 'salaryRequestedReview', label: 'Salary requested' },
23
+ { name: 'salaryRequestReview', label: 'Salary request fit' },
24
+ { name: 'cultureFit', label: 'Culture fit' },
25
+ { name: 'finalRecommendation', label: 'Final recommendation' },
26
+ { name: 'recommendationComments', label: 'Comments' }
27
+ ]
28
+ ];
29
+ export const initialState = {
30
+ currentStepIndex: 0,
31
+ cancelled: false,
32
+ finished: false,
33
+ numSteps: 3,
34
+ formData: {
35
+ firstName: 'Marcus',
36
+ lastName: 'Kennedy',
37
+ currentTitle: 'Data Analyst',
38
+ currentCompany: 'Acme Co.'
39
+ },
40
+ formErrors: {}
41
+ };
42
+ const formValidation = {
43
+ salaryRequested: {
44
+ message: 'This field is required.',
45
+ validator: (value) => value?.length > 0
46
+ },
47
+ experienceLevel: {
48
+ message: 'This field is required.',
49
+ validator: (value) => value?.length > 0
50
+ },
51
+ nextInterviewer: {
52
+ message: 'This field is required.',
53
+ validator: (value) => value?.length > 0
54
+ },
55
+ salaryRequestReview: {
56
+ message: 'This field is required.',
57
+ validator: (value) => value?.length > 0
58
+ },
59
+ cultureFit: {
60
+ message: 'This field is required.',
61
+ validator: (value) => value?.length > 0
62
+ },
63
+ finalRecommendation: {
64
+ message: 'This field is required.',
65
+ validator: (value) => value?.length > 0
66
+ }
67
+ };
68
+ export const reducer = (state, action) => {
69
+ const type = action.type;
70
+ const payload = action.payload;
71
+ switch (type) {
72
+ case 'restart': {
73
+ return initialState;
74
+ }
75
+ case 'cancel': {
76
+ return {
77
+ ...state,
78
+ cancelled: true
79
+ };
80
+ }
81
+ case 'finish': {
82
+ return {
83
+ ...state,
84
+ finished: true
85
+ };
86
+ }
87
+ case 'setStep': {
88
+ return {
89
+ ...state,
90
+ currentStepIndex: payload,
91
+ formErrors: {}
92
+ };
93
+ }
94
+ case 'setFieldValue': {
95
+ const { name: field, label, value } = payload;
96
+ const formData = {
97
+ ...state.formData
98
+ };
99
+ const formErrors = {
100
+ ...state.formErrors
101
+ };
102
+ formData[field] = value;
103
+ if (formErrors[field] && Object.prototype.hasOwnProperty.call(formValidation, field)) {
104
+ const valid = formValidation[field].validator(value);
105
+ if (valid) {
106
+ delete formErrors[field];
107
+ }
108
+ else {
109
+ formErrors[field] = { label, description: formValidation[field].message };
110
+ }
111
+ }
112
+ return {
113
+ ...state,
114
+ formData,
115
+ formErrors
116
+ };
117
+ }
118
+ case 'submitCurrentStep': {
119
+ const stepIndex = state.numSteps === 4 || state.currentStepIndex <= 1
120
+ ? state.currentStepIndex
121
+ : state.currentStepIndex + 1;
122
+ const formErrors = { ...state.formErrors };
123
+ let isValid = true;
124
+ const validateFields = (fields) => {
125
+ if (!fields)
126
+ return;
127
+ fields.forEach(({ name: field, label }) => {
128
+ if (Object.prototype.hasOwnProperty.call(formValidation, field)) {
129
+ const valid = formValidation[field].validator(state.formData[field]);
130
+ if (valid) {
131
+ delete formErrors[field];
132
+ }
133
+ else {
134
+ isValid = false;
135
+ formErrors[field] = { label, description: formValidation[field].message };
136
+ }
137
+ }
138
+ });
139
+ };
140
+ validateFields(stepFields[stepIndex]);
141
+ return {
142
+ ...state,
143
+ numSteps: state.formData.additionalInterview ? 4 : 3,
144
+ currentStepIndex: isValid && state.currentStepIndex !== state.numSteps - 1
145
+ ? state.currentStepIndex + 1
146
+ : state.currentStepIndex,
147
+ finished: isValid && state.currentStepIndex === state.numSteps - 1,
148
+ formErrors
149
+ };
150
+ }
151
+ default:
152
+ return state;
153
+ }
154
+ };
2
155
  export const ApplicantDetailsFields = ({ formData, formErrors, dispatch }) => {
3
156
  return (<Grid container={{ gap: 1, cols: 'repeat(2, minmax(0, 1fr))' }}>
4
- <Input name='firstName' label='First name' value={formData.firstName} readOnly/>
5
- <Input name='lastName' label='Last name' value={formData.lastName} readOnly/>
6
- <Input name='currentTitle' label='Current title' value={formData.currentTitle} onChange={(e) => dispatch({
157
+ <Input {...stepFields[0][0]} value={formData.firstName} readOnly/>
158
+ <Input {...stepFields[0][1]} value={formData.lastName} readOnly/>
159
+ <Input {...stepFields[0][2]} value={formData.currentTitle} onChange={(e) => dispatch({
7
160
  type: 'setFieldValue',
8
- payload: { field: 'currentTitle', value: e.target.value }
161
+ payload: { ...stepFields[0][2], value: e.target.value }
9
162
  })}/>
10
- <Input name='currentCompany' label='Current company' value={formData.currentCompany} onChange={(e) => dispatch({
163
+ <Input {...stepFields[0][3]} value={formData.currentCompany} onChange={(e) => dispatch({
11
164
  type: 'setFieldValue',
12
- payload: { field: 'currentCompany', value: e.target.value }
165
+ payload: { ...stepFields[0][3], value: e.target.value }
13
166
  })}/>
14
- <CurrencyInput name='salaryRequested' label='Salary requested' value={formData.salaryRequested} currencyISOCode='USD' onChange={value => dispatch({
167
+ <CurrencyInput {...stepFields[0][4]} value={formData.salaryRequested} currencyISOCode='USD' onChange={value => dispatch({
15
168
  type: 'setFieldValue',
16
- payload: { field: 'salaryRequested', value }
17
- })} status={formErrors.salaryRequested ? 'error' : undefined} info={formErrors.salaryRequested ? formErrors.salaryRequested : undefined} required/>
18
- <Select id='experienceLevel' label='Weighted experience' value={formData.experienceLevel} onChange={(e) => {
169
+ payload: { ...stepFields[0][4], value }
170
+ })} status={formErrors.salaryRequested ? 'error' : undefined} info={formErrors.salaryRequested ? formErrors.salaryRequested.description : undefined} required/>
171
+ <Select {...stepFields[0][5]} value={formData.experienceLevel} onChange={(e) => {
19
172
  dispatch({
20
173
  type: 'setFieldValue',
21
- payload: { field: 'experienceLevel', value: e.target.value }
174
+ payload: { ...stepFields[0][5], value: e.target.value }
22
175
  });
23
- }} status={formErrors.experienceLevel ? 'error' : undefined} info={formErrors.experienceLevel ? formErrors.experienceLevel : undefined} required>
176
+ }} status={formErrors.experienceLevel ? 'error' : undefined} info={formErrors.experienceLevel ? formErrors.experienceLevel.description : undefined} required>
24
177
  <Option value=''>--</Option>
25
178
  <Option value='junior'>0-3 years (junior)</Option>
26
179
  <Option value='mid-level'>4-6 years (mid)</Option>
@@ -30,22 +183,22 @@ export const ApplicantDetailsFields = ({ formData, formErrors, dispatch }) => {
30
183
  <Grid item={{ colStart: '1', colEnd: '-1' }}>
31
184
  <FieldGroup name='Work priorities' headingTag='h3'>
32
185
  <Grid container={{ gap: 1, cols: 'repeat(3, minmax(0, 1fr))' }}>
33
- <Input name='priorityOne' label='First' value={formData.priorityOne} onChange={(e) => {
186
+ <Input {...stepFields[0][6]} value={formData.priorityOne} onChange={(e) => {
34
187
  dispatch({
35
188
  type: 'setFieldValue',
36
- payload: { field: 'priorityOne', value: e.target.value }
189
+ payload: { ...stepFields[0][6], value: e.target.value }
37
190
  });
38
191
  }}/>
39
- <Input name='priorityTwo' label='Second' value={formData.priorityTwo} onChange={(e) => {
192
+ <Input {...stepFields[0][7]} value={formData.priorityTwo} onChange={(e) => {
40
193
  dispatch({
41
194
  type: 'setFieldValue',
42
- payload: { field: 'priorityTwo', value: e.target.value }
195
+ payload: { ...stepFields[0][7], value: e.target.value }
43
196
  });
44
197
  }}/>
45
- <Input name='priorityThree' label='Third' value={formData.priorityThree} onChange={(e) => {
198
+ <Input {...stepFields[0][8]} value={formData.priorityThree} onChange={(e) => {
46
199
  dispatch({
47
200
  type: 'setFieldValue',
48
- payload: { field: 'priorityThree', value: e.target.value }
201
+ payload: { ...stepFields[0][8], value: e.target.value }
49
202
  });
50
203
  }}/>
51
204
  </Grid>
@@ -55,27 +208,27 @@ export const ApplicantDetailsFields = ({ formData, formErrors, dispatch }) => {
55
208
  };
56
209
  export const InterviewNotesFields = ({ formData, formErrors, dispatch }) => {
57
210
  return (<Grid container={{ gap: 1, cols: '1fr' }}>
58
- <TextArea name='impressions' label='Impressions' value={formData.interviewNotes} onChange={(e) => {
211
+ <TextArea {...stepFields[1][0]} value={formData.interviewNotes} onChange={(e) => {
59
212
  dispatch({
60
213
  type: 'setFieldValue',
61
- payload: { field: 'interviewNotes', value: e.target.value }
214
+ payload: { ...stepFields[1][0], value: e.target.value }
62
215
  });
63
- }} status={formErrors.impressions ? 'error' : undefined} info={formErrors.impressions ? formErrors.impressions : undefined}/>
64
- <Checkbox name='additionalInterview' label='Request additional interview' defaultChecked={formData.additionalInterview} onChange={(e) => {
216
+ }} status={formErrors.impressions ? 'error' : undefined} info={formErrors.impressions ? formErrors.impressions.description : undefined}/>
217
+ <Checkbox {...stepFields[1][1]} defaultChecked={formData.additionalInterview} onChange={(e) => {
65
218
  dispatch({
66
219
  type: 'setFieldValue',
67
- payload: { field: 'additionalInterview', value: e.target.checked }
220
+ payload: { ...stepFields[1][1], value: e.target.checked }
68
221
  });
69
222
  }}/>
70
223
  </Grid>);
71
224
  };
72
225
  export const NextInterviewFields = ({ formData, formErrors, dispatch }) => {
73
- return (<Select name='nextInterviewer' label='Next interviewer' value={formData.nextInterviewer} onChange={(e) => {
226
+ return (<Select {...stepFields[2][0]} value={formData.nextInterviewer} onChange={(e) => {
74
227
  dispatch({
75
228
  type: 'setFieldValue',
76
- payload: { field: 'nextInterviewer', value: e.target.value }
229
+ payload: { ...stepFields[2][0], value: e.target.value }
77
230
  });
78
- }} status={formErrors.nextInterviewer ? 'error' : undefined} info={formErrors.nextInterviewer ? formErrors.nextInterviewer : undefined} required>
231
+ }} status={formErrors.nextInterviewer ? 'error' : undefined} info={formErrors.nextInterviewer ? formErrors.nextInterviewer.description : undefined} required>
79
232
  <Option value=''>Choose an option...</Option>
80
233
  <Option>Myself</Option>
81
234
  <Option>Cindy Turner </Option>
@@ -85,19 +238,19 @@ export const NextInterviewFields = ({ formData, formErrors, dispatch }) => {
85
238
  };
86
239
  export const RecommendationsFields = ({ formData, formErrors, dispatch }) => {
87
240
  return (<Grid container={{ gap: 1, cols: '1fr' }}>
88
- <CurrencyInput name='salaryRequestedReview' label='Salary requested' value={formData.salaryRequested} onChange={() => { }} currencyISOCode='USD' readOnly/>
241
+ <CurrencyInput {...stepFields[3][0]} value={formData.salaryRequested} onChange={() => { }} currencyISOCode='USD' readOnly/>
89
242
 
90
243
  <p>$99,000 is the recommended salary for this position.</p>
91
244
 
92
- <RadioButtonGroup label='Salary request fit' name='salaryRequestReview' onChange={(e) => {
245
+ <RadioButtonGroup {...stepFields[3][1]} onChange={(e) => {
93
246
  dispatch({
94
247
  type: 'setFieldValue',
95
248
  payload: {
96
- field: 'salaryRequestReview',
249
+ ...stepFields[3][1],
97
250
  value: e.target.value
98
251
  }
99
252
  });
100
- }} status={formErrors.salaryRequestReview ? 'error' : undefined} info={formErrors.salaryRequestReview ? formErrors.salaryRequestReview : undefined} inline required>
253
+ }} status={formErrors.salaryRequestReview ? 'error' : undefined} info={formErrors.salaryRequestReview ? formErrors.salaryRequestReview.description : undefined} inline required>
101
254
  <RadioButton label='Very low' id='salaryTargetVeryLow' value='salaryTargetVeryLow' checked={formData.salaryRequestReview === 'salaryTargetVeryLow'}/>
102
255
  <RadioButton label='Low' id='salaryTargetLow' value='salaryTargetLow' checked={formData.salaryRequestReview === 'salaryTargetLow'}/>
103
256
  <RadioButton label='On trend' id='salaryTargetOnTrend' value='salaryTargetOnTrend' checked={formData.salaryRequestReview === 'salaryTargetOnTrend'}/>
@@ -105,15 +258,15 @@ export const RecommendationsFields = ({ formData, formErrors, dispatch }) => {
105
258
  <RadioButton label='Very high' id='salaryTargetVeryHigh' value='salaryTargetVeryHigh' checked={formData.salaryRequestReview === 'salaryTargetVeryHigh'}/>
106
259
  </RadioButtonGroup>
107
260
 
108
- <RadioButtonGroup label='Culture fit' name='cultureFit' onChange={(e) => {
261
+ <RadioButtonGroup {...stepFields[3][2]} onChange={(e) => {
109
262
  dispatch({
110
263
  type: 'setFieldValue',
111
264
  payload: {
112
- field: 'cultureFit',
265
+ ...stepFields[3][2],
113
266
  value: e.target.value
114
267
  }
115
268
  });
116
- }} status={formErrors.cultureFit ? 'error' : undefined} info={formErrors.cultureFit ? formErrors.cultureFit : undefined} inline required>
269
+ }} status={formErrors.cultureFit ? 'error' : undefined} info={formErrors.cultureFit ? formErrors.cultureFit.description : undefined} inline required>
117
270
  <RadioButton label='High risk' id='cultureFitHighRisk' value='cultureFitHighRisk' checked={formData.cultureFit === 'cultureFitHighRisk'}/>
118
271
  <RadioButton label='Signs of risk' id='cultureFitSomeRisk' value='cultureFitSomeRisk' checked={formData.cultureFit === 'cultureFitSomeRisk'}/>
119
272
  <RadioButton label='Indeterminate' id='cultureFitIndeterminate' value='cultureFitIndeterminate' checked={formData.cultureFit === 'cultureFitIndeterminate'}/>
@@ -121,26 +274,128 @@ export const RecommendationsFields = ({ formData, formErrors, dispatch }) => {
121
274
  <RadioButton label='Perfect' id='cultureFitPerfect' value='cultureFitPerfect' checked={formData.cultureFit === 'cultureFitPerfect'}/>
122
275
  </RadioButtonGroup>
123
276
 
124
- <RadioButtonGroup label='Final recomendation' name='finalRecommendation' onChange={(e) => {
277
+ <RadioButtonGroup {...stepFields[3][3]} onChange={(e) => {
125
278
  dispatch({
126
279
  type: 'setFieldValue',
127
280
  payload: {
128
- field: 'finalRecommendation',
281
+ ...stepFields[3][3],
129
282
  value: e.target.value
130
283
  }
131
284
  });
132
- }} status={formErrors.finalRecommendation ? 'error' : undefined} info={formErrors.finalRecommendation ? formErrors.finalRecommendation : undefined} inline required>
285
+ }} status={formErrors.finalRecommendation ? 'error' : undefined} info={formErrors.finalRecommendation ? formErrors.finalRecommendation.description : undefined} inline required>
133
286
  <RadioButton label='Do not recommend' id='doNotRecommend' value='doNotRecommend' checked={formData.finalRecommendation === 'doNotRecommend'}/>
134
287
  <RadioButton label='Indeterminate' id='noRecommendation' value='noRecommendation' checked={formData.finalRecommendation === 'noRecommendation'}/>
135
288
  <RadioButton label='Recommend' id='recommend' value='recommend' checked={formData.finalRecommendation === 'recommend'}/>
136
289
  </RadioButtonGroup>
137
290
 
138
- <TextArea name='comments' label='Comments' value={formData.recommendationComments} onChange={(e) => {
291
+ <TextArea {...stepFields[3][4]} value={formData.recommendationComments} onChange={(e) => {
139
292
  dispatch({
140
293
  type: 'setFieldValue',
141
- payload: { field: 'recommendationComments', value: e.target.value }
294
+ payload: { ...stepFields[3][4], value: e.target.value }
142
295
  });
143
296
  }}/>
144
297
  </Grid>);
145
298
  };
299
+ export const MultiStepModal = (args) => {
300
+ const { dismiss } = useModalContext();
301
+ const { push: pushToaster } = useToaster();
302
+ const [loading, setLoading] = useState(false);
303
+ const [banners, setBanners] = useState();
304
+ const bannerHandleRef = useRef(null);
305
+ const [state, dispatch] = useReducer(reducer, initialState);
306
+ const submitStep = () => {
307
+ setLoading(true);
308
+ setTimeout(() => {
309
+ dispatch({ type: 'submitCurrentStep' });
310
+ setLoading(false);
311
+ }, loadingTimeoutMS);
312
+ };
313
+ useEffect(() => {
314
+ if (banners && bannerHandleRef.current)
315
+ bannerHandleRef.current.focus();
316
+ }, [banners]);
317
+ useEffect(() => {
318
+ const bannerErrors = Object.keys(state.formErrors)
319
+ .filter(errorField => {
320
+ return stepFields[state.currentStepIndex].find(field => field.name === errorField);
321
+ })
322
+ .map(errorField => state.formErrors[errorField]);
323
+ if (bannerErrors.length) {
324
+ setBanners(<Banner messages={bannerErrors} variant='urgent' handle={bannerHandleRef}/>);
325
+ }
326
+ else {
327
+ setBanners(undefined);
328
+ }
329
+ }, [state.currentStepIndex, state.formErrors]);
330
+ const stepActions = useMemo(() => {
331
+ return (<>
332
+ <Button onClick={() => {
333
+ dispatch({ type: 'cancel' });
334
+ dismiss();
335
+ }} disabled={loading}>
336
+ Cancel
337
+ </Button>
338
+ <div>
339
+ {state.currentStepIndex > 0 && (<Button onClick={() => dispatch({ type: 'setStep', payload: state.currentStepIndex - 1 })} disabled={loading}>
340
+ Previous
341
+ </Button>)}
342
+ {state.currentStepIndex !== state.numSteps - 1 && (<Button variant='primary' onClick={submitStep} disabled={loading}>
343
+ Next
344
+ </Button>)}
345
+ {state.currentStepIndex === state.numSteps - 1 && (<Button type='submit' variant='primary' onClick={(e) => {
346
+ e.preventDefault();
347
+ submitStep();
348
+ }} disabled={loading}>
349
+ Finish
350
+ </Button>)}
351
+ </div>
352
+ </>);
353
+ }, [state.currentStepIndex, loading]);
354
+ const stepData = useMemo(() => {
355
+ const steps = [
356
+ {
357
+ id: 'applicant_details',
358
+ name: 'Applicant details - personal information',
359
+ description: 'This applicant has passed initial screening and has been cleared to have an interview scheduled. ' +
360
+ 'Please confirm their details and have a discussion regarding the open position and the company.',
361
+ banners,
362
+ content: (<ApplicantDetailsFields formData={state.formData} formErrors={state.formErrors} dispatch={dispatch}/>)
363
+ },
364
+ {
365
+ id: 'interview_notes',
366
+ name: 'Interview notes',
367
+ banners,
368
+ content: (<InterviewNotesFields formData={state.formData} formErrors={state.formErrors} dispatch={dispatch}/>)
369
+ },
370
+ {
371
+ id: 'recommendations',
372
+ name: 'Final recommendations',
373
+ description: 'Based on your screening call with the applicant please submit your recomendations.',
374
+ banners,
375
+ content: (<RecommendationsFields formData={state.formData} formErrors={state.formErrors} dispatch={dispatch}/>)
376
+ }
377
+ ];
378
+ if (state.numSteps === 4) {
379
+ steps.splice(2, 0, {
380
+ id: 'next_interview',
381
+ name: 'Next interview',
382
+ description: 'Please select an individual to conduct the next interview.',
383
+ banners,
384
+ content: (<NextInterviewFields formData={state.formData} formErrors={state.formErrors} dispatch={dispatch}/>)
385
+ });
386
+ }
387
+ return steps;
388
+ }, [state.formData, state.formErrors, state.currentStepIndex, banners, loading]);
389
+ useEffect(() => {
390
+ if (state.finished) {
391
+ dismiss();
392
+ pushToaster({ content: 'Interview successfully submitted!' });
393
+ }
394
+ }, [state.finished]);
395
+ return (<Modal heading={args.heading} progress={loading
396
+ ? { message: `Submitting ${stepData[state.currentStepIndex].name.toLowerCase()}...` }
397
+ : undefined} actions={stepActions} onRequestDismiss={() => !loading}>
398
+ <MultiStepForm steps={stepData} currentStepId={stepData[state.currentStepIndex].id} stepIndicator={args.stepIndicator}/>
399
+ </Modal>);
400
+ };
146
401
  //# sourceMappingURL=MultiStepForm.mocks.jsx.map