@openmrs/esm-fast-data-entry-app 1.0.1-pre.17 → 1.0.1-pre.176

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 (176) hide show
  1. package/README.md +21 -2
  2. package/__mocks__/react-i18next.js +9 -14
  3. package/dist/101.js +1 -0
  4. package/dist/101.js.map +1 -0
  5. package/dist/132.js +1 -1
  6. package/dist/143.js +1 -0
  7. package/dist/143.js.map +1 -0
  8. package/dist/188.js +1 -0
  9. package/dist/188.js.map +1 -0
  10. package/dist/197.js +1 -0
  11. package/dist/219.js +1 -0
  12. package/dist/219.js.map +1 -0
  13. package/dist/221.js +1 -0
  14. package/dist/221.js.map +1 -0
  15. package/dist/259.js +1 -0
  16. package/dist/259.js.map +1 -0
  17. package/dist/29.js +2 -0
  18. package/dist/29.js.LICENSE.txt +3 -0
  19. package/dist/29.js.map +1 -0
  20. package/dist/300.js +1 -0
  21. package/dist/31.js +2 -0
  22. package/dist/{569.js.LICENSE.txt → 31.js.LICENSE.txt} +9 -6
  23. package/dist/31.js.map +1 -0
  24. package/dist/326.js +1 -0
  25. package/dist/326.js.map +1 -0
  26. package/dist/335.js +1 -0
  27. package/dist/367.js +1 -0
  28. package/dist/367.js.map +1 -0
  29. package/dist/480.js +1 -0
  30. package/dist/491.js +1 -0
  31. package/dist/491.js.map +1 -0
  32. package/dist/540.js +2 -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/{68.js.LICENSE.txt → 773.js.LICENSE.txt} +13 -2
  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.map +1 -0
  52. package/dist/99.js +1 -0
  53. package/dist/99.js.map +1 -0
  54. package/dist/main.js +1 -1
  55. package/dist/main.js.map +1 -0
  56. package/dist/openmrs-esm-fast-data-entry-app.js +1 -1
  57. package/dist/openmrs-esm-fast-data-entry-app.js.buildmanifest.json +403 -136
  58. package/dist/openmrs-esm-fast-data-entry-app.js.map +1 -0
  59. package/dist/routes.json +1 -0
  60. package/jest.config.json +2 -1
  61. package/package.json +41 -38
  62. package/prettier.config.js +8 -0
  63. package/src/CancelModal.tsx +42 -0
  64. package/src/CompleteModal.tsx +35 -0
  65. package/src/FormBootstrap.tsx +39 -11
  66. package/src/Root.tsx +7 -12
  67. package/src/add-group-modal/AddGroupModal.tsx +107 -120
  68. package/src/add-group-modal/styles.scss +7 -3
  69. package/src/config-schema.ts +77 -16
  70. package/src/constant.ts +1 -1
  71. package/src/context/FormWorkflowContext.tsx +31 -32
  72. package/src/context/FormWorkflowReducer.ts +53 -67
  73. package/src/context/GroupFormWorkflowContext.tsx +56 -44
  74. package/src/context/GroupFormWorkflowReducer.ts +177 -68
  75. package/src/declarations.d.ts +4 -0
  76. package/src/empty-state/EmptyDataIllustration.tsx +4 -16
  77. package/src/empty-state/EmptyState.tsx +8 -13
  78. package/src/empty-state/styles.scss +14 -14
  79. package/src/form-entry-workflow/FormEntryWorkflow.tsx +78 -124
  80. package/src/form-entry-workflow/form-review-card/FormReviewCard.tsx +7 -7
  81. package/src/form-entry-workflow/form-review-card/index.ts +1 -1
  82. package/src/form-entry-workflow/form-review-card/styles.scss +9 -11
  83. package/src/form-entry-workflow/index.ts +1 -1
  84. package/src/form-entry-workflow/patient-banner/PatientBanner.test.tsx +5 -5
  85. package/src/form-entry-workflow/patient-banner/PatientBanner.tsx +14 -27
  86. package/src/form-entry-workflow/patient-banner/index.ts +1 -1
  87. package/src/form-entry-workflow/patient-banner/styles.scss +11 -12
  88. package/src/form-entry-workflow/patient-search-header/PatientSearchHeader.tsx +19 -28
  89. package/src/form-entry-workflow/patient-search-header/index.ts +1 -1
  90. package/src/form-entry-workflow/patient-search-header/styles.scss +13 -10
  91. package/src/form-entry-workflow/styles.scss +13 -14
  92. package/src/form-entry-workflow/workflow-review/WorkflowReview.tsx +13 -11
  93. package/src/form-entry-workflow/workflow-review/index.ts +1 -1
  94. package/src/form-entry-workflow/workflow-review/styles.scss +0 -4
  95. package/src/forms-app-menu-link.tsx +4 -6
  96. package/src/forms-page/FormsPage.tsx +24 -47
  97. package/src/forms-page/forms-table/FormsTable.tsx +33 -47
  98. package/src/forms-page/forms-table/index.ts +1 -1
  99. package/src/forms-page/forms-table/styles.scss +4 -5
  100. package/src/forms-page/index.ts +1 -1
  101. package/src/forms-page/styles.scss +3 -5
  102. package/src/group-form-entry-workflow/GroupFormEntryWorkflow.tsx +15 -402
  103. package/src/group-form-entry-workflow/GroupSessionWorkspace.tsx +207 -0
  104. package/src/group-form-entry-workflow/SessionDetailsForm.tsx +154 -0
  105. package/src/group-form-entry-workflow/SessionMetaWorkspace.tsx +99 -0
  106. package/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx +130 -0
  107. package/src/group-form-entry-workflow/attendance-table/index.ts +1 -0
  108. package/src/group-form-entry-workflow/configurable-questions/ConfigurableQuestionsSection.tsx +41 -0
  109. package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.test.tsx +5 -5
  110. package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.tsx +14 -30
  111. package/src/group-form-entry-workflow/group-display-header/index.ts +1 -1
  112. package/src/group-form-entry-workflow/group-display-header/styles.scss +20 -20
  113. package/src/group-form-entry-workflow/group-search/CompactGroupResults.tsx +24 -35
  114. package/src/group-form-entry-workflow/group-search/CompactGroupSearch.tsx +13 -15
  115. package/src/group-form-entry-workflow/group-search/GroupSearch.tsx +22 -38
  116. package/src/group-form-entry-workflow/group-search/compact-group-result.scss +16 -17
  117. package/src/group-form-entry-workflow/group-search/compact-group-search.scss +7 -8
  118. package/src/group-form-entry-workflow/group-search/group-search.scss +20 -23
  119. package/src/group-form-entry-workflow/group-search-header/GroupSearchHeader.tsx +41 -18
  120. package/src/group-form-entry-workflow/group-search-header/index.ts +1 -1
  121. package/src/group-form-entry-workflow/group-search-header/styles.scss +8 -8
  122. package/src/group-form-entry-workflow/index.ts +1 -1
  123. package/src/group-form-entry-workflow/styles.scss +15 -17
  124. package/src/hooks/index.ts +7 -6
  125. package/src/hooks/useForm.ts +56 -0
  126. package/src/hooks/useFormState.ts +3 -3
  127. package/src/hooks/useGetAllForms.ts +7 -15
  128. package/src/hooks/useGetEncounter.ts +3 -3
  129. package/src/hooks/useGetPatient.ts +3 -3
  130. package/src/hooks/useGetPatients.ts +32 -0
  131. package/src/hooks/useGetSystemSetting.ts +36 -0
  132. package/src/hooks/useKeyPress.ts +5 -5
  133. package/src/hooks/usePostEndpoint.ts +16 -10
  134. package/src/hooks/useSearchEndpoint.ts +23 -40
  135. package/src/hooks/useStartVisit.ts +82 -0
  136. package/src/index.ts +12 -76
  137. package/src/patient-card/PatientCard.tsx +8 -20
  138. package/src/patient-card/index.ts +1 -1
  139. package/src/patient-card/styles.scss +3 -4
  140. package/src/routes.json +24 -0
  141. package/src/setup-tests.ts +1 -1
  142. package/src/types.ts +20 -0
  143. package/tools/i18next-parser.config.js +93 -0
  144. package/translations/am.json +75 -0
  145. package/translations/ar.json +75 -0
  146. package/translations/en.json +32 -11
  147. package/translations/es.json +75 -0
  148. package/translations/fr.json +75 -0
  149. package/translations/he.json +75 -0
  150. package/translations/km.json +75 -0
  151. package/turbo.json +18 -0
  152. package/webpack.config.js +1 -1
  153. package/dist/247.js +0 -1
  154. package/dist/255.js +0 -1
  155. package/dist/294.js +0 -2
  156. package/dist/32.js +0 -1
  157. package/dist/327.js +0 -1
  158. package/dist/403.js +0 -2
  159. package/dist/403.js.LICENSE.txt +0 -14
  160. package/dist/553.js +0 -2
  161. package/dist/553.js.LICENSE.txt +0 -14
  162. package/dist/569.js +0 -2
  163. package/dist/574.js +0 -1
  164. package/dist/595.js +0 -2
  165. package/dist/595.js.LICENSE.txt +0 -1
  166. package/dist/617.js +0 -1
  167. package/dist/68.js +0 -2
  168. package/dist/776.js +0 -1
  169. package/dist/804.js +0 -1
  170. package/dist/820.js +0 -1
  171. package/dist/906.js +0 -1
  172. package/dist/935.js +0 -2
  173. package/dist/openmrs-esm-fast-data-entry-app.old +0 -1
  174. package/src/declarations.d.tsx +0 -2
  175. /package/dist/{294.js.LICENSE.txt → 540.js.LICENSE.txt} +0 -0
  176. /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,26 +24,27 @@
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 {
46
44
  flex-grow: 1;
47
45
  max-height: calc(100vh - 14rem);
48
46
  overflow-y: scroll;
47
+ text-align: left;
49
48
  }
