@kenyaemr/esm-pharmacy-app 5.2.1-pre.724

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 (85) hide show
  1. package/.turbo/turbo-build.log +32 -0
  2. package/LICENSE.md +401 -0
  3. package/README.md +5 -0
  4. package/dist/102.js +1 -0
  5. package/dist/102.js.map +1 -0
  6. package/dist/130.js +2 -0
  7. package/dist/130.js.LICENSE.txt +3 -0
  8. package/dist/130.js.map +1 -0
  9. package/dist/152.js +1 -0
  10. package/dist/152.js.map +1 -0
  11. package/dist/255.js +2 -0
  12. package/dist/255.js.LICENSE.txt +9 -0
  13. package/dist/255.js.map +1 -0
  14. package/dist/303.js +1 -0
  15. package/dist/303.js.map +1 -0
  16. package/dist/341.js +1 -0
  17. package/dist/341.js.map +1 -0
  18. package/dist/368.js +1 -0
  19. package/dist/368.js.map +1 -0
  20. package/dist/383.js +1 -0
  21. package/dist/383.js.map +1 -0
  22. package/dist/419.js +1 -0
  23. package/dist/419.js.map +1 -0
  24. package/dist/515.js +1 -0
  25. package/dist/515.js.map +1 -0
  26. package/dist/574.js +1 -0
  27. package/dist/591.js +2 -0
  28. package/dist/591.js.LICENSE.txt +32 -0
  29. package/dist/591.js.map +1 -0
  30. package/dist/682.js +2 -0
  31. package/dist/682.js.LICENSE.txt +35 -0
  32. package/dist/682.js.map +1 -0
  33. package/dist/729.js +1 -0
  34. package/dist/729.js.map +1 -0
  35. package/dist/75.js +1 -0
  36. package/dist/75.js.map +1 -0
  37. package/dist/784.js +2 -0
  38. package/dist/784.js.LICENSE.txt +9 -0
  39. package/dist/784.js.map +1 -0
  40. package/dist/883.js +1 -0
  41. package/dist/883.js.map +1 -0
  42. package/dist/kenyaemr-esm-pharmacy-app.js +1 -0
  43. package/dist/kenyaemr-esm-pharmacy-app.js.buildmanifest.json +556 -0
  44. package/dist/kenyaemr-esm-pharmacy-app.js.map +1 -0
  45. package/dist/main.js +1 -0
  46. package/dist/main.js.map +1 -0
  47. package/dist/routes.json +1 -0
  48. package/jest.config.js +8 -0
  49. package/package.json +55 -0
  50. package/src/autosuggest/autosuggest.component.tsx +187 -0
  51. package/src/autosuggest/autosuggest.scss +62 -0
  52. package/src/config-schema.ts +43 -0
  53. package/src/declarations.d.ts +6 -0
  54. package/src/hooks/index.ts +4 -0
  55. package/src/hooks/usePharmacy.ts +17 -0
  56. package/src/hooks/usePharmacyPatients.ts +48 -0
  57. package/src/hooks/usePharmacyUsers.ts +43 -0
  58. package/src/hooks/useUserMappedPharmacies.ts +47 -0
  59. package/src/index.ts +41 -0
  60. package/src/pharamacy-forms/delete-confirm-dialog.modal.tsx +26 -0
  61. package/src/pharamacy-forms/pharamacy-assignment-form.workspace.tsx +121 -0
  62. package/src/pharamacy-forms/pharmacy-assignment-form.scss +125 -0
  63. package/src/pharmacy-component/pharmacy.component.tsx +14 -0
  64. package/src/pharmacy-detail/pharmacy-detail.component.tsx +14 -0
  65. package/src/pharmacy-detail-header/pharmacy-detail-header.component.tsx +41 -0
  66. package/src/pharmacy-header/pharmacy-header.component.tsx +36 -0
  67. package/src/pharmacy-header/pharmacy-header.scss +71 -0
  68. package/src/pharmacy-header/pharmacy-illustration.component.tsx +13 -0
  69. package/src/pharmacy-left-panel/pharmacy-left-panel-link.component.tsx +40 -0
  70. package/src/pharmacy-tables/pharmacy-patients.component.tsx +221 -0
  71. package/src/pharmacy-tables/pharmacy-table.component.tsx +164 -0
  72. package/src/pharmacy-tables/pharmacy-tables.scss +49 -0
  73. package/src/pharmacy-tables/pharmacy-users.component.tsx +197 -0
  74. package/src/pharmacy-tabs/pharmacy-tabs-component.tsx +28 -0
  75. package/src/pharmacy-tabs/pharmacy-tabs.scss +28 -0
  76. package/src/pharmacy.resources.ts +55 -0
  77. package/src/root.component.tsx +19 -0
  78. package/src/root.scss +15 -0
  79. package/src/root.test.tsx +5 -0
  80. package/src/routes.json +38 -0
  81. package/src/setup-tests.ts +1 -0
  82. package/src/types/index.ts +67 -0
  83. package/translations/en.json +27 -0
  84. package/tsconfig.json +5 -0
  85. package/webpack.config.js +1 -0
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@kenyaemr/esm-pharmacy-app",
3
+ "version": "5.2.1-pre.724",
4
+ "description": "pharmacy app for KenyaEMR",
5
+ "browser": "dist/kenyaemr-esm-pharmacy-app.js",
6
+ "main": "src/index.ts",
7
+ "source": true,
8
+ "license": "MPL-2.0",
9
+ "homepage": "https://github.com/palladiumkenya/kenyaemr-esm-core#readme",
10
+ "scripts": {
11
+ "start": "openmrs develop",
12
+ "serve": "webpack serve --mode=development",
13
+ "debug": "npm run serve",
14
+ "build": "webpack --mode production",
15
+ "analyze": "webpack --mode=production --env.analyze=true",
16
+ "lint": "eslint src --ext ts,tsx",
17
+ "typescript": "tsc",
18
+ "extract-translations": "i18next 'src/**/*.component.tsx' 'src/index.ts' --config ../../tools/i18next-parser.config.js",
19
+ "test": "cross-env TZ=UTC jest --config jest.config.js --verbose false --passWithNoTests",
20
+ "test:watch": "cross-env TZ=UTC jest --watch --config jest.config.js",
21
+ "coverage": "yarn test --coverage"
22
+ },
23
+ "browserslist": [
24
+ "extends browserslist-config-openmrs"
25
+ ],
26
+ "keywords": [
27
+ "openmrs"
28
+ ],
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/palladiumkenya/kenyaemr-esm-core#readme"
35
+ },
36
+ "bugs": {
37
+ "url": "https://github.com/palladiumkenya/kenyaemr-esm-core/issues"
38
+ },
39
+ "dependencies": {
40
+ "@carbon/react": "^1.42.1",
41
+ "lodash-es": "^4.17.15",
42
+ "react-to-print": "^2.14.13"
43
+ },
44
+ "peerDependencies": {
45
+ "@openmrs/esm-framework": "5.x",
46
+ "react": "^18.1.0",
47
+ "react-i18next": "11.x",
48
+ "react-router-dom": "6.x",
49
+ "swr": "2.x"
50
+ },
51
+ "devDependencies": {
52
+ "webpack": "^5.74.0"
53
+ },
54
+ "gitHead": "26fcec8e422b36202ce9874565ac44d9326f94da"
55
+ }
@@ -0,0 +1,187 @@
1
+ import React, { type HTMLAttributes, useEffect, useRef, useState } from 'react';
2
+ import { Layer, Search, type SearchProps } from '@carbon/react';
3
+ import classNames from 'classnames';
4
+ import styles from './autosuggest.scss';
5
+
6
+ // FIXME Temporarily included types from Carbon
7
+ type InputPropsBase = Omit<HTMLAttributes<HTMLInputElement>, 'onChange'>;
8
+
9
+ interface SearchProps extends InputPropsBase {
10
+ /**
11
+ * Specify an optional value for the `autocomplete` property on the underlying
12
+ * `<input>`, defaults to "off"
13
+ */
14
+ autoComplete?: string;
15
+
16
+ /**
17
+ * Specify an optional className to be applied to the container node
18
+ */
19
+ className?: string;
20
+
21
+ /**
22
+ * Specify a label to be read by screen readers on the "close" button
23
+ */
24
+ closeButtonLabelText?: string;
25
+
26
+ /**
27
+ * Optionally provide the default value of the `<input>`
28
+ */
29
+ defaultValue?: string | number;
30
+
31
+ /**
32
+ * Specify whether the `<input>` should be disabled
33
+ */
34
+ disabled?: boolean;
35
+
36
+ /**
37
+ * Specify whether or not ExpandableSearch should render expanded or not
38
+ */
39
+ isExpanded?: boolean;
40
+
41
+ /**
42
+ * Specify a custom `id` for the input
43
+ */
44
+ id?: string;
45
+
46
+ /**
47
+ * Provide the label text for the Search icon
48
+ */
49
+ labelText: React.ReactNode;
50
+
51
+ /**
52
+ * Optional callback called when the search value changes.
53
+ */
54
+ onChange?(e: { target: HTMLInputElement; type: 'change' }): void;
55
+
56
+ /**
57
+ * Optional callback called when the search value is cleared.
58
+ */
59
+ onClear?(): void;
60
+
61
+ /**
62
+ * Optional callback called when the magnifier icon is clicked in ExpandableSearch.
63
+ */
64
+ onExpand?(e: React.MouseEvent<HTMLDivElement> | React.KeyboardEvent<HTMLDivElement>): void;
65
+
66
+ /**
67
+ * Provide an optional placeholder text for the Search.
68
+ * Note: if the label and placeholder differ,
69
+ * VoiceOver on Mac will read both
70
+ */
71
+ placeholder?: string;
72
+
73
+ /**
74
+ * Rendered icon for the Search.
75
+ * Can be a React component class
76
+ */
77
+ renderIcon?: React.ComponentType | React.FunctionComponent;
78
+
79
+ /**
80
+ * Specify the role for the underlying `<input>`, defaults to `searchbox`
81
+ */
82
+ role?: string;
83
+
84
+ /**
85
+ * Specify the size of the Search
86
+ */
87
+ size?: 'sm' | 'md' | 'lg';
88
+
89
+ /**
90
+ * Optional prop to specify the type of the `<input>`
91
+ */
92
+ type?: string;
93
+
94
+ /**
95
+ * Specify the value of the `<input>`
96
+ */
97
+ value?: string | number;
98
+ }
99
+
100
+ interface AutosuggestProps extends SearchProps {
101
+ getDisplayValue: Function;
102
+ getFieldValue: Function;
103
+ getSearchResults: (query: string) => Promise<any>;
104
+ onSuggestionSelected: (field: string, value: string) => void;
105
+ invalid?: boolean | undefined;
106
+ invalidText?: string | undefined;
107
+ }
108
+
109
+ export const Autosuggest: React.FC<AutosuggestProps> = ({
110
+ getDisplayValue,
111
+ getFieldValue,
112
+ getSearchResults,
113
+ onSuggestionSelected,
114
+ invalid,
115
+ invalidText,
116
+ ...searchProps
117
+ }) => {
118
+ const [suggestions, setSuggestions] = useState([]);
119
+ const searchBox = useRef(null);
120
+ const wrapper = useRef(null);
121
+ const { id: name, labelText } = searchProps;
122
+
123
+ useEffect(() => {
124
+ document.addEventListener('mousedown', handleClickOutsideComponent);
125
+
126
+ return () => {
127
+ document.removeEventListener('mousedown', handleClickOutsideComponent);
128
+ };
129
+ }, [wrapper]);
130
+
131
+ const handleClickOutsideComponent = (e) => {
132
+ if (wrapper.current && !wrapper.current.contains(e.target)) {
133
+ setSuggestions([]);
134
+ }
135
+ };
136
+
137
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
138
+ const query = e.target.value;
139
+ onSuggestionSelected(name, undefined);
140
+
141
+ if (query) {
142
+ getSearchResults(query).then((suggestions) => {
143
+ setSuggestions(suggestions);
144
+ });
145
+ } else {
146
+ setSuggestions([]);
147
+ }
148
+ };
149
+
150
+ const handleClear = (e: React.ChangeEvent<HTMLInputElement>) => {
151
+ onSuggestionSelected(name, undefined);
152
+ };
153
+
154
+ const handleClick = (index: number) => {
155
+ const display = getDisplayValue(suggestions[index]);
156
+ const value = getFieldValue(suggestions[index]);
157
+ searchBox.current.value = display;
158
+ onSuggestionSelected(name, value);
159
+ setSuggestions([]);
160
+ };
161
+
162
+ return (
163
+ <div className={styles.autocomplete} ref={wrapper}>
164
+ <label className="cds--label">{labelText}</label>
165
+ <Layer className={classNames({ [styles.invalid]: invalid })}>
166
+ <Search
167
+ id="autosuggest"
168
+ onChange={handleChange}
169
+ onClear={handleClear}
170
+ ref={searchBox}
171
+ className={styles.autocompleteSearch}
172
+ {...searchProps}
173
+ />
174
+ </Layer>
175
+ {suggestions.length > 0 && (
176
+ <ul className={styles.suggestions}>
177
+ {suggestions.map((suggestion, index) => (
178
+ <li key={index} onClick={(e) => handleClick(index)} role="presentation">
179
+ {getDisplayValue(suggestion)}
180
+ </li>
181
+ ))}
182
+ </ul>
183
+ )}
184
+ {invalid ? <label className={classNames(styles.invalidMsg)}>{invalidText}</label> : <></>}
185
+ </div>
186
+ );
187
+ };
@@ -0,0 +1,62 @@
1
+ @use '@carbon/styles/scss/spacing';
2
+ @use '@carbon/styles/scss/type';
3
+ @import '~@openmrs/esm-styleguide/src/vars';
4
+
5
+ .label01 {
6
+ @include type.type-style('label-01');
7
+ }
8
+
9
+ .suggestions {
10
+ position: relative;
11
+ border-top-width: 0;
12
+ list-style: none;
13
+ margin-top: 0;
14
+ max-height: 143px;
15
+ overflow-y: auto;
16
+ padding-left: 0;
17
+ width: 100%;
18
+ position: absolute;
19
+ left: 0;
20
+ background-color: #fff;
21
+ margin-bottom: 20px;
22
+ z-index: 99;
23
+ }
24
+
25
+ .suggestions li {
26
+ padding: spacing.$spacing-05;
27
+ line-height: 1.29;
28
+ color: #525252;
29
+ border-bottom: 1px solid #8d8d8d;
30
+ }
31
+
32
+ .suggestions li:hover {
33
+ background-color: #e5e5e5;
34
+ color: #161616;
35
+ cursor: pointer;
36
+ }
37
+
38
+ .suggestions li:not(:last-of-type) {
39
+ border-bottom: 1px solid #999;
40
+ }
41
+
42
+ .autocomplete {
43
+ position: relative;
44
+ }
45
+
46
+ .autocompleteSearch {
47
+ width: 100%;
48
+ }
49
+
50
+ .suggestions a {
51
+ color: inherit;
52
+ text-decoration: none;
53
+ }
54
+
55
+ .invalid input {
56
+ outline: 2px solid var(--cds-support-error, #da1e28);
57
+ outline-offset: -2px;
58
+ }
59
+
60
+ .invalidMsg {
61
+ color: var(--cds-text-error, #da1e28);
62
+ }
@@ -0,0 +1,43 @@
1
+ import { Type, validator } from '@openmrs/esm-framework';
2
+
3
+ /**
4
+ * This is the config schema. It expects a configuration object which
5
+ * looks like this:
6
+ *
7
+ * ```json
8
+ * { "casualGreeting": true, "whoToGreet": ["Mom"] }
9
+ * ```
10
+ *
11
+ * In OpenMRS Microfrontends, all config parameters are optional. Thus,
12
+ * all elements must have a reasonable default. A good default is one
13
+ * that works well with the reference application.
14
+ *
15
+ * To understand the schema below, please read the configuration system
16
+ * documentation:
17
+ * https://openmrs.github.io/openmrs-esm-core/#/main/config
18
+ * Note especially the section "How do I make my module configurable?"
19
+ * https://openmrs.github.io/openmrs-esm-core/#/main/config?id=im-developing-an-esm-module-how-do-i-make-it-configurable
20
+ * and the Schema Reference
21
+ * https://openmrs.github.io/openmrs-esm-core/#/main/config?id=schema-reference
22
+ */
23
+ export const configSchema = {
24
+ casualGreeting: {
25
+ _type: Type.Boolean,
26
+ _default: false,
27
+ _description: 'Whether to use a casual greeting (or a formal one).',
28
+ },
29
+ whoToGreet: {
30
+ _type: Type.Array,
31
+ _default: ['World'],
32
+ _description: 'Who should be greeted. Names will be separated by a comma and space.',
33
+ _elements: {
34
+ _type: Type.String,
35
+ },
36
+ _validators: [validator((v) => v.length > 0, 'At least one person must be greeted.')],
37
+ },
38
+ };
39
+
40
+ export type Config = {
41
+ casualGreeting: boolean;
42
+ whoToGreet: Array<string>;
43
+ };
@@ -0,0 +1,6 @@
1
+ declare module '@carbon/react';
2
+ declare module '*.css';
3
+ declare module '*.scss';
4
+ declare module '*.png';
5
+
6
+ declare type SideNavProps = object;
@@ -0,0 +1,4 @@
1
+ export { default as useUserMappedPharmacies } from './useUserMappedPharmacies';
2
+ export { default as usePharmacy } from './usePharmacy';
3
+ export { default as usePharmacyPatients } from './usePharmacyPatients';
4
+ export { default as usePharmacyUsers } from './usePharmacyUsers';
@@ -0,0 +1,17 @@
1
+ import { FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import useSWR from 'swr';
3
+ import { Pharmacy } from '../types';
4
+
5
+ const usePharmacy = (pharmacyUuid: string) => {
6
+ const customeRepresentation = 'full';
7
+ const url = `${restBaseUrl}/location/${pharmacyUuid}?v=${customeRepresentation}`;
8
+ const { isLoading, error, data } = useSWR<FetchResponse<Pharmacy>>(url, openmrsFetch);
9
+
10
+ return {
11
+ isLoading,
12
+ error,
13
+ pharmacy: data?.data,
14
+ };
15
+ };
16
+
17
+ export default usePharmacy;
@@ -0,0 +1,48 @@
1
+ import { FetchResponse, formatDatetime, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import useSWR from 'swr';
3
+ import { PharamacyPatientMapping, PharmacyPatient } from '../types';
4
+
5
+ const usePharmacyPatients = (pharmacyUuid: string) => {
6
+ const url = `${restBaseUrl}/datafilter/search?type=org.openmrs.Patient`;
7
+
8
+ const fetchPharmacyPatients = async (url: string) => {
9
+ const abortController = new AbortController();
10
+
11
+ const response = await openmrsFetch(url, {
12
+ body: JSON.stringify({
13
+ entityIdentifier: '',
14
+ entityType: 'org.openmrs.Patient',
15
+ basisIdentifier: pharmacyUuid,
16
+ basisType: 'org.openmrs.Location',
17
+ }),
18
+ method: 'POST',
19
+ headers: {
20
+ 'Content-Type': 'application/json',
21
+ },
22
+ signal: abortController.signal,
23
+ });
24
+ return response;
25
+ };
26
+
27
+ const { data, isLoading, error } = useSWR<FetchResponse<Array<PharamacyPatientMapping>>>(url, fetchPharmacyPatients);
28
+
29
+ return {
30
+ isLoading,
31
+ error,
32
+ patients: (data?.data ?? []).map(extractData),
33
+ };
34
+ };
35
+
36
+ const extractData = (mapping: PharamacyPatientMapping) => {
37
+ return {
38
+ name: mapping.entity.name,
39
+ uuid: mapping.entity.uuid,
40
+ age: mapping.entity.age,
41
+ gender: mapping.entity.gender,
42
+ telephoneContact: mapping.entity['Telephone contact'],
43
+ openmrsId: mapping.entity.OpenMRSID,
44
+ dateMapped: formatDatetime(new Date(mapping.dateCreated), { mode: 'standard', noToday: true }),
45
+ } as PharmacyPatient;
46
+ };
47
+
48
+ export default usePharmacyPatients;
@@ -0,0 +1,43 @@
1
+ import { FetchResponse, formatDatetime, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import useSWR from 'swr';
3
+ import { PhamarcyUserMapping, PharmacyUser } from '../types';
4
+
5
+ const usePharmacyUsers = (pharmacyUuid: string) => {
6
+ const customPresentation = 'full';
7
+ const url = `${restBaseUrl}/datafilter/search?type=org.openmrs.User`;
8
+ const fetchPharmacyUsers = async (url: string) => {
9
+ const abortController = new AbortController();
10
+
11
+ const response = await openmrsFetch(url, {
12
+ body: JSON.stringify({
13
+ entityIdentifier: '',
14
+ entityType: 'org.openmrs.User',
15
+ basisIdentifier: pharmacyUuid,
16
+ basisType: 'org.openmrs.Location',
17
+ }),
18
+ method: 'POST',
19
+ headers: {
20
+ 'Content-Type': 'application/json',
21
+ },
22
+ signal: abortController.signal,
23
+ });
24
+ return response;
25
+ };
26
+ const { data, isLoading, error } = useSWR<FetchResponse<PhamarcyUserMapping[]>>(url, fetchPharmacyUsers);
27
+
28
+ return {
29
+ isLoading,
30
+ error,
31
+ users: (data?.data ?? []).map(extractData),
32
+ };
33
+ };
34
+
35
+ const extractData = (mapping: PhamarcyUserMapping) => {
36
+ return {
37
+ name: mapping.entity.name,
38
+ uuid: mapping.entity.uuid,
39
+ dateMapped: formatDatetime(new Date(mapping.dateCreated), { mode: 'standard', noToday: true }),
40
+ } as PharmacyUser;
41
+ };
42
+
43
+ export default usePharmacyUsers;
@@ -0,0 +1,47 @@
1
+ import { FetchResponse, formatDatetime, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import useSWR from 'swr';
3
+ import { PhamarcyUserMapping, Pharmacy } from '../types';
4
+
5
+ const extractPharmacyData = (mapping: PhamarcyUserMapping) => {
6
+ return {
7
+ uuid: mapping.basis.uuid,
8
+ name: mapping.basis.name,
9
+ dateMaped: formatDatetime(new Date(mapping.dateCreated), { mode: 'standard', noToday: true }),
10
+ cityVillage: mapping.basis.cityVillage,
11
+ countyDistrict: mapping.basis.countyDistrict,
12
+ mflCode: mapping.basis['Master Facility Code'],
13
+ } as Pharmacy;
14
+ };
15
+
16
+ const useUserMappedPharmacies = (userUuid: string) => {
17
+ const url = `${restBaseUrl}/datafilter/search`;
18
+
19
+ const fetchUserPharmacies = async (url: string) => {
20
+ const abortController = new AbortController();
21
+
22
+ const response = await openmrsFetch(url, {
23
+ body: JSON.stringify({
24
+ entityIdentifier: userUuid,
25
+ entityType: 'org.openmrs.User',
26
+ basisIdentifier: '',
27
+ basisType: 'org.openmrs.Location',
28
+ }),
29
+ method: 'POST',
30
+ headers: {
31
+ 'Content-Type': 'application/json',
32
+ },
33
+ signal: abortController.signal,
34
+ });
35
+ return response;
36
+ };
37
+
38
+ const { isLoading, error, data } = useSWR<FetchResponse<PhamarcyUserMapping[]>>(url, fetchUserPharmacies);
39
+
40
+ return {
41
+ isLoading,
42
+ error,
43
+ pharmacies: (data?.data ?? []).map(extractPharmacyData),
44
+ };
45
+ };
46
+
47
+ export default useUserMappedPharmacies;
package/src/index.ts ADDED
@@ -0,0 +1,41 @@
1
+ import { getAsyncLifecycle, defineConfigSchema, getSyncLifecycle, registerBreadcrumbs } from '@openmrs/esm-framework';
2
+ import { configSchema } from './config-schema';
3
+ import { createLeftPanelLink } from './pharmacy-left-panel/pharmacy-left-panel-link.component';
4
+ const moduleName = '@kenyaemr/esm-pharmacy-app';
5
+
6
+ const options = {
7
+ featureName: 'esm-pharmacy-app',
8
+ moduleName,
9
+ };
10
+
11
+ export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
12
+
13
+ export function startupApp() {
14
+ const pharmacyBasepath = `${window.spaBase}/home/pharmacy`;
15
+
16
+ defineConfigSchema(moduleName, configSchema);
17
+ registerBreadcrumbs([
18
+ {
19
+ title: 'pharmacy',
20
+ path: pharmacyBasepath,
21
+ parent: `${window.spaBase}/home`,
22
+ },
23
+ ]);
24
+ }
25
+
26
+ export const root = getAsyncLifecycle(() => import('./root.component'), options);
27
+ export const pharmacyAssignmentForm = getAsyncLifecycle(
28
+ () => import('./pharamacy-forms/pharamacy-assignment-form.workspace'),
29
+ options,
30
+ );
31
+ export const pharmacyDeleteConfirmDialog = getAsyncLifecycle(
32
+ () => import('./pharamacy-forms/delete-confirm-dialog.modal'),
33
+ options,
34
+ );
35
+ export const pharmacyDashboardLink = getSyncLifecycle(
36
+ createLeftPanelLink({
37
+ name: 'pharmacy',
38
+ title: 'Community Pharmacy',
39
+ }),
40
+ options,
41
+ );
@@ -0,0 +1,26 @@
1
+ import { Button, ButtonSet, ModalBody, ModalFooter, ModalHeader } from '@carbon/react';
2
+ import React from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+
5
+ const DeleteConfirmDialog = ({ onClose, onDelete }) => {
6
+ const { t } = useTranslation();
7
+
8
+ return (
9
+ <React.Fragment>
10
+ <ModalHeader closeModal={onClose}>{t('warning', 'Warning!')}</ModalHeader>
11
+ <ModalBody>Are you sure you want to revoke access?</ModalBody>
12
+ <ModalFooter>
13
+ <ButtonSet>
14
+ <Button kind="secondary" onClick={onClose}>
15
+ Cancel
16
+ </Button>
17
+ <Button kind="primary" onClick={onDelete}>
18
+ Revoke
19
+ </Button>
20
+ </ButtonSet>
21
+ </ModalFooter>
22
+ </React.Fragment>
23
+ );
24
+ };
25
+
26
+ export default DeleteConfirmDialog;