@openmrs/esm-fast-data-entry-app 1.0.1-pre.15 → 1.0.1-pre.159

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 (135) hide show
  1. package/README.md +21 -2
  2. package/dist/101.js +1 -0
  3. package/dist/101.js.map +1 -0
  4. package/dist/132.js +1 -0
  5. package/dist/143.js +1 -0
  6. package/dist/143.js.map +1 -0
  7. package/dist/188.js +1 -0
  8. package/dist/188.js.map +1 -0
  9. package/dist/197.js +1 -0
  10. package/dist/219.js +1 -0
  11. package/dist/219.js.map +1 -0
  12. package/dist/221.js +1 -0
  13. package/dist/221.js.map +1 -0
  14. package/dist/259.js +1 -0
  15. package/dist/259.js.map +1 -0
  16. package/dist/29.js +2 -0
  17. package/dist/29.js.LICENSE.txt +3 -0
  18. package/dist/29.js.map +1 -0
  19. package/dist/300.js +1 -0
  20. package/dist/31.js +2 -0
  21. package/dist/31.js.LICENSE.txt +30 -0
  22. package/dist/31.js.map +1 -0
  23. package/dist/326.js +1 -0
  24. package/dist/326.js.map +1 -0
  25. package/dist/335.js +1 -0
  26. package/dist/367.js +1 -0
  27. package/dist/367.js.map +1 -0
  28. package/dist/480.js +1 -0
  29. package/dist/491.js +1 -0
  30. package/dist/491.js.map +1 -0
  31. package/dist/540.js +2 -0
  32. package/dist/540.js.LICENSE.txt +9 -0
  33. package/dist/540.js.map +1 -0
  34. package/dist/55.js +1 -0
  35. package/dist/564.js +1 -0
  36. package/dist/564.js.map +1 -0
  37. package/dist/602.js +1 -0
  38. package/dist/602.js.map +1 -0
  39. package/dist/626.js +2 -0
  40. package/dist/626.js.LICENSE.txt +9 -0
  41. package/dist/626.js.map +1 -0
  42. package/dist/652.js +1 -0
  43. package/dist/685.js +1 -0
  44. package/dist/685.js.map +1 -0
  45. package/dist/773.js +2 -0
  46. package/dist/773.js.LICENSE.txt +32 -0
  47. package/dist/773.js.map +1 -0
  48. package/dist/91.js +1 -0
  49. package/dist/91.js.map +1 -0
  50. package/dist/961.js +2 -0
  51. package/dist/961.js.LICENSE.txt +19 -0
  52. package/dist/961.js.map +1 -0
  53. package/dist/99.js +1 -0
  54. package/dist/99.js.map +1 -0
  55. package/dist/main.js +1 -0
  56. package/dist/main.js.map +1 -0
  57. package/dist/openmrs-esm-fast-data-entry-app.js +1 -1
  58. package/dist/openmrs-esm-fast-data-entry-app.js.buildmanifest.json +811 -0
  59. package/dist/openmrs-esm-fast-data-entry-app.js.map +1 -0
  60. package/dist/routes.json +1 -0
  61. package/jest.config.json +2 -1
  62. package/package.json +42 -37
  63. package/src/CancelModal.tsx +48 -0
  64. package/src/CompleteModal.tsx +46 -0
  65. package/src/FormBootstrap.tsx +30 -3
  66. package/src/add-group-modal/AddGroupModal.tsx +106 -61
  67. package/src/add-group-modal/styles.scss +7 -3
  68. package/src/config-schema.ts +57 -0
  69. package/src/context/FormWorkflowContext.tsx +13 -1
  70. package/src/context/FormWorkflowReducer.ts +13 -3
  71. package/src/context/GroupFormWorkflowContext.tsx +43 -6
  72. package/src/context/GroupFormWorkflowReducer.ts +154 -10
  73. package/src/declarations.d.ts +4 -0
  74. package/src/empty-state/styles.scss +14 -14
  75. package/src/form-entry-workflow/FormEntryWorkflow.tsx +74 -102
  76. package/src/form-entry-workflow/form-review-card/styles.scss +9 -11
  77. package/src/form-entry-workflow/patient-banner/styles.scss +11 -12
  78. package/src/form-entry-workflow/patient-search-header/PatientSearchHeader.tsx +2 -2
  79. package/src/form-entry-workflow/patient-search-header/styles.scss +13 -10
  80. package/src/form-entry-workflow/styles.scss +13 -14
  81. package/src/form-entry-workflow/workflow-review/WorkflowReview.tsx +5 -3
  82. package/src/form-entry-workflow/workflow-review/styles.scss +0 -4
  83. package/src/forms-page/FormsPage.tsx +10 -5
  84. package/src/forms-page/forms-table/FormsTable.tsx +11 -5
  85. package/src/forms-page/forms-table/styles.scss +4 -5
  86. package/src/forms-page/styles.scss +3 -5
  87. package/src/group-form-entry-workflow/GroupFormEntryWorkflow.tsx +12 -399
  88. package/src/group-form-entry-workflow/GroupSessionWorkspace.tsx +238 -0
  89. package/src/group-form-entry-workflow/SessionDetailsForm.tsx +177 -0
  90. package/src/group-form-entry-workflow/SessionMetaWorkspace.tsx +107 -0
  91. package/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx +144 -0
  92. package/src/group-form-entry-workflow/attendance-table/index.ts +1 -0
  93. package/src/group-form-entry-workflow/configurable-questions/ConfigurableQuestionsSection.tsx +47 -0
  94. package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.tsx +1 -9
  95. package/src/group-form-entry-workflow/group-display-header/styles.scss +20 -20
  96. package/src/group-form-entry-workflow/group-search/CompactGroupSearch.tsx +1 -1
  97. package/src/group-form-entry-workflow/group-search/GroupSearch.tsx +1 -1
  98. package/src/group-form-entry-workflow/group-search/compact-group-result.scss +16 -17
  99. package/src/group-form-entry-workflow/group-search/compact-group-search.scss +7 -8
  100. package/src/group-form-entry-workflow/group-search/group-search.scss +20 -23
  101. package/src/group-form-entry-workflow/group-search-header/GroupSearchHeader.tsx +33 -6
  102. package/src/group-form-entry-workflow/group-search-header/styles.scss +8 -8
  103. package/src/group-form-entry-workflow/styles.scss +15 -17
  104. package/src/hooks/index.ts +8 -1
  105. package/src/hooks/useForm.ts +73 -0
  106. package/src/hooks/useGetAllForms.ts +3 -2
  107. package/src/hooks/useGetEncounter.ts +2 -2
  108. package/src/hooks/useGetPatient.ts +1 -1
  109. package/src/hooks/useGetPatients.ts +34 -0
  110. package/src/hooks/useGetSystemSetting.ts +38 -0
  111. package/src/hooks/usePostEndpoint.ts +10 -4
  112. package/src/hooks/useSearchEndpoint.ts +14 -8
  113. package/src/hooks/useStartVisit.ts +93 -0
  114. package/src/index.ts +13 -65
  115. package/src/patient-card/styles.scss +3 -4
  116. package/src/routes.json +24 -0
  117. package/src/types.ts +20 -0
  118. package/tools/i18next-parser.config.js +93 -0
  119. package/translations/am.json +75 -0
  120. package/translations/ar.json +75 -0
  121. package/translations/en.json +32 -11
  122. package/translations/es.json +75 -0
  123. package/translations/fr.json +75 -0
  124. package/translations/he.json +75 -0
  125. package/translations/km.json +75 -0
  126. package/turbo.json +18 -0
  127. package/.editorconfig +0 -12
  128. package/.eslintignore +0 -2
  129. package/.eslintrc.js +0 -10
  130. package/.husky/pre-push +0 -1
  131. package/.prettierignore +0 -14
  132. package/.tx/config +0 -9
  133. package/.yarn/plugins/@yarnpkg/plugin-version.cjs +0 -550
  134. package/.yarn/versions/c1451405.yml +0 -0
  135. package/src/declarations.d.tsx +0 -2
