@openmrs/esm-fast-data-entry-app 1.0.1-pre.99 → 1.1.0

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 (190) hide show
  1. package/__mocks__/react-i18next.js +9 -14
  2. package/dist/12.js +1 -0
  3. package/dist/12.js.map +1 -0
  4. package/dist/132.js +1 -0
  5. package/dist/151.js +2 -0
  6. package/dist/151.js.map +1 -0
  7. package/dist/195.js +1 -0
  8. package/dist/195.js.map +1 -0
  9. package/dist/197.js +1 -0
  10. package/dist/221.js +1 -0
  11. package/dist/221.js.map +1 -0
  12. package/dist/259.js +1 -0
  13. package/dist/259.js.map +1 -0
  14. package/dist/265.js +1 -0
  15. package/dist/265.js.map +1 -0
  16. package/dist/269.js +1 -0
  17. package/dist/269.js.map +1 -0
  18. package/dist/{574.js → 300.js} +1 -1
  19. package/dist/335.js +1 -0
  20. package/dist/367.js +1 -0
  21. package/dist/367.js.map +1 -0
  22. package/dist/384.js +1 -0
  23. package/dist/384.js.map +1 -0
  24. package/dist/{294.js → 540.js} +2 -2
  25. package/dist/{294.js.map → 540.js.map} +1 -1
  26. package/dist/55.js +1 -0
  27. package/dist/579.js +1 -0
  28. package/dist/579.js.map +1 -0
  29. package/dist/595.js +2 -0
  30. package/dist/{409.js.LICENSE.txt → 595.js.LICENSE.txt} +14 -6
  31. package/dist/595.js.map +1 -0
  32. package/dist/602.js +1 -0
  33. package/dist/602.js.map +1 -0
  34. package/dist/616.js +1 -0
  35. package/dist/616.js.map +1 -0
  36. package/dist/626.js +2 -0
  37. package/dist/626.js.map +1 -0
  38. package/dist/652.js +1 -0
  39. package/dist/77.js +1 -0
  40. package/dist/77.js.map +1 -0
  41. package/dist/773.js +2 -0
  42. package/dist/{897.js.LICENSE.txt → 773.js.LICENSE.txt} +13 -2
  43. package/dist/773.js.map +1 -0
  44. package/dist/88.js +1 -0
  45. package/dist/88.js.map +1 -0
  46. package/dist/930.js +1 -0
  47. package/dist/930.js.map +1 -0
  48. package/dist/961.js +2 -0
  49. package/dist/961.js.map +1 -0
  50. package/dist/983.js +1 -0
  51. package/dist/983.js.map +1 -0
  52. package/dist/99.js +1 -0
  53. package/dist/main.js +1 -1
  54. package/dist/main.js.map +1 -1
  55. package/dist/openmrs-esm-fast-data-entry-app.js +1 -1
  56. package/dist/openmrs-esm-fast-data-entry-app.js.buildmanifest.json +386 -154
  57. package/dist/openmrs-esm-fast-data-entry-app.js.map +1 -1
  58. package/dist/routes.json +1 -1
  59. package/jest.config.json +2 -1
  60. package/package.json +39 -36
  61. package/prettier.config.js +8 -0
  62. package/src/CancelModal.tsx +9 -15
  63. package/src/CompleteModal.tsx +7 -18
  64. package/src/FormBootstrap.tsx +31 -18
  65. package/src/Root.tsx +7 -12
  66. package/src/add-group-modal/AddGroupModal.tsx +73 -112
  67. package/src/add-group-modal/styles.scss +7 -3
  68. package/src/config-schema.ts +63 -24
  69. package/src/constant.ts +1 -1
  70. package/src/context/FormWorkflowContext.tsx +26 -39
  71. package/src/context/FormWorkflowReducer.ts +50 -74
  72. package/src/context/GroupFormWorkflowContext.tsx +40 -59
  73. package/src/context/GroupFormWorkflowReducer.ts +84 -109
  74. package/src/declarations.d.ts +3 -0
  75. package/src/empty-state/EmptyDataIllustration.tsx +4 -16
  76. package/src/empty-state/EmptyState.tsx +8 -13
  77. package/src/empty-state/styles.scss +14 -14
  78. package/src/form-entry-workflow/FormEntryWorkflow.tsx +43 -55
  79. package/src/form-entry-workflow/form-review-card/FormReviewCard.tsx +7 -7
  80. package/src/form-entry-workflow/form-review-card/index.ts +1 -1
  81. package/src/form-entry-workflow/form-review-card/styles.scss +9 -11
  82. package/src/form-entry-workflow/index.ts +1 -1
  83. package/src/form-entry-workflow/patient-banner/PatientBanner.test.tsx +5 -5
  84. package/src/form-entry-workflow/patient-banner/PatientBanner.tsx +14 -27
  85. package/src/form-entry-workflow/patient-banner/index.ts +1 -1
  86. package/src/form-entry-workflow/patient-banner/styles.scss +11 -12
  87. package/src/form-entry-workflow/patient-search-header/PatientSearchHeader.tsx +19 -28
  88. package/src/form-entry-workflow/patient-search-header/index.ts +1 -1
  89. package/src/form-entry-workflow/patient-search-header/styles.scss +13 -10
  90. package/src/form-entry-workflow/styles.scss +11 -13
  91. package/src/form-entry-workflow/workflow-review/WorkflowReview.tsx +13 -11
  92. package/src/form-entry-workflow/workflow-review/index.ts +1 -1
  93. package/src/form-entry-workflow/workflow-review/styles.scss +0 -4
  94. package/src/forms-app-menu-link.tsx +4 -6
  95. package/src/forms-page/FormsPage.tsx +23 -51
  96. package/src/forms-page/forms-table/FormsTable.tsx +22 -42
  97. package/src/forms-page/forms-table/index.ts +1 -1
  98. package/src/forms-page/forms-table/styles.scss +4 -5
  99. package/src/forms-page/index.ts +1 -1
  100. package/src/forms-page/styles.scss +3 -5
  101. package/src/group-form-entry-workflow/GroupFormEntryWorkflow.tsx +9 -9
  102. package/src/group-form-entry-workflow/GroupSessionWorkspace.tsx +77 -117
  103. package/src/group-form-entry-workflow/SessionDetailsForm.tsx +73 -50
  104. package/src/group-form-entry-workflow/SessionMetaWorkspace.tsx +20 -28
  105. package/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx +15 -29
  106. package/src/group-form-entry-workflow/attendance-table/index.ts +1 -1
  107. package/src/group-form-entry-workflow/configurable-questions/ConfigurableQuestionsSection.tsx +45 -0
  108. package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.test.tsx +5 -5
  109. package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.tsx +13 -21
  110. package/src/group-form-entry-workflow/group-display-header/index.ts +1 -1
  111. package/src/group-form-entry-workflow/group-display-header/styles.scss +20 -20
  112. package/src/group-form-entry-workflow/group-search/CompactGroupResults.tsx +24 -35
  113. package/src/group-form-entry-workflow/group-search/CompactGroupSearch.tsx +13 -15
  114. package/src/group-form-entry-workflow/group-search/GroupSearch.tsx +22 -38
  115. package/src/group-form-entry-workflow/group-search/compact-group-result.scss +16 -17
  116. package/src/group-form-entry-workflow/group-search/compact-group-search.scss +7 -8
  117. package/src/group-form-entry-workflow/group-search/group-search.scss +20 -23
  118. package/src/group-form-entry-workflow/group-search-header/GroupSearchHeader.tsx +20 -21
  119. package/src/group-form-entry-workflow/group-search-header/index.ts +1 -1
  120. package/src/group-form-entry-workflow/group-search-header/styles.scss +8 -8
  121. package/src/group-form-entry-workflow/index.ts +1 -1
  122. package/src/group-form-entry-workflow/styles.scss +13 -16
  123. package/src/hooks/index.ts +7 -6
  124. package/src/hooks/useFormState.ts +3 -3
  125. package/src/hooks/useGetAllForms.ts +7 -15
  126. package/src/hooks/useGetEncounter.ts +3 -3
  127. package/src/hooks/useGetPatient.ts +2 -2
  128. package/src/hooks/useGetPatients.ts +4 -6
  129. package/src/hooks/useGetSystemSetting.ts +3 -5
  130. package/src/hooks/useKeyPress.ts +5 -5
  131. package/src/hooks/usePostEndpoint.ts +10 -10
  132. package/src/hooks/useSearchEndpoint.ts +23 -40
  133. package/src/hooks/useSpecificQuestions.ts +75 -0
  134. package/src/hooks/useStartVisit.ts +18 -28
  135. package/src/index.ts +8 -20
  136. package/src/patient-card/PatientCard.tsx +8 -20
  137. package/src/patient-card/index.ts +1 -1
  138. package/src/patient-card/styles.scss +2 -4
  139. package/src/routes.json +2 -2
  140. package/src/setup-tests.ts +1 -1
  141. package/src/types.ts +25 -0
  142. package/tools/i18next-parser.config.js +19 -19
  143. package/translations/am.json +75 -0
  144. package/translations/ar.json +75 -0
  145. package/translations/en.json +7 -1
  146. package/translations/es.json +75 -0
  147. package/translations/fr.json +33 -8
  148. package/translations/he.json +75 -0
  149. package/translations/km.json +75 -0
  150. package/tsconfig.json +2 -1
  151. package/turbo.json +18 -0
  152. package/webpack.config.js +1 -1
  153. package/dist/136.js +0 -1
  154. package/dist/136.js.map +0 -1
  155. package/dist/141.js +0 -2
  156. package/dist/141.js.map +0 -1
  157. package/dist/233.js +0 -2
  158. package/dist/233.js.map +0 -1
  159. package/dist/242.js +0 -1
  160. package/dist/242.js.map +0 -1
  161. package/dist/327.js +0 -1
  162. package/dist/327.js.map +0 -1
  163. package/dist/387.js +0 -1
  164. package/dist/387.js.map +0 -1
  165. package/dist/405.js +0 -1
  166. package/dist/405.js.map +0 -1
  167. package/dist/409.js +0 -2
  168. package/dist/409.js.map +0 -1
  169. package/dist/431.js +0 -1
  170. package/dist/431.js.map +0 -1
  171. package/dist/559.js +0 -1
  172. package/dist/559.js.map +0 -1
  173. package/dist/757.js +0 -1
  174. package/dist/820.js +0 -1
  175. package/dist/820.js.map +0 -1
  176. package/dist/846.js +0 -1
  177. package/dist/846.js.map +0 -1
  178. package/dist/885.js +0 -1
  179. package/dist/885.js.map +0 -1
  180. package/dist/897.js +0 -2
  181. package/dist/897.js.map +0 -1
  182. package/dist/92.js +0 -1
  183. package/dist/92.js.map +0 -1
  184. package/dist/935.js +0 -2
  185. package/dist/935.js.map +0 -1
  186. package/src/declarations.d.tsx +0 -2
  187. /package/dist/{141.js.LICENSE.txt → 151.js.LICENSE.txt} +0 -0
  188. /package/dist/{294.js.LICENSE.txt → 540.js.LICENSE.txt} +0 -0
  189. /package/dist/{233.js.LICENSE.txt → 626.js.LICENSE.txt} +0 -0
  190. /package/dist/{935.js.LICENSE.txt → 961.js.LICENSE.txt} +0 -0