50
49
 
51
50
  .formContainer :global(.cds--form-item) :global(.question-area) {
@@ -53,23 +52,23 @@
53
52
  }
54
53
 
55
54
  .rightPanel {
56
- width: 13rem;
55
+ min-width: 13rem;
57
56
  text-align: left;
58
57
  overflow-y: scroll;
59
58
  display: flex;
60
59
  flex-direction: column;
61
- row-gap: spacing.$spacing-05;
60
+ row-gap: layout.$spacing-05;
62
61
  }
63
62
 
64
63
  .patientCardsSection {
65
- margin: spacing.$spacing-05 0;
64
+ margin: layout.$spacing-05 0;
66
65
  border-bottom: 1px solid colors.$gray-10;
67
66
  }
68
67
 
69
68
  .rightPanelActionButtons {
70
69
  display: flex;
71
70
  flex-direction: column;
72
- row-gap: spacing.$spacing-03;
71
+ row-gap: layout.$spacing-03;
73
72
  & button {
74
73
  width: 100%;
75
74
  text-decoration: "none";
@@ -89,7 +88,6 @@
89
88
  width: 500px;
90
89
  }
91
90
 
92
-
93
91
  .formError {
94
92
  @include type.type-style("helper-text-02");
95
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 useForm from './useForm';
5
6
 
6
- export { useGetAllForms, useGetPatient, useFormState, useGetEncounter };
7
- export * from "./usePostEndpoint";
7
+ export { useGetAllForms, useGetPatient, useFormState, useGetEncounter, useForm };
8
+ export * from './usePostEndpoint';
@@ -0,0 +1,56 @@
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
+ () => getQuestionIdsByFormId(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 = getQuestionsByIds(specificQuestionsToLoad, data?.data);
20
+
21
+ return {
22
+ questions: specificQuestions || null,
23
+ isError: error,
24
+ isLoading: !data && !error,
25
+ };
26
+ };
27
+
28
+ function getQuestionIdsByFormId(formUuid: string, specificQuestionConfig: Array<SpecificQuestionConfig>) {
29
+ const matchingQuestions = specificQuestionConfig.filter((question) => question.forms.includes(formUuid));
30
+ return matchingQuestions.map((question) => question.questionId);
31
+ }
32
+
33
+ function getQuestionsByIds(questionIds, formSchema): Array<SpecificQuestion> {
34
+ if (!formSchema || questionIds.lenght <= 0) {
35
+ return [];
36
+ }
37
+ const conceptLabels = formSchema.conceptReferences;
38
+ return formSchema.pages.flatMap((page) =>
39
+ page.sections.flatMap((section) =>
40
+ section.questions
41
+ .filter((question) => questionIds.includes(question.id))
42
+ .map((question) => ({
43
+ question: {
44
+ display: question.label ?? conceptLabels[question.questionOptions.concept]?.display,
45
+ id: question.id,
46
+ },
47
+ answers: (question.questionOptions.answers ?? []).map((answer) => ({
48
+ value: answer.concept,
49
+ display: answer.label ?? conceptLabels[answer.concept]?.display,
50
+ })),
51
+ })),
52
+ ),
53
+ );
54
+ }
55
+
56
+ export default useSpecificQuestions;
@@ -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);
@@ -14,7 +14,7 @@ const useGetPatient = (patientUuid) => {
14
14
 
15
15
  const getPatient = async (uuid) => {
16
16
  const result = await fetchCurrentPatient(uuid);
17
- setPatient(result?.data);
17
+ setPatient(result);
18
18
  };
19
19
 
20
20
  return patient;
@@ -0,0 +1,32 @@
1
+ import { fetchCurrentPatient } from '@openmrs/esm-framework';
2
+ import { useEffect, useState } from 'react';
3
+
4
+ const useGetPatients = (patientUuids) => {
5
+ const [patients, setPatients] = useState([]);
6
+ const [isLoading, setIsLoading] = useState(true);
7
+
8
+ useEffect(() => {
9
+ if (!patientUuids || patientUuids.length === 0) {
10
+ setPatients([]);
11
+ setIsLoading(false);
12
+ } else {
13
+ getPatients(patientUuids);
14
+ }
15
+ }, [patientUuids]);
16
+
17
+ const getPatients = async (uuids) => {
18
+ try {
19
+ setIsLoading(true);
20
+ const results = await Promise.all(uuids.map(async (uuid) => await fetchCurrentPatient(uuid)));
21
+ setPatients(results);
22
+ setIsLoading(false);
23
+ } catch (error) {
24
+ console.error('Error fetching patients:', error);
25
+ setIsLoading(false);
26
+ }
27
+ };
28
+
29
+ return { patients, isLoading };
30
+ };
31
+
32
+ export default useGetPatients;
@@ -0,0 +1,36 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
3
+
4
+ const useGetSystemSetting = (settingId) => {
5
+ const [isSubmitting, setIsSubmitting] = useState(false);
6
+ const [result, setResult] = useState(null);
7
+ const [error, setError] = useState(null);
8
+
9
+ const onResult = useCallback((result) => {
10
+ setIsSubmitting(false);
11
+ setError(false);
12
+ setResult(result);
13
+ }, []);
14
+
15
+ const onError = useCallback((error) => {
16
+ setIsSubmitting(false);
17
+ setResult(null);
18
+ setError(error);
19
+ }, []);
20
+
21
+ const getSetting = useCallback(() => {
22
+ openmrsFetch(`${restBaseUrl}/systemsetting?q=${settingId}&v=default`).then(onResult).catch(onError);
23
+ }, [onError, onResult, settingId]);
24
+
25
+ useEffect(() => {
26
+ getSetting();
27
+ }, [getSetting]);
28
+
29
+ return {
30
+ result,
31
+ error,
32
+ isSubmitting,
33
+ };
34
+ };
35
+
36
+ export default useGetSystemSetting;
@@ -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,23 +25,29 @@ 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(
32
32
  async (data) => {
33
33
  setSubmissionInProgress(true);
34
- return openmrsFetch(endpointUrl, {
35
- method: "POST",
34
+
35
+ let path = endpointUrl;
36
+ if (data.uuid) {
37
+ path += '/' + data.uuid;
38
+ }
39
+
40
+ return openmrsFetch(path, {
41
+ method: 'POST',
36
42
  headers: {
37
- "Content-Type": "application/json",
43
+ 'Content-Type': 'application/json',
38
44
  },
39
45
  body: data,
40
46
  })
41
47
  .then(onFormPosted)
42
48
  .catch(onError);
43
49
  },
44
- [endpointUrl, onError, onFormPosted]
50
+ [endpointUrl, onError, onFormPosted],
45
51
  );
46
52
 
47
53
  const reset = () => {
@@ -60,11 +66,11 @@ const usePostEndpoint = ({ endpointUrl }) => {
60
66
  };
61
67
 
62
68
  const usePostVisit = () => {
63
- return usePostEndpoint({ endpointUrl: "/ws/rest/v1/visit" });
69
+ return usePostEndpoint({ endpointUrl: `${restBaseUrl}/visit` });
64
70
  };
65
71
 
66
72
  const usePostCohort = () => {
67
- return usePostEndpoint({ endpointUrl: "/ws/rest/v1/cohortm/cohort" });
73
+ return usePostEndpoint({ endpointUrl: `${restBaseUrl}/cohortm/cohort` });
68
74
  };
69
75
 
70
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,82 @@
1
+ import { useCallback, useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { showNotification, showToast, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
4
+
5
+ const useStartVisit = ({ showSuccessNotification = true, showErrorNotification = true }) => {
6
+ const { t } = useTranslation();
7
+ const [isSubmitting, setIsSubmitting] = useState(false);
8
+ const [success, setSuccess] = useState(null);
9
+ const [error, setError] = useState(null);
10
+
11
+ const onSave = useCallback(
12
+ (result) => {
13
+ setIsSubmitting(false);
14
+ setError(false);
15
+ setSuccess(result);
16
+ if (showSuccessNotification) {
17
+ showToast({
18
+ critical: true,
19
+ kind: 'success',
20
+ description: t('visitStartedSuccessfully', `${result?.data?.visitType?.display} started successfully`),
21
+ title: t('visitStarted', 'Visit started'),
22
+ });
23
+ }
24
+ },
25
+ [t, showSuccessNotification],
26
+ );
27
+
28
+ const onError = useCallback(
29
+ (error) => {
30
+ setIsSubmitting(false);
31
+ setSuccess(false);
32
+ setError(error);
33
+ if (showErrorNotification) {
34
+ showNotification({
35
+ title: t('startVisitError', 'Error starting visit'),
36
+ kind: 'error',
37
+ critical: true,
38
+ description: error?.message,
39
+ });
40
+ }
41
+ },
42
+ [t, showErrorNotification],
43
+ );
44
+
45
+ const saveVisit = useCallback(
46
+ (data) => {
47
+ const payload = {
48
+ patient: data.patientUuid,
49
+ startDatetime: data.startDatetime,
50
+ stopDatetime: data.stopDatetime,
51
+ visitType: data.visitType,
52
+ location: data.location,
53
+ };
54
+ openmrsFetch(`${restBaseUrl}/visit`, {
55
+ method: 'POST',
56
+ body: payload,
57
+ headers: { 'Content-Type': 'application/json' },
58
+ })
59
+ .then(onSave)
60
+ .catch(onError);
61
+ },
62
+ [onError, onSave],
63
+ );
64
+
65
+ const updateEncounter = useCallback((data) => {
66
+ openmrsFetch(`${restBaseUrl}/encounter/` + data.uuid, {
67
+ method: 'POST',
68
+ body: { visit: data.visit },
69
+ headers: { 'Content-Type': 'application/json' },
70
+ });
71
+ }, []);
72
+
73
+ return {
74
+ saveVisit,
75
+ updateEncounter,
76
+ success,
77
+ error,
78
+ isSubmitting,
79
+ };
80
+ };
81
+
82
+ export default useStartVisit;