@@ -60,6 +60,63 @@ export const configSchema = {
60
60
  },
61
61
  _default: ["ICRC Forms", "Distress Scales"],
62
62
  },
63
+ groupSessionConcepts: {
64
+ sessionName: {
65
+ _type: Type.UUID,
66
+ _description: "UUID of concept for Session Name",
67
+ _default: "e2559620-900b-4f66-ae41-0b9c4adfb654",
68
+ },
69
+ sessionDate: {
70
+ _type: Type.UUID,
71
+ _description: "UUID of concept for Session Date",
72
+ _default: "ceaca505-6dff-4940-8a43-8c060a0924d7",
73
+ },
74
+ practitionerName: {
75
+ _type: Type.UUID,
76
+ _description: "UUID of concept for Practitioner Name",
77
+ _default: "f1a2d58c-1a0e-4148-931a-aac224649fdc",
78
+ },
79
+ sessionNotes: {
80
+ _type: Type.UUID,
81
+ _description: "UUID of concept for Session Notes",
82
+ _default: "fa8fedc0-c066-4da3-8dc1-2ad8621fc480",
83
+ },
84
+ cohortId: {
85
+ _type: Type.UUID,
86
+ _description: "UUID of concept for cohort identifier",
87
+ _default: "5461f231-7e59-4be8-93a4-6d49fd13c00a",
88
+ },
89
+ cohortName: {
90
+ _type: Type.UUID,
91
+ _description: "UUID of concept for cohort name",
92
+ _default: "6029f289-92a6-4a68-80f1-3078d0152449",
93
+ },
94
+ sessionUuid: {
95
+ _type: Type.UUID,
96
+ _description: "UUID of concept for session identifier",
97
+ _default: "6a803908-8a5b-4598-adea-19358c83529a",
98
+ },
99
+ },
100
+ specificQuestions: {
101
+ _type: Type.Array,
102
+ _description: "List of specific questions to populate forms.",
103
+ _elements: {
104
+ forms: {
105
+ _type: Type.Array,
106
+ _description: "List of form UUIDs for which the question applies.",
107
+ _elements: {
108
+ _type: Type.UUID,
109
+ },
110
+ _default: [],
111
+ },
112
+ questionId: {
113
+ _type: Type.String,
114
+ _description: "ID of the question.",
115
+ _default: "",
116
+ },
117
+ },
118
+ _default: [],
119
+ },
63
120
  };
