@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.
- package/README.md +21 -2
- package/__mocks__/react-i18next.js +9 -14
- package/dist/101.js +1 -0
- package/dist/101.js.map +1 -0
- package/dist/132.js +1 -1
- package/dist/143.js +1 -0
- package/dist/143.js.map +1 -0
- package/dist/188.js +1 -0
- package/dist/188.js.map +1 -0
- package/dist/197.js +1 -0
- package/dist/219.js +1 -0
- package/dist/219.js.map +1 -0
- package/dist/221.js +1 -0
- package/dist/221.js.map +1 -0
- package/dist/259.js +1 -0
- package/dist/259.js.map +1 -0
- package/dist/29.js +2 -0
- package/dist/29.js.LICENSE.txt +3 -0
- package/dist/29.js.map +1 -0
- package/dist/300.js +1 -0
- package/dist/31.js +2 -0
- package/dist/{569.js.LICENSE.txt → 31.js.LICENSE.txt} +9 -6
- package/dist/31.js.map +1 -0
- package/dist/326.js +1 -0
- package/dist/326.js.map +1 -0
- package/dist/335.js +1 -0
- package/dist/367.js +1 -0
- package/dist/367.js.map +1 -0
- package/dist/480.js +1 -0
- package/dist/491.js +1 -0
- package/dist/491.js.map +1 -0
- package/dist/540.js +2 -0
- package/dist/540.js.map +1 -0
- package/dist/55.js +1 -0
- package/dist/564.js +1 -0
- package/dist/564.js.map +1 -0
- package/dist/602.js +1 -0
- package/dist/602.js.map +1 -0
- package/dist/626.js +2 -0
- package/dist/626.js.LICENSE.txt +9 -0
- package/dist/626.js.map +1 -0
- package/dist/652.js +1 -0
- package/dist/685.js +1 -0
- package/dist/685.js.map +1 -0
- package/dist/773.js +2 -0
- package/dist/{68.js.LICENSE.txt → 773.js.LICENSE.txt} +13 -2
- package/dist/773.js.map +1 -0
- package/dist/91.js +1 -0
- package/dist/91.js.map +1 -0
- package/dist/961.js +2 -0
- package/dist/961.js.map +1 -0
- package/dist/99.js +1 -0
- package/dist/99.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -0
- package/dist/openmrs-esm-fast-data-entry-app.js +1 -1
- package/dist/openmrs-esm-fast-data-entry-app.js.buildmanifest.json +403 -136
- package/dist/openmrs-esm-fast-data-entry-app.js.map +1 -0
- package/dist/routes.json +1 -0
- package/jest.config.json +2 -1
- package/package.json +41 -38
- package/prettier.config.js +8 -0
- package/src/CancelModal.tsx +42 -0
- package/src/CompleteModal.tsx +35 -0
- package/src/FormBootstrap.tsx +39 -11
- package/src/Root.tsx +7 -12
- package/src/add-group-modal/AddGroupModal.tsx +107 -120
- package/src/add-group-modal/styles.scss +7 -3
- package/src/config-schema.ts +77 -16
- package/src/constant.ts +1 -1
- package/src/context/FormWorkflowContext.tsx +31 -32
- package/src/context/FormWorkflowReducer.ts +53 -67
- package/src/context/GroupFormWorkflowContext.tsx +56 -44
- package/src/context/GroupFormWorkflowReducer.ts +177 -68
- package/src/declarations.d.ts +4 -0
- package/src/empty-state/EmptyDataIllustration.tsx +4 -16
- package/src/empty-state/EmptyState.tsx +8 -13
- package/src/empty-state/styles.scss +14 -14
- package/src/form-entry-workflow/FormEntryWorkflow.tsx +78 -124
- package/src/form-entry-workflow/form-review-card/FormReviewCard.tsx +7 -7
- package/src/form-entry-workflow/form-review-card/index.ts +1 -1
- package/src/form-entry-workflow/form-review-card/styles.scss +9 -11
- package/src/form-entry-workflow/index.ts +1 -1
- package/src/form-entry-workflow/patient-banner/PatientBanner.test.tsx +5 -5
- package/src/form-entry-workflow/patient-banner/PatientBanner.tsx +14 -27
- package/src/form-entry-workflow/patient-banner/index.ts +1 -1
- package/src/form-entry-workflow/patient-banner/styles.scss +11 -12
- package/src/form-entry-workflow/patient-search-header/PatientSearchHeader.tsx +19 -28
- package/src/form-entry-workflow/patient-search-header/index.ts +1 -1
- package/src/form-entry-workflow/patient-search-header/styles.scss +13 -10
- package/src/form-entry-workflow/styles.scss +13 -14
- package/src/form-entry-workflow/workflow-review/WorkflowReview.tsx +13 -11
- package/src/form-entry-workflow/workflow-review/index.ts +1 -1
- package/src/form-entry-workflow/workflow-review/styles.scss +0 -4
- package/src/forms-app-menu-link.tsx +4 -6
- package/src/forms-page/FormsPage.tsx +24 -47
- package/src/forms-page/forms-table/FormsTable.tsx +33 -47
- package/src/forms-page/forms-table/index.ts +1 -1
- package/src/forms-page/forms-table/styles.scss +4 -5
- package/src/forms-page/index.ts +1 -1
- package/src/forms-page/styles.scss +3 -5
- package/src/group-form-entry-workflow/GroupFormEntryWorkflow.tsx +15 -402
- package/src/group-form-entry-workflow/GroupSessionWorkspace.tsx +207 -0
- package/src/group-form-entry-workflow/SessionDetailsForm.tsx +154 -0
- package/src/group-form-entry-workflow/SessionMetaWorkspace.tsx +99 -0
- package/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx +130 -0
- package/src/group-form-entry-workflow/attendance-table/index.ts +1 -0
- package/src/group-form-entry-workflow/configurable-questions/ConfigurableQuestionsSection.tsx +41 -0
- package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.test.tsx +5 -5
- package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.tsx +14 -30
- package/src/group-form-entry-workflow/group-display-header/index.ts +1 -1
- package/src/group-form-entry-workflow/group-display-header/styles.scss +20 -20
- package/src/group-form-entry-workflow/group-search/CompactGroupResults.tsx +24 -35
- package/src/group-form-entry-workflow/group-search/CompactGroupSearch.tsx +13 -15
- package/src/group-form-entry-workflow/group-search/GroupSearch.tsx +22 -38
- package/src/group-form-entry-workflow/group-search/compact-group-result.scss +16 -17
- package/src/group-form-entry-workflow/group-search/compact-group-search.scss +7 -8
- package/src/group-form-entry-workflow/group-search/group-search.scss +20 -23
- package/src/group-form-entry-workflow/group-search-header/GroupSearchHeader.tsx +41 -18
- package/src/group-form-entry-workflow/group-search-header/index.ts +1 -1
- package/src/group-form-entry-workflow/group-search-header/styles.scss +8 -8
- package/src/group-form-entry-workflow/index.ts +1 -1
- package/src/group-form-entry-workflow/styles.scss +15 -17
- package/src/hooks/index.ts +7 -6
- package/src/hooks/useForm.ts +56 -0
- package/src/hooks/useFormState.ts +3 -3
- package/src/hooks/useGetAllForms.ts +7 -15
- package/src/hooks/useGetEncounter.ts +3 -3
- package/src/hooks/useGetPatient.ts +3 -3
- package/src/hooks/useGetPatients.ts +32 -0
- package/src/hooks/useGetSystemSetting.ts +36 -0
- package/src/hooks/useKeyPress.ts +5 -5
- package/src/hooks/usePostEndpoint.ts +16 -10
- package/src/hooks/useSearchEndpoint.ts +23 -40
- package/src/hooks/useStartVisit.ts +82 -0
- package/src/index.ts +12 -76
- package/src/patient-card/PatientCard.tsx +8 -20
- package/src/patient-card/index.ts +1 -1
- package/src/patient-card/styles.scss +3 -4
- package/src/routes.json +24 -0
- package/src/setup-tests.ts +1 -1
- package/src/types.ts +20 -0
- package/tools/i18next-parser.config.js +93 -0
- package/translations/am.json +75 -0
- package/translations/ar.json +75 -0
- package/translations/en.json +32 -11
- package/translations/es.json +75 -0
- package/translations/fr.json +75 -0
- package/translations/he.json +75 -0
- package/translations/km.json +75 -0
- package/turbo.json +18 -0
- package/webpack.config.js +1 -1
- package/dist/247.js +0 -1
- package/dist/255.js +0 -1
- package/dist/294.js +0 -2
- package/dist/32.js +0 -1
- package/dist/327.js +0 -1
- package/dist/403.js +0 -2
- package/dist/403.js.LICENSE.txt +0 -14
- package/dist/553.js +0 -2
- package/dist/553.js.LICENSE.txt +0 -14
- package/dist/569.js +0 -2
- package/dist/574.js +0 -1
- package/dist/595.js +0 -2
- package/dist/595.js.LICENSE.txt +0 -1
- package/dist/617.js +0 -1
- package/dist/68.js +0 -2
- package/dist/776.js +0 -1
- package/dist/804.js +0 -1
- package/dist/820.js +0 -1
- package/dist/906.js +0 -1
- package/dist/935.js +0 -2
- package/dist/openmrs-esm-fast-data-entry-app.old +0 -1
- package/src/declarations.d.tsx +0 -2
- /package/dist/{294.js.LICENSE.txt → 540.js.LICENSE.txt} +0 -0
- /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/
|
|
4
|
-
@
|
|
5
|
-
|
|
2
|
+
@use '@carbon/layout';
|
|
3
|
+
@use '@carbon/type';
|
|
6
4
|
|
|
7
5
|
.breadcrumbsContainer > div > div > nav {
|
|
8
|
-
background-color:
|
|
9
|
-
padding:
|
|
10
|
-
height:
|
|
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
|
|
27
|
+
padding: 0 layout.$spacing-04;
|
|
30
28
|
}
|
|
31
29
|
|
|
32
30
|
.selectPatientMessage {
|
|
33
|
-
@include type.type-style('
|
|
34
|
-
margin:
|
|
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:
|
|
42
|
-
column-gap:
|
|
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:
|
|
60
|
+
row-gap: layout.$spacing-05;
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
.patientCardsSection {
|
|
65
|
-
margin:
|
|
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:
|
|
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;
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import useGetAllForms from
|
|
2
|
-
import useGetPatient from
|
|
3
|
-
import useFormState from
|
|
4
|
-
import useGetEncounter from
|
|
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
|
|
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
|
|
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(
|
|
13
|
+
window.addEventListener('ampath-form-state', handler);
|
|
14
14
|
|
|
15
15
|
return () => {
|
|
16
|
-
window.removeEventListener(
|
|
16
|
+
window.removeEventListener('ampath-form-state', handler);
|
|
17
17
|
};
|
|
18
18
|
}, [formUuid]);
|
|
19
19
|
|
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
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
|
-
|
|
5
|
+
'(uuid,name,display,encounterType:(uuid,name,viewPrivilege,editPrivilege),version,published,retired,resources:(uuid,name,dataType,valueReference))';
|
|
10
6
|
|
|
11
|
-
const formEncounterUrl =
|
|
12
|
-
const formEncounterUrlPoc =
|
|
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
|
|
2
|
-
import useSWR from
|
|
1
|
+
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
+
import useSWR from 'swr';
|
|
3
3
|
|
|
4
|
-
const encounterUrl =
|
|
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
|
|
2
|
-
import { useEffect, useState } from
|
|
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
|
|
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;
|
package/src/hooks/useKeyPress.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useState } from
|
|
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(
|
|
20
|
-
window.addEventListener(
|
|
19
|
+
window.addEventListener('keydown', downHandler);
|
|
20
|
+
window.addEventListener('keyup', upHandler);
|
|
21
21
|
|
|
22
22
|
return () => {
|
|
23
|
-
window.removeEventListener(
|
|
24
|
-
window.removeEventListener(
|
|
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
|
|
2
|
-
import { useCallback, useState } from
|
|
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
|
-
|
|
35
|
-
|
|
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
|
-
|
|
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:
|
|
69
|
+
return usePostEndpoint({ endpointUrl: `${restBaseUrl}/visit` });
|
|
64
70
|
};
|
|
65
71
|
|
|
66
72
|
const usePostCohort = () => {
|
|
67
|
-
return usePostEndpoint({ endpointUrl:
|
|
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
|
|
2
|
-
import { useCallback, useMemo } from
|
|
3
|
-
import useSWRInfinite from
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
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;
|