@@ -1,13 +1,11 @@
1
- @use '@carbon/styles/scss/spacing';
2
1
  @use '@carbon/colors';
3
- @use '@carbon/styles/scss/type';
4
- @import '~@openmrs/esm-styleguide/src/vars';
5
-
2
+ @use '@carbon/layout';
3
+ @use '@carbon/type';
6
4
 
7
5
  .breadcrumbsContainer > div > div > nav {
8
- background-color: $ui-02;
9
- padding: spacing.$spacing-04 spacing.$spacing-05;
10
- height: spacing.$spacing-08;
6
+ background-color: colors.$white-0;
7
+ padding: layout.$spacing-04 layout.$spacing-05;
8
+ height: layout.$spacing-08;
11
9
  }
12
10
 
13
11
  .workspaceWrapper {
@@ -26,20 +24,20 @@
26
24
  :global(.omrs-breakpoint-lt-small-desktop) .workspace {
27
25
  // there's only so much we can do here. Currenlty the design does not support tablet
28
26
  width: 100vw;
29
- padding: 0 spacing.$spacing-04;
27
+ padding: 0 layout.$spacing-04;
30
28
  }
31
29
 
32
30
  .selectPatientMessage {
33
- @include type.type-style('productive-heading-03');
34
- margin: spacing.$spacing-07;
31
+ @include type.type-style('heading-03');
32
+ margin: layout.$spacing-07;
35
33
  text-align: center;
36
34
  }
37
35
 
38
36
  .formMainContent {
39
37
  display: flex;
40
38
  text-align: center;
41
- margin-top: spacing.$spacing-05;
42
- column-gap: spacing.$spacing-05;
39
+ margin-top: layout.$spacing-05;
40
+ column-gap: layout.$spacing-05;
43
41
  }
44
42
 
45
43
  .formContainer {
@@ -59,18 +57,18 @@
59
57
  overflow-y: scroll;
60
58
  display: flex;
61
59
  flex-direction: column;
62
- row-gap: spacing.$spacing-05;
60
+ row-gap: layout.$spacing-05;
63
61
  }
64
62
 
65
63
  .patientCardsSection {
66
- margin: spacing.$spacing-05 0;
64
+ margin: layout.$spacing-05 0;
67
65
  border-bottom: 1px solid colors.$gray-10;
68
66
  }
69
67
 
70
68
  .rightPanelActionButtons {
71
69
  display: flex;
72
70
  flex-direction: column;
73
- row-gap: spacing.$spacing-03;
71
+ row-gap: layout.$spacing-03;
74
72
  & button {
75
73
  width: 100%;
76
74
  text-decoration: "none";
@@ -90,7 +88,6 @@
90
88
  width: 500px;
91
89
  }
92
90
 
93
-
94
91
  .formError {
95
92
  @include type.type-style("helper-text-02");
96
93
  color: colors.$red-60;
@@ -1,7 +1,8 @@
1
- import useGetAllForms from "./useGetAllForms";
2
- import useGetPatient from "./useGetPatient";
3
- import useFormState from "./useFormState";
4
- import useGetEncounter from "./useGetEncounter";
1
+ import useGetAllForms from './useGetAllForms';
2
+ import useGetPatient from './useGetPatient';
3
+ import useFormState from './useFormState';
4
+ import useGetEncounter from './useGetEncounter';
5
+ import useSpecificQuestions from './useSpecificQuestions';
5
6
 
6
- export { useGetAllForms, useGetPatient, useFormState, useGetEncounter };
7
- export * from "./usePostEndpoint";
7
+ export { useGetAllForms, useGetPatient, useFormState, useGetEncounter, useSpecificQuestions };
8
+ export * from './usePostEndpoint';
@@ -1,4 +1,4 @@
1
- import { useEffect, useState } from "react";
1
+ import { useEffect, useState } from 'react';
2
2
 
3
3
  const useFormState = (formUuid) => {
4
4
  const [state, setState] = useState(null);
@@ -10,10 +10,10 @@ const useFormState = (formUuid) => {
10
10
  }
11
11
  };
12
12
 
13
- window.addEventListener("ampath-form-state", handler);
13
+ window.addEventListener('ampath-form-state', handler);
14
14
 
15
15
  return () => {
16
- window.removeEventListener("ampath-form-state", handler);
16
+ window.removeEventListener('ampath-form-state', handler);
17
17
  };
18
18
  }, [formUuid]);
19
19
 
@@ -1,15 +1,11 @@
1
- import {
2
- openmrsFetch,
3
- userHasAccess,
4
- useSession,
5
- } from "@openmrs/esm-framework";
6
- import useSWR from "swr";
1
+ import { openmrsFetch, userHasAccess, useSession, restBaseUrl } from '@openmrs/esm-framework';
2
+ import useSWR from 'swr';
7
3
 
8
4
  const customFormRepresentation =
9
- "(uuid,name,display,encounterType:(uuid,name,viewPrivilege,editPrivilege),version,published,retired,resources:(uuid,name,dataType,valueReference))";
5
+ '(uuid,name,display,encounterType:(uuid,name,viewPrivilege,editPrivilege),version,published,retired,resources:(uuid,name,dataType,valueReference))';
10
6
 
11
- const formEncounterUrl = `/ws/rest/v1/form?v=custom:${customFormRepresentation}`;
12
- const formEncounterUrlPoc = `/ws/rest/v1/form?v=custom:${customFormRepresentation}&q=poc`;
7
+ const formEncounterUrl = `${restBaseUrl}/form?v=custom:${customFormRepresentation}`;
8
+ const formEncounterUrlPoc = `${restBaseUrl}/form?v=custom:${customFormRepresentation}&q=poc`;
13
9
 
14
10
  export function useGetAllForms(cachedOfflineFormsOnly = false) {
15
11
  const session = useSession();
@@ -24,7 +20,7 @@ export function useGetAllForms(cachedOfflineFormsOnly = false) {
24
20
  // forms should be published
25
21
  form.published &&
26
22
  // forms should not be component forms
27
- !/component/i.test(form.name)
23
+ !/component/i.test(form.name),
28
24
  // user should have privileges to edit forms
29
25
  ) ?? [];
30
26
 
@@ -32,11 +28,7 @@ export function useGetAllForms(cachedOfflineFormsOnly = false) {
32
28
  });
33
29
 
34
30
  return {
35
- forms: data?.filter((form) =>
36
- Boolean(
37
- userHasAccess(form.encounterType?.editPrivilege?.display, session?.user)
38
- )
39
- ),
31
+ forms: data?.filter((form) => Boolean(userHasAccess(form.encounterType?.editPrivilege?.display, session?.user))),
40
32
  isLoading: !error && !data,
41
33
  error,
42
34
  };
@@ -1,7 +1,7 @@
1
- import { openmrsFetch } from "@openmrs/esm-framework";
2
- import useSWR from "swr";
1
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import useSWR from 'swr';
3
3
 
4
- const encounterUrl = "/ws/rest/v1/encounter/";
4
+ const encounterUrl = `${restBaseUrl}/encounter/`;
5
5
 
6
6
  const useGetEncounter = (encounterUuid) => {
7
7
  const url = `${encounterUrl}${encounterUuid}`;
@@ -1,5 +1,5 @@
1
- import { fetchCurrentPatient } from "@openmrs/esm-framework";
2
- import { useEffect, useState } from "react";
1
+ import { fetchCurrentPatient } from '@openmrs/esm-framework';
2
+ import { useEffect, useState } from 'react';
3
3
 
4
4
  const useGetPatient = (patientUuid) => {
5
5
  const [patient, setPatient] = useState(null);
@@ -1,5 +1,5 @@
1
- import { fetchCurrentPatient } from "@openmrs/esm-framework";
2
- import { useEffect, useState } from "react";
1
+ import { fetchCurrentPatient } from '@openmrs/esm-framework';
2
+ import { useEffect, useState } from 'react';
3
3
 
4
4
  const useGetPatients = (patientUuids) => {
5
5
  const [patients, setPatients] = useState([]);
@@ -17,13 +17,11 @@ const useGetPatients = (patientUuids) => {
17
17
  const getPatients = async (uuids) => {
18
18
  try {
19
19
  setIsLoading(true);
20
- const results = await Promise.all(
21
- uuids.map(async (uuid) => await fetchCurrentPatient(uuid))
22
- );
20
+ const results = await Promise.all(uuids.map(async (uuid) => await fetchCurrentPatient(uuid)));
23
21
  setPatients(results);
24
22
  setIsLoading(false);
25
23
  } catch (error) {
26
- console.error("Error fetching patients:", error);
24
+ console.error('Error fetching patients:', error);
27
25
  setIsLoading(false);
28
26
  }
29
27
  };
@@ -1,5 +1,5 @@
1
- import { useCallback, useEffect, useState } from "react";
2
- import { openmrsFetch } from "@openmrs/esm-framework";
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
3
3
 
4
4
  const useGetSystemSetting = (settingId) => {
5
5
  const [isSubmitting, setIsSubmitting] = useState(false);
@@ -19,9 +19,7 @@ const useGetSystemSetting = (settingId) => {
19
19
  }, []);
20
20
 
21
21
  const getSetting = useCallback(() => {
22
- openmrsFetch(`/ws/rest/v1/systemsetting?q=${settingId}&v=default`)
23
- .then(onResult)
24
- .catch(onError);
22
+ openmrsFetch(`${restBaseUrl}/systemsetting?q=${settingId}&v=default`).then(onResult).catch(onError);
25
23
  }, [onError, onResult, settingId]);
26
24
 
27
25
  useEffect(() => {
@@ -1,4 +1,4 @@
1
- import { useEffect, useState } from "react";
1
+ import { useEffect, useState } from 'react';
2
2
 
3
3
  const useKeyPress = (targetKey) => {
4
4
  const [keyPressed, setKeyPressed] = useState(false);
@@ -16,12 +16,12 @@ const useKeyPress = (targetKey) => {
16
16
  }
17
17
  };
18
18
 
19
- window.addEventListener("keydown", downHandler);
20
- window.addEventListener("keyup", upHandler);
19
+ window.addEventListener('keydown', downHandler);
20
+ window.addEventListener('keyup', upHandler);
21
21
 
22
22
  return () => {
23
- window.removeEventListener("keydown", downHandler);
24
- window.removeEventListener("keyup", upHandler);
23
+ window.removeEventListener('keydown', downHandler);
24
+ window.removeEventListener('keyup', upHandler);
25
25
  };
26
26
  }, [targetKey]);
27
27
 
@@ -1,5 +1,5 @@
1
- import { openmrsFetch } from "@openmrs/esm-framework";
2
- import { useCallback, useState } from "react";
1
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import { useCallback, useState } from 'react';
3
3
 
4
4
  const usePostEndpoint = ({ endpointUrl }) => {
5
5
  const [submissionInProgress, setSubmissionInProgress] = useState(null);
@@ -14,7 +14,7 @@ const usePostEndpoint = ({ endpointUrl }) => {
14
14
  }
15
15
  setResult(result.data);
16
16
  },
17
- [error]
17
+ [error],
18
18
  );
19
19
 
20
20
  const onError = useCallback(
@@ -25,7 +25,7 @@ const usePostEndpoint = ({ endpointUrl }) => {
25
25
  }
26
26
  setError(error?.responseBody?.error ?? error?.responseBody ?? error);
27
27
  },
28
- [result]
28
+ [result],
29
29
  );
30
30
 
31
31
  const post = useCallback(
@@ -34,20 +34,20 @@ const usePostEndpoint = ({ endpointUrl }) => {
34
34
 
35
35
  let path = endpointUrl;
36
36
  if (data.uuid) {
37
- path += "/" + data.uuid;
37
+ path += '/' + data.uuid;
38
38
  }
39
39
 
40
40
  return openmrsFetch(path, {
41
- method: "POST",
41
+ method: 'POST',
42
42
  headers: {
43
- "Content-Type": "application/json",
43
+ 'Content-Type': 'application/json',
44
44
  },
45
45
  body: data,
46
46
  })
47
47
  .then(onFormPosted)
48
48
  .catch(onError);
49
49
  },
50
- [endpointUrl, onError, onFormPosted]
50
+ [endpointUrl, onError, onFormPosted],
51
51
  );
52
52
 
53
53
  const reset = () => {
@@ -66,11 +66,11 @@ const usePostEndpoint = ({ endpointUrl }) => {
66
66
  };
67
67
 
68
68
  const usePostVisit = () => {
69
- return usePostEndpoint({ endpointUrl: "/ws/rest/v1/visit" });
69
+ return usePostEndpoint({ endpointUrl: `${restBaseUrl}/visit` });
70
70
  };
71
71
 
72
72
  const usePostCohort = () => {
73
- return usePostEndpoint({ endpointUrl: "/ws/rest/v1/cohortm/cohort" });
73
+ return usePostEndpoint({ endpointUrl: `${restBaseUrl}/cohortm/cohort` });
74
74
  };
75
75
 
76
76
  export { usePostEndpoint, usePostVisit, usePostCohort };
@@ -1,6 +1,6 @@
1
- import { openmrsFetch, FetchResponse } from "@openmrs/esm-framework";
2
- import { useCallback, useMemo } from "react";
3
- import useSWRInfinite from "swr/infinite";
1
+ import { openmrsFetch, type FetchResponse, restBaseUrl } from '@openmrs/esm-framework';
2
+ import { useCallback, useMemo } from 'react';
3
+ import useSWRInfinite from 'swr/infinite';
4
4
 
5
5
  export interface SearchResponse {
6
6
  data: Array<Record<string, unknown>> | null;
@@ -11,12 +11,14 @@ export interface SearchResponse {
11
11
  currentPage: number;
12
12
  totalResults: number;
13
13
  setPage: (size: number | ((_size: number) => number)) => Promise<
14
- FetchResponse<{
15
- results: Array<Record<string, unknown>>;
16
- links: Array<{
17
- rel: "prev" | "next";
18
- }>;
19
- }>[]
14
+ Array<
15
+ FetchResponse<{
16
+ results: Array<Record<string, unknown>>;
17
+ links: Array<{
18
+ rel: 'prev' | 'next';
19
+ }>;
20
+ }>
21
+ >
20
22
  >;
21
23
  }
22
24
 
@@ -28,29 +30,18 @@ interface SearchInfiniteProps {
28
30
  resultsToFetch?: number;
29
31
  }
30
32
 
31
- const useSearchEndpointInfinite = (
32
- arg0: SearchInfiniteProps
33
- ): SearchResponse => {
34
- const {
35
- baseUrl,
36
- searchTerm,
37
- parameters,
38
- searching = true,
39
- resultsToFetch = 10,
40
- } = arg0;
33
+ const useSearchEndpointInfinite = (arg0: SearchInfiniteProps): SearchResponse => {
34
+ const { baseUrl, searchTerm, parameters, searching = true, resultsToFetch = 10 } = arg0;
41
35
 
42
36
  const getUrl = useCallback(
43
37
  (
44
38
  page: number,
45
39
  prevPageData: FetchResponse<{
46
40
  results: Array<Record<string, unknown>>;
47
- links: Array<{ rel: "prev" | "next" }>;
48
- }>
41
+ links: Array<{ rel: 'prev' | 'next' }>;
42
+ }>,
49
43
  ) => {
50
- if (
51
- prevPageData &&
52
- !prevPageData?.data?.links.some((link) => link.rel === "next")
53
- ) {
44
+ if (prevPageData && !prevPageData?.data?.links.some((link) => link.rel === 'next')) {
54
45
  return null;
55
46
  }
56
47
  let url = `${baseUrl}?q=${searchTerm}`;
@@ -72,13 +63,13 @@ const useSearchEndpointInfinite = (
72
63
  }
73
64
  return url;
74
65
  },
75
- [baseUrl, searchTerm, parameters, resultsToFetch]
66
+ [baseUrl, searchTerm, parameters, resultsToFetch],
76
67
  );
77
68
 
78
69
  const { data, isValidating, setSize, error, size } = useSWRInfinite<
79
70
  FetchResponse<{
80
71
  results: Array<Record<string, unknown>>;
81
- links: Array<{ rel: "prev" | "next" }>;
72
+ links: Array<{ rel: 'prev' | 'next' }>;
82
73
  totalCount: number;
83
74
  }>,
84
75
  Error
@@ -86,32 +77,24 @@ const useSearchEndpointInfinite = (
86
77
 
87
78
  const results = useMemo(
88
79
  () => ({
89
- data: data
90
- ? [].concat(...(data?.map((resp) => resp?.data?.results) ?? []))
91
- : null,
80
+ data: data ? [].concat(...(data?.map((resp) => resp?.data?.results) ?? [])) : null,
92
81
  isLoading: !data && !error,
93
82
  error,
94
- hasMore: data?.length
95
- ? !!data[data.length - 1].data?.links?.some(
96
- (link) => link.rel === "next"
97
- )
98
- : false,
83
+ hasMore: data?.length ? !!data[data.length - 1].data?.links?.some((link) => link.rel === 'next') : false,
99
84
  loadingNewData: isValidating,
100
85
  setPage: setSize,
101
86
  currentPage: size,
102
87
  totalResults: data?.[0]?.data?.totalCount,
103
88
  }),
104
- [data, isValidating, error, setSize, size]
89
+ [data, isValidating, error, setSize, size],
105
90
  );
106
91
 
107
92
  return results;
108
93
  };
109
94
 
110
- const useSearchCohortInfinite = ({
111
- ...props
112
- }: SearchInfiniteProps): SearchResponse => {
95
+ const useSearchCohortInfinite = ({ ...props }: SearchInfiniteProps): SearchResponse => {
113
96
  return useSearchEndpointInfinite({
114
- baseUrl: "/ws/rest/v1/cohortm/cohort",
97
+ baseUrl: `${restBaseUrl}/cohortm/cohort`,
115
98
  resultsToFetch: 10,
116
99
  ...props,
117
100
  });
@@ -0,0 +1,75 @@
1
+ import { type FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import useSWR from 'swr';
3
+ import { type SpecificQuestion, type SpecificQuestionConfig } from '../types';
4
+ import { useMemo } from 'react';
5
+
6
+ const formUrl = `${restBaseUrl}/o3/forms`;
7
+
8
+ export const useSpecificQuestions = (formUuid: string, specificQuestionConfig: Array<SpecificQuestionConfig>) => {
9
+ const specificQuestionsToLoad = useMemo(
10
+ () => getQuestionByFormId(formUuid, specificQuestionConfig),
11
+ [formUuid, specificQuestionConfig],
12
+ );
13
+
14
+ const { data, error } = useSWR<FetchResponse, Error>(
15
+ specificQuestionsToLoad ? `${formUrl}/${formUuid}` : null,
16
+ openmrsFetch,
17
+ );
18
+
19
+ const specificQuestions = getQuestions(specificQuestionsToLoad, data?.data);
20
+
21
+ return {
22
+ questions: specificQuestions || null,
23
+ isError: error,
24
+ isLoading: !data && !error,
25
+ };
26
+ };
27
+
28
+ function getQuestionByFormId(formUuid: string, specificQuestionConfig: Array<SpecificQuestionConfig>) {
29
+ return specificQuestionConfig.filter((question) => question.forms.includes(formUuid));
30
+ }
31
+
32
+ function getQuestions(specificQuestions: Array<SpecificQuestionConfig>, formSchema): Array<SpecificQuestion> {
33
+ if (!formSchema || specificQuestions.length <= 0) {
34
+ return [];
35
+ }
36
+
37
+ const specificQuestionsMap = new Map<string, SpecificQuestionConfig>(
38
+ specificQuestions.map((sq) => [sq.questionId, sq]),
39
+ );
40
+
41
+ const questionIds = new Set(specificQuestionsMap.keys());
42
+ const conceptLabels = formSchema.conceptReferences;
43
+
44
+ return formSchema.pages.flatMap((page) =>
45
+ page.sections.flatMap((section) =>
46
+ section.questions
47
+ .filter((question) => questionIds.has(question.id))
48
+ .map((question) => {
49
+ const specificQuestion = specificQuestionsMap.get(question.id) || {};
50
+
51
+ const answers =
52
+ (specificQuestion as SpecificQuestionConfig).answers?.map((a) => ({
53
+ value: a,
54
+ display: conceptLabels[a]?.display,
55
+ })) ||
56
+ (question.questionOptions.answers ?? []).map((answer) => ({
57
+ value: answer.concept,
58
+ display: answer.label ?? conceptLabels[answer.concept]?.display,
59
+ }));
60
+
61
+ return {
62
+ question: {
63
+ display: question.label ?? conceptLabels[question.questionOptions.concept]?.display,
64
+ id: question.id,
65
+ disabled: (specificQuestion as SpecificQuestionConfig).disabled,
66
+ defaultAnswer: (specificQuestion as SpecificQuestionConfig).defaultAnswer,
67
+ },
68
+ answers,
69
+ };
70
+ }),
71
+ ),
72
+ );
73
+ }
74
+
75
+ export default useSpecificQuestions;
@@ -1,15 +1,8 @@
1
- import { useCallback, useState } from "react";
2
- import { useTranslation } from "react-i18next";
3
- import {
4
- showNotification,
5
- showToast,
6
- openmrsFetch,
7
- } from "@openmrs/esm-framework";
1
+ import { useCallback, useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { showNotification, showToast, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
8
4
 
9
- const useStartVisit = ({
10
- showSuccessNotification = true,
11
- showErrorNotification = true,
12
- }) => {
5
+ const useStartVisit = ({ showSuccessNotification = true, showErrorNotification = true }) => {
13
6
  const { t } = useTranslation();
14
7
  const [isSubmitting, setIsSubmitting] = useState(false);
15
8
  const [success, setSuccess] = useState(null);
@@ -23,16 +16,13 @@ const useStartVisit = ({
23
16
  if (showSuccessNotification) {
24
17
  showToast({
25
18
  critical: true,
26
- kind: "success",
27
- description: t(
28
- "visitStartedSuccessfully",
29
- `${result?.data?.visitType?.display} started successfully`
30
- ),
31
- title: t("visitStarted", "Visit started"),
19
+ kind: 'success',
20
+ description: t('visitStartedSuccessfully', `${result?.data?.visitType?.display} started successfully`),
21
+ title: t('visitStarted', 'Visit started'),
32
22
  });
33
23
  }
34
24
  },
35
- [t, showSuccessNotification]
25
+ [t, showSuccessNotification],
36
26
  );
37
27
 
38
28
  const onError = useCallback(
@@ -42,14 +32,14 @@ const useStartVisit = ({
42
32
  setError(error);
43
33
  if (showErrorNotification) {
44
34
  showNotification({
45
- title: t("startVisitError", "Error starting visit"),
46
- kind: "error",
35
+ title: t('startVisitError', 'Error starting visit'),
36
+ kind: 'error',
47
37
  critical: true,
48
38
  description: error?.message,
49
39
  });
50
40
  }
51
41
  },
52
- [t, showErrorNotification]
42
+ [t, showErrorNotification],
53
43
  );
54
44
 
55
45
  const saveVisit = useCallback(
@@ -61,22 +51,22 @@ const useStartVisit = ({
61
51
  visitType: data.visitType,
62
52
  location: data.location,
63
53
  };
64
- openmrsFetch("/ws/rest/v1/visit", {
65
- method: "POST",
54
+ openmrsFetch(`${restBaseUrl}/visit`, {
55
+ method: 'POST',
66
56
  body: payload,
67
- headers: { "Content-Type": "application/json" },
57
+ headers: { 'Content-Type': 'application/json' },
68
58
  })
69
59
  .then(onSave)
70
60
  .catch(onError);
71
61
  },
72
- [onError, onSave]
62
+ [onError, onSave],
73
63
  );
74
64
 
75
65
  const updateEncounter = useCallback((data) => {
76
- openmrsFetch("/ws/rest/v1/encounter/" + data.uuid, {
77
- method: "POST",
66
+ openmrsFetch(`${restBaseUrl}/encounter/` + data.uuid, {
67
+ method: 'POST',
78
68
  body: { visit: data.visit },
79
- headers: { "Content-Type": "application/json" },
69
+ headers: { 'Content-Type': 'application/json' },
80
70
  });
81
71
  }, []);
82
72
 
package/src/index.ts CHANGED
@@ -1,30 +1,18 @@
1
- import {
2
- getAsyncLifecycle,
3
- defineConfigSchema,
4
- registerBreadcrumbs,
5
- } from "@openmrs/esm-framework";
6
- import { configSchema } from "./config-schema";
1
+ import { getAsyncLifecycle, defineConfigSchema, registerBreadcrumbs } from '@openmrs/esm-framework';
2
+ import { configSchema } from './config-schema';
7
3
 
8
- const moduleName = "@openmrs/esm-fast-data-entry-app";
4
+ const moduleName = '@openmrs/esm-fast-data-entry-app';
9
5
 
10
6
  const options = {
11
- featureName: "fast-data-entry-app",
7
+ featureName: 'fast-data-entry-app',
12
8
  moduleName,
13
9
  };
14
10
 
15
- export const importTranslation = require.context(
16
- "../translations",
17
- false,
18
- /.json$/,
19
- "lazy"
20
- );
11
+ export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
21
12
 
22
- export const root = getAsyncLifecycle(() => import("./Root"), options);
13
+ export const root = getAsyncLifecycle(() => import('./Root'), options);
23
14
 
24
- export const formsAppMenuLink = getAsyncLifecycle(
25
- () => import("./forms-app-menu-link"),
26
- options
27
- );
15
+ export const formsAppMenuLink = getAsyncLifecycle(() => import('./forms-app-menu-link'), options);
28
16
 
29
17
  export function startupApp() {
30
18
  defineConfigSchema(moduleName, configSchema);
@@ -32,7 +20,7 @@ export function startupApp() {
32
20
  registerBreadcrumbs([
33
21
  {
34
22
  path: `${window.spaBase}/forms`,
35
- title: "Forms",
23
+ title: 'Forms',
36
24
  parent: `${window.spaBase}/home`,
37
25
  },
38
26
  ]);