64
121
 
65
122
  export type Form = {
@@ -1,6 +1,8 @@
1
1
  import React, { useEffect, useMemo, useReducer } from "react";
2
2
  import reducer from "./FormWorkflowReducer";
3
3
  import { useParams, useLocation } from "react-router-dom";
4
+ import useGetSystemSetting from "../hooks/useGetSystemSetting";
5
+ import { useSession } from "@openmrs/esm-framework";
4
6
  interface ParamTypes {
5
7
  formUuid?: string;
6
8
  }
@@ -30,6 +32,8 @@ export const initialWorkflowState = {
30
32
  activeEncounterUuid: null, // pseudo field from state[activeFormUuid].encounterUuid
31
33
  patientUuids: [], // pseudo field from state[activeFormUuid].patientUuids
32
34
  encounters: {}, // pseudo field from state[activeFormUuid].encounters
35
+ singleSessionVisitTypeUuid: null,
36
+ userUuid: null, // UUID of the user to which this workflow state belongs to
33
37
  };
34
38
 
35
39
  const FormWorkflowContext = React.createContext({
@@ -38,6 +42,7 @@ const FormWorkflowContext = React.createContext({
38
42
  });
39
43
 
40
44
  const FormWorkflowProvider = ({ children }) => {
45
+ const { user } = useSession();
41
46
  const { formUuid } = useParams() as ParamTypes;
42
47
  const activeFormUuid = formUuid.split("&")[0];
43
48
  const { search } = useLocation();
@@ -46,6 +51,11 @@ const FormWorkflowProvider = ({ children }) => {
46
51
  ...initialWorkflowState,
47
52
  ...initialActions,
48
53
  });
54
+ const systemSetting = useGetSystemSetting(
55
+ "@openmrs/esm-fast-data-entry-app.groupSessionVisitTypeUuid"
56
+ );
57
+ const singleSessionVisitTypeUuid =
58
+ systemSetting?.result?.data?.results?.[0]?.value;
49
59
 
50
60
  const actions = useMemo(
51
61
  () => ({
@@ -54,6 +64,7 @@ const FormWorkflowProvider = ({ children }) => {
54
64
  type: "INITIALIZE_WORKFLOW_STATE",
55
65
  activeFormUuid,
56
66
  newPatientUuid,
67
+ userUuid: user.uuid,
57
68
  }),
58
69
  addPatient: (patientUuid) =>
59
70
  dispatch({ type: "ADD_PATIENT", patientUuid }),
@@ -72,7 +83,7 @@ const FormWorkflowProvider = ({ children }) => {
72
83
  destroySession: () => dispatch({ type: "DESTROY_SESSION" }),
73
84
  closeSession: () => dispatch({ type: "CLOSE_SESSION" }),
74
85
  }),
75
- []
86
+ [user]
76
87
  );
77
88
 
78
89
  // if formUuid isn't a part of state yet, grab it from the url params
@@ -103,6 +114,7 @@ const FormWorkflowProvider = ({ children }) => {
103
114
  encounters:
104
115
  state.forms?.[state.activeFormUuid]?.encounters ??
105
116
  initialWorkflowState.encounters,
117
+ singleSessionVisitTypeUuid,
106
118
  }}
107
119
  >
108
120
  {children}
@@ -1,10 +1,13 @@
1
1
  import { navigate } from "@openmrs/esm-framework";
2
2
  import { initialWorkflowState } from "./FormWorkflowContext";
3
3
 
4
- export const fdeWorkflowStorageVersion = "1.0.13";
4
+ export const fdeWorkflowStorageVersion = "1.1.0";
5
5
  export const fdeWorkflowStorageName = "openmrs:fastDataEntryWorkflowState";
6
6
  const persistData = (data) => {
7
- localStorage.setItem(fdeWorkflowStorageName, JSON.stringify(data));
7
+ localStorage.setItem(
8
+ fdeWorkflowStorageName + ":" + data.userUuid,
9
+ JSON.stringify(data)
10
+ );
8
11
  };
9
12
 
10
13
  const initialFormState = {
@@ -18,7 +21,9 @@ const initialFormState = {
18
21
  const reducer = (state, action) => {
19
22
  switch (action.type) {
20
23
  case "INITIALIZE_WORKFLOW_STATE": {
21
- const savedData = localStorage.getItem(fdeWorkflowStorageName);
24
+ const savedData = localStorage.getItem(
25
+ fdeWorkflowStorageName + ":" + action.userUuid
26
+ );
22
27
  const savedDataObject = savedData ? JSON.parse(savedData) : {};
23
28
  let newState: { [key: string]: unknown } = {};
24
29
  const newPatient = action.newPatientUuid
@@ -69,6 +74,7 @@ const reducer = (state, action) => {
69
74
  [action.activeFormUuid]: initialFormState,
70
75
  },
71
76
  activeFormUuid: action.activeFormUuid,
77
+ userUuid: action.userUuid,
72
78
  };
73
79
  }
74
80
  persistData(newState);
@@ -259,6 +265,8 @@ const reducer = (state, action) => {
259
265
  activeFormUuid: null,
260
266
  };
261
267
  persistData(newState);
268
+ //eslint-disable-next-line
269
+ navigate({ to: "${openmrsSpaBase}/forms" });
262
270
  return newState;
263
271
  }
264
272
  case "CLOSE_SESSION": {
@@ -267,6 +275,8 @@ const reducer = (state, action) => {
267
275
  activeFormUuid: null,
268
276
  };
269
277
  persistData(newState);
278
+ //eslint-disable-next-line
279
+ navigate({ to: "${openmrsSpaBase}/forms" });
270
280
  return newState;
271
281
  }
272
282
  default:
@@ -1,7 +1,8 @@
1
1
  import React, { useEffect, useMemo, useReducer } from "react";
2
2
  import reducer from "./GroupFormWorkflowReducer";
3
3
  import { useParams } from "react-router-dom";
4
- import { Type } from "@openmrs/esm-framework";
4
+ import { type Type, useSession } from "@openmrs/esm-framework";
5
+ import useGetSystemSetting from "../hooks/useGetSystemSetting";
5
6
  interface ParamTypes {
6
7
  formUuid?: string;
7
8
  }
@@ -25,9 +26,14 @@ const initialActions = {
25
26
  openPatientSearch: () => undefined,
26
27
  saveEncounter: (encounterUuid: string | number) => undefined,
27
28
  editEncounter: (patientUuid: string | number) => undefined,
28
- submitForNext: () => undefined,
29
+ validateForNext: () => undefined,
30
+ validateForComplete: () => undefined,
31
+ updateVisitUuid: (visitUuid: string) => undefined,
32
+ submitForNext: (nextPatientUuid: string = null) => undefined,
29
33
  submitForReview: () => undefined,
30
34
  submitForComplete: () => undefined,
35
+ addPatientUuid: (patientUuid: string) => undefined,
36
+ removePatientUuid: (patientUuid: string) => undefined,
31
37
  goToReview: () => undefined,
32
38
  destroySession: () => undefined,
33
39
  closeSession: () => undefined,
@@ -42,17 +48,23 @@ export const initialWorkflowState = {
42
48
  // aciveFormUuid
43
49
  workflowState: null, // pseudo field from state[activeFormUuid].workflowState
44
50
  activePatientUuid: null, // pseudo field from state[activeFormUuid].activePatientUuid
45
- activeEncounterUuid: null, // pseudo field from state[activeFormUuid].encounterUuid
51
+ activeEncounterUuid: null, // pseudo field from state[activeFormUuid].activeEncounterUuid
52
+ activeSessionUuid: null, // pseudo field from state[activeFormUuid].activeSessionUuid
53
+ activeVisitUuid: null, // pseudo field from state[activeFormUuid].activeVisitUuid
46
54
  patientUuids: [], // pseudo field from state[activeFormUuid].patientUuids
47
55
  encounters: {}, // pseudo field from state[activeFormUuid].encounters
56
+ visits: {}, // pseudo field from state[activeFormUuid].visits
48
57
  activeGroupUuid: null, // pseudo field from state[activeFormUuid].groupUuid
49
- activeGroupName: null, // pseudo field from state[activeFormUuid].groupname
58
+ activeGroupName: null, // pseudo field from state[activeFormUuid].groupName
59
+ activeGroupMembers: [], // pseudo field from state[activeFormUuid].groupMembers
50
60
  activeSessionMeta: {
51
61
  sessionName: null,
52
62
  practitionerName: null,
53
63
  sessionDate: null,
54
64
  sessionNotes: null,
55
65
  },
66
+ groupVisitTypeUuid: null,
67
+ userUuid: null, // UUID of the user to which this workflow state belongs to
56
68
  };
57
69
 
58
70
  const GroupFormWorkflowContext = React.createContext({
@@ -61,8 +73,13 @@ const GroupFormWorkflowContext = React.createContext({
61
73
  });
62
74
 
63
75
  const GroupFormWorkflowProvider = ({ children }) => {
76
+ const { user } = useSession();
64
77
  const { formUuid } = useParams() as ParamTypes;
65
78
  const activeFormUuid = formUuid.split("&")[0];
79
+ const systemSetting = useGetSystemSetting(
80
+ "@openmrs/esm-fast-data-entry-app.groupSessionVisitTypeUuid"
81
+ );
82
+ const groupVisitTypeUuid = systemSetting?.result?.data?.results?.[0]?.value;
66
83
  const [state, dispatch] = useReducer(reducer, {
67
84
  ...initialWorkflowState,
68
85
  ...initialActions,
@@ -74,17 +91,27 @@ const GroupFormWorkflowProvider = ({ children }) => {
74
91
  dispatch({
75
92
  type: "INITIALIZE_WORKFLOW_STATE",
76
93
  activeFormUuid,
94
+ userUuid: user.uuid,
77
95
  }),
78
96
  setGroup: (group) => dispatch({ type: "SET_GROUP", group }),
79
97
  unsetGroup: () => dispatch({ type: "UNSET_GROUP" }),
80
98
  setSessionMeta: (meta) => dispatch({ type: "SET_SESSION_META", meta }),
99
+ addPatientUuid: (patientUuid) =>
100
+ dispatch({ type: "ADD_PATIENT_UUID", patientUuid }),
101
+ removePatientUuid: (patientUuid) =>
102
+ dispatch({ type: "REMOVE_PATIENT_UUID", patientUuid }),
81
103
  openPatientSearch: () => dispatch({ type: "OPEN_PATIENT_SEARCH" }),
82
104
  saveEncounter: (encounterUuid) =>
83
105
  dispatch({
84
106
  type: "SAVE_ENCOUNTER",
85
107
  encounterUuid,
86
108
  }),
87
- submitForNext: () => dispatch({ type: "SUBMIT_FOR_NEXT" }),
109
+ validateForNext: () => dispatch({ type: "VALIDATE_FOR_NEXT" }),
110
+ validateForComplete: () => dispatch({ type: "VALIDATE_FOR_COMPLETE" }),
111
+ updateVisitUuid: (visitUuid) =>
112
+ dispatch({ type: "UPDATE_VISIT_UUID", visitUuid }),
113
+ submitForNext: (nextPatientUuid) =>
114
+ dispatch({ type: "SUBMIT_FOR_NEXT", nextPatientUuid }),
88
115
  submitForComplete: () => dispatch({ type: "SUBMIT_FOR_COMPLETE" }),
89
116
  editEncounter: (patientUuid) =>
90
117
  dispatch({ type: "EDIT_ENCOUNTER", patientUuid }),
@@ -92,7 +119,7 @@ const GroupFormWorkflowProvider = ({ children }) => {
92
119
  destroySession: () => dispatch({ type: "DESTROY_SESSION" }),
93
120
  closeSession: () => dispatch({ type: "CLOSE_SESSION" }),
94
121
  }),
95
- []
122
+ [user]
96
123
  );
97
124
 
98
125
  // if formUuid isn't a part of state yet, grab it from the url params
@@ -106,17 +133,24 @@ const GroupFormWorkflowProvider = ({ children }) => {
106
133
  return (
107
134
  <GroupFormWorkflowContext.Provider
108
135
  value={{
136
+ groupVisitTypeUuid,
109
137
  ...state,
110
138
  ...actions,
111
139
  workflowState:
112
140
  state.forms?.[state.activeFormUuid]?.workflowState ??
113
141
  initialWorkflowState.workflowState,
142
+ activeSessionUuid:
143
+ state.forms?.[state.activeFormUuid]?.activeSessionUuid ??
144
+ initialWorkflowState.activeSessionUuid,
114
145
  activePatientUuid:
115
146
  state.forms?.[state.activeFormUuid]?.activePatientUuid ??
116
147
  initialWorkflowState.activePatientUuid,
117
148
  activeEncounterUuid:
118
149
  state.forms?.[state.activeFormUuid]?.activeEncounterUuid ??
119
150
  initialWorkflowState.activeEncounterUuid,
151
+ activeVisitUuid:
152
+ state.forms?.[state.activeFormUuid]?.activeVisitUuid ??
153
+ initialWorkflowState.activeVisitUuid,
120
154
  patientUuids:
121
155
  state.forms?.[state.activeFormUuid]?.patientUuids ??
122
156
  initialWorkflowState.patientUuids,
@@ -129,6 +163,9 @@ const GroupFormWorkflowProvider = ({ children }) => {
129
163
  activeGroupName:
130
164
  state.forms?.[state.activeFormUuid]?.groupName ??
131
165
  initialWorkflowState.activeGroupName,
166
+ activeGroupMembers:
167
+ state.forms?.[state.activeFormUuid]?.groupMembers ??
168
+ initialWorkflowState.activeGroupMembers,
132
169
  activeSessionMeta:
133
170
  state.forms?.[state.activeFormUuid]?.sessionMeta ??
134
171
  initialWorkflowState.activeSessionMeta,
@@ -1,27 +1,37 @@
1
1
  import { navigate } from "@openmrs/esm-framework";
2
2
  import { initialWorkflowState } from "./FormWorkflowContext";
3
+ import { v4 as uuid } from "uuid";
3
4
 
4
5
  export const fdeGroupWorkflowStorageVersion = "1.0.5";
5
6
  export const fdeGroupWorkflowStorageName =
6
7
  "openmrs:fastDataEntryGroupWorkflowState";
7
8
  const persistData = (data) => {
8
- localStorage.setItem(fdeGroupWorkflowStorageName, JSON.stringify(data));
9
+ localStorage.setItem(
10
+ fdeGroupWorkflowStorageName + ":" + data.userUuid,
11
+ JSON.stringify(data)
12
+ );
9
13
  };
10
14
 
11
15
  const initialFormState = {
12
16
  workflowState: "NEW_GROUP_SESSION",
13
17
  groupUuid: null,
14
18
  groupName: null,
19
+ groupMembers: [],
15
20
  activePatientUuid: null,
16
21
  activeEncounterUuid: null,
22
+ activeVisitUuid: null,
23
+ activeSessionUuid: null,
17
24
  patientUuids: [],
18
25
  encounters: {},
26
+ visits: {},
19
27
  };
20
28
 
21
29
  const reducer = (state, action) => {
22
30
  switch (action.type) {
23
31
  case "INITIALIZE_WORKFLOW_STATE": {
24
- const savedData = localStorage.getItem(fdeGroupWorkflowStorageName);
32
+ const savedData = localStorage.getItem(
33
+ fdeGroupWorkflowStorageName + ":" + action.userUuid
34
+ );
25
35
  const savedDataObject = savedData ? JSON.parse(savedData) : {};
26
36
  let newState: { [key: string]: unknown } = {};
27
37
  if (
@@ -37,6 +47,7 @@ const reducer = (state, action) => {
37
47
  thisSavedForm?.patientUuids?.[0] ||
38
48
  // something probably went wrong...
39
49
  null;
50
+ const activeSessionUuid = thisSavedForm?.activeSessionUuid || uuid();
40
51
  newState = {
41
52
  ...savedDataObject,
42
53
  // set current form to this one
@@ -50,6 +61,9 @@ const reducer = (state, action) => {
50
61
  activePatientUuid: activePatientUuid,
51
62
  activeEncounterUuid:
52
63
  thisSavedForm?.encounters?.[activePatientUuid] || null,
64
+ activeVisitUuid:
65
+ thisSavedForm?.visits?.[activePatientUuid] || null,
66
+ activeSessionUuid: activeSessionUuid,
53
67
  },
54
68
  },
55
69
  };
@@ -62,6 +76,7 @@ const reducer = (state, action) => {
62
76
  [action.activeFormUuid]: initialFormState,
63
77
  },
64
78
  activeFormUuid: action.activeFormUuid,
79
+ userUuid: action.userUuid,
65
80
  };
66
81
  }
67
82
  persistData(newState);
@@ -84,8 +99,14 @@ const reducer = (state, action) => {
84
99
  action.group.cohortMembers?.map(
85
100
  (member) => member?.patient?.uuid
86
101
  ) ?? [],
102
+ groupMembers:
103
+ action.group.cohortMembers?.map(
104
+ (member) => member?.patient?.uuid
105
+ ) ?? [],
87
106
  activePatientUuid: null,
88
107
  activeEncounterUuid: null,
108
+ activeVisitUuid: null,
109
+ activeSessionUuid: null,
89
110
  },
90
111
  },
91
112
  };
@@ -102,8 +123,11 @@ const reducer = (state, action) => {
102
123
  groupUuid: null,
103
124
  groupName: null,
104
125
  patientUuids: [],
126
+ groupMembers: [],
105
127
  activePatientUuid: null,
106
128
  activeEncounterUuid: null,
129
+ activeVisitUuid: null,
130
+ activeSessionUuid: null,
107
131
  },
108
132
  },
109
133
  };
@@ -125,6 +149,11 @@ const reducer = (state, action) => {
125
149
  state.forms[state.activeFormUuid].encounters[
126
150
  state.forms[state.activeFormUuid].patientUuids?.[0]
127
151
  ] || null,
152
+ activeVisitUuid:
153
+ state.forms[state.activeFormUuid].visits[
154
+ state.forms[state.activeFormUuid].patientUuids?.[0]
155
+ ] || null,
156
+ activeSessionUuid: uuid(),
128
157
  workflowState: "EDIT_FORM",
129
158
  },
130
159
  },
@@ -132,7 +161,47 @@ const reducer = (state, action) => {
132
161
  persistData(newState);
133
162
  return newState;
134
163
  }
164
+ case "ADD_PATIENT_UUID": {
165
+ if (
166
+ state.forms[state.activeFormUuid].patientUuids.includes(
167
+ action.patientUuid
168
+ )
169
+ ) {
170
+ return state;
171
+ }
135
172
 
173
+ const newState = {
174
+ ...state,
175
+ forms: {
176
+ ...state.forms,
177
+ [state.activeFormUuid]: {
178
+ ...state.forms[state.activeFormUuid],
179
+ patientUuids: [
180
+ ...state.forms[state.activeFormUuid].patientUuids,
181
+ action.patientUuid,
182
+ ],
183
+ },
184
+ },
185
+ };
186
+ persistData(newState);
187
+ return newState;
188
+ }
189
+ case "REMOVE_PATIENT_UUID": {
190
+ const newState = {
191
+ ...state,
192
+ forms: {
193
+ ...state.forms,
194
+ [state.activeFormUuid]: {
195
+ ...state.forms[state.activeFormUuid],
196
+ patientUuids: state.forms[
197
+ state.activeFormUuid
198
+ ].patientUuids?.filter((uuid) => action.patientUuid !== uuid),
199
+ },
200
+ },
201
+ };
202
+ persistData(newState);
203
+ return newState;
204
+ }
136
205
  case "SAVE_ENCOUNTER": {
137
206
  const thisForm = state.forms[state.activeFormUuid];
138
207
  if (thisForm.workflowState === "SUBMIT_FOR_COMPLETE") {
@@ -147,13 +216,14 @@ const reducer = (state, action) => {
147
216
  navigate({ to: "${openmrsSpaBase}/forms" });
148
217
  return newState;
149
218
  } else if (thisForm.workflowState === "SUBMIT_FOR_NEXT") {
150
- const nextPatientUuid =
151
- thisForm.patientUuids[
152
- Math.min(
153
- thisForm.patientUuids.indexOf(thisForm.activePatientUuid) + 1,
154
- thisForm.patientUuids.length - 1
155
- )
156
- ];
219
+ const nextPatientUuid = state.nextPatientUuid
220
+ ? state.nextPatientUuid
221
+ : thisForm.patientUuids[
222
+ Math.min(
223
+ thisForm.patientUuids.indexOf(thisForm.activePatientUuid) + 1,
224
+ thisForm.patientUuids.length - 1
225
+ )
226
+ ];
157
227
  const newState = {
158
228
  ...state,
159
229
  forms: {
@@ -166,6 +236,8 @@ const reducer = (state, action) => {
166
236
  },
167
237
  activePatientUuid: nextPatientUuid,
168
238
  activeEncounterUuid: thisForm.encounters[nextPatientUuid] || null,
239
+ activeVisitUuid: thisForm.visits[nextPatientUuid] || null,
240
+ activeSessionUuid: thisForm.activeSessionUuid,
169
241
  workflowState: "EDIT_FORM",
170
242
  },
171
243
  },
@@ -183,7 +255,10 @@ const reducer = (state, action) => {
183
255
  ...state.forms[state.activeFormUuid],
184
256
  activeEncounterUuid:
185
257
  state.forms[state.activeFormUuid].encounters[action.patientUuid],
258
+ activeVisitUuid:
259
+ state.forms[state.activeFormUuid].visits[action.patientUuid],
186
260
  activePatientUuid: action.patientUuid,
261
+ activeSessionUuid: action.activeSessionUuid,
187
262
  workflowState: "EDIT_FORM",
188
263
  },
189
264
  },
@@ -191,6 +266,46 @@ const reducer = (state, action) => {
191
266
  persistData(newState);
192
267
  return newState;
193
268
  }
269
+ case "VALIDATE_FOR_NEXT":
270
+ // this state should not be persisted
271
+ window.dispatchEvent(
272
+ new CustomEvent("ampath-form-action", {
273
+ detail: {
274
+ formUuid: state.activeFormUuid,
275
+ patientUuid: state.forms[state.activeFormUuid].activePatientUuid,
276
+ action: "validateForm",
277
+ },
278
+ })
279
+ );
280
+ return {
281
+ ...state,
282
+ forms: {
283
+ ...state.forms,
284
+ [state.activeFormUuid]: {
285
+ ...state.forms[state.activeFormUuid],
286
+ workflowState: "VALIDATE_FOR_NEXT",
287
+ },
288
+ },
289
+ };
290
+ case "UPDATE_VISIT_UUID":
291
+ // this state should not be persisted
292
+ // we don't pers
293
+ return {
294
+ ...state,
295
+ forms: {
296
+ ...state.forms,
297
+ [state.activeFormUuid]: {
298
+ ...state.forms[state.activeFormUuid],
299
+ visits: {
300
+ ...state.forms[state.activeFormUuid].visits,
301
+ [state.forms[state.activeFormUuid].activePatientUuid]:
302
+ action.visitUuid,
303
+ },
304
+ activeVisitUuid: action.visitUuid,
305
+ },
306
+ },
307
+ };
308
+
194
309
  case "SUBMIT_FOR_NEXT":
195
310
  // this state should not be persisted
196
311
  window.dispatchEvent(
@@ -211,6 +326,7 @@ const reducer = (state, action) => {
211
326
  workflowState: "SUBMIT_FOR_NEXT",
212
327
  },
213
328
  },
329
+ nextPatientUuid: action.nextPatientUuid,
214
330
  };
215
331
  case "SUBMIT_FOR_REVIEW":
216
332
  // this state should not be persisted
@@ -233,6 +349,28 @@ const reducer = (state, action) => {
233
349
  },
234
350
  },
235
351
  };
352
+
353
+ case "VALIDATE_FOR_COMPLETE":
354
+ // this state should not be persisted
355
+ window.dispatchEvent(
356
+ new CustomEvent("ampath-form-action", {
357
+ detail: {
358
+ formUuid: state.activeFormUuid,
359
+ patientUuid: state.forms[state.activeFormUuid].activePatientUuid,
360
+ action: "validateForm",
361
+ },
362
+ })
363
+ );
364
+ return {
365
+ ...state,
366
+ forms: {
367
+ ...state.forms,
368
+ [state.activeFormUuid]: {
369
+ ...state.forms[state.activeFormUuid],
370
+ workflowState: "VALIDATE_FOR_COMPLETE",
371
+ },
372
+ },
373
+ };
236
374
  case "SUBMIT_FOR_COMPLETE":
237
375
  // this state should not be persisted
238
376
  window.dispatchEvent(
@@ -262,7 +400,9 @@ const reducer = (state, action) => {
262
400
  [state.activeFormUuid]: {
263
401
  ...state.forms[state.activeFormUuid],
264
402
  activeEncounterUuid: null,
403
+ activVisitUuid: null,
265
404
  activePatientUuid: null,
405
+ activeSessionUuid: null,
266
406
  workflowState: "REVIEW",
267
407
  },
268
408
  },
@@ -278,7 +418,9 @@ const reducer = (state, action) => {
278
418
  activeFormUuid: null,
279
419
  };
280
420
  persistData(newState);
281
- return newState;
421
+ //eslint-disable-next-line
422
+ navigate({ to: "${openmrsSpaBase}/forms" });
423
+ return { ...newState, formDestroyed: true };
282
424
  }
283
425
  case "CLOSE_SESSION": {
284
426
  const newState = {
@@ -286,6 +428,8 @@ const reducer = (state, action) => {
286
428
  activeFormUuid: null,
287
429
  };
288
430
  persistData(newState);
431
+ //eslint-disable-next-line
432
+ navigate({ to: "${openmrsSpaBase}/forms" });
289
433
  return newState;
290
434
  }
291
435
  default:
@@ -0,0 +1,4 @@
1
+ declare module "@carbon/react";
2
+ declare module "*.css";
3
+ declare module "*.scss";
4
+ declare type SideNavProps = object;
@@ -1,36 +1,36 @@
1
- @import "~@openmrs/esm-styleguide/src/vars";
2
- @import "~carbon-components/src/globals/scss/vars";
3
- @import "~carbon-components/src/globals/scss/mixins";
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+ @use '@carbon/type';
4
4
 
5
5
  .action {
6
- margin-bottom: $spacing-03;
6
+ margin-bottom: layout.$spacing-03;
7
7
  }
8
8
 
9
9
  .content {
10
- @include carbon--type-style("productive-heading-01");
11
- color: $text-02;
12
- margin-top: $spacing-05;
13
- margin-bottom: $spacing-03;
10
+ @include type.type-style("heading-compact-01");
11
+ color: colors.$gray-70;
12
+ margin-top: layout.$spacing-05;
13
+ margin-bottom: layout.$spacing-03;
14
14
  }
15
15
 
16
16
  .desktopHeading {
17
17
  h4 {
18
- @include carbon--type-style('productive-heading-02');
19
- color: $text-02;
18
+ @include type.type-style('heading-compact-02');
19
+ color: colors.$gray-70;
20
20
  }
21
21
  }
22
22
 
23
23
  .tabletHeading {
24
24
  h4 {
25
- @include carbon--type-style('productive-heading-03');
26
- color: $text-02;
25
+ @include type.type-style('heading-03');
26
+ color: colors.$gray-70;
27
27
  }
28
28
  }
29
29
 
30
30
  .desktopHeading, .tabletHeading {
31
31
  text-align: left;
32
32
  text-transform: capitalize;
33
- margin-bottom: $spacing-05;
33
+ margin-bottom: layout.$spacing-05;
34
34
 
35
35
  h4:after {
36
36
  content: "";
@@ -51,5 +51,5 @@
51
51
 
52
52
  .tile {
53
53
  text-align: center;
54
- border: 1px solid $ui-03;
54
+ border: 1px solid colors.$gray-20;
55
55
  }