@digihmis/esm-administration-app 1.0.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 (206) hide show
  1. package/README.md +4 -0
  2. package/dist/101.js +1 -0
  3. package/dist/101.js.map +1 -0
  4. package/dist/117.js +1 -0
  5. package/dist/117.js.map +1 -0
  6. package/dist/132.js +1 -0
  7. package/dist/132.js.map +1 -0
  8. package/dist/15.js +1 -0
  9. package/dist/15.js.map +1 -0
  10. package/dist/152.js +1 -0
  11. package/dist/152.js.map +1 -0
  12. package/dist/153.js +1 -0
  13. package/dist/153.js.map +1 -0
  14. package/dist/190.js +1 -0
  15. package/dist/190.js.map +1 -0
  16. package/dist/209.js +1 -0
  17. package/dist/209.js.map +1 -0
  18. package/dist/266.js +1 -0
  19. package/dist/266.js.map +1 -0
  20. package/dist/317.js +1 -0
  21. package/dist/317.js.map +1 -0
  22. package/dist/349.js +1 -0
  23. package/dist/349.js.map +1 -0
  24. package/dist/371.js +1 -0
  25. package/dist/371.js.map +1 -0
  26. package/dist/378.js +1 -0
  27. package/dist/378.js.map +1 -0
  28. package/dist/394.js +1 -0
  29. package/dist/394.js.map +1 -0
  30. package/dist/442.js +1 -0
  31. package/dist/442.js.map +1 -0
  32. package/dist/45.js +1 -0
  33. package/dist/45.js.map +1 -0
  34. package/dist/454.js +1 -0
  35. package/dist/454.js.map +1 -0
  36. package/dist/466.js +1 -0
  37. package/dist/466.js.map +1 -0
  38. package/dist/482.js +1 -0
  39. package/dist/482.js.map +1 -0
  40. package/dist/501.js +1 -0
  41. package/dist/501.js.map +1 -0
  42. package/dist/508.js +1 -0
  43. package/dist/508.js.map +1 -0
  44. package/dist/578.js +1 -0
  45. package/dist/578.js.map +1 -0
  46. package/dist/598.js +1 -0
  47. package/dist/598.js.map +1 -0
  48. package/dist/606.js +1 -0
  49. package/dist/606.js.map +1 -0
  50. package/dist/61.js +1 -0
  51. package/dist/61.js.map +1 -0
  52. package/dist/640.js +1 -0
  53. package/dist/640.js.map +1 -0
  54. package/dist/685.js +1 -0
  55. package/dist/685.js.map +1 -0
  56. package/dist/689.js +1 -0
  57. package/dist/689.js.map +1 -0
  58. package/dist/709.js +1 -0
  59. package/dist/709.js.map +1 -0
  60. package/dist/712.js +1 -0
  61. package/dist/712.js.map +1 -0
  62. package/dist/720.js +1 -0
  63. package/dist/720.js.map +1 -0
  64. package/dist/737.js +12 -0
  65. package/dist/737.js.map +1 -0
  66. package/dist/742.js +1 -0
  67. package/dist/742.js.map +1 -0
  68. package/dist/747.js +1 -0
  69. package/dist/747.js.map +1 -0
  70. package/dist/771.js +1 -0
  71. package/dist/771.js.map +1 -0
  72. package/dist/806.js +1 -0
  73. package/dist/806.js.map +1 -0
  74. package/dist/912.js +1 -0
  75. package/dist/912.js.map +1 -0
  76. package/dist/913.js +1 -0
  77. package/dist/913.js.map +1 -0
  78. package/dist/916.js +15 -0
  79. package/dist/916.js.map +1 -0
  80. package/dist/940.js +1 -0
  81. package/dist/940.js.map +1 -0
  82. package/dist/digihmis-esm-administration-app.js +6 -0
  83. package/dist/digihmis-esm-administration-app.js.buildmanifest.json +1100 -0
  84. package/dist/digihmis-esm-administration-app.js.map +1 -0
  85. package/dist/main.js +17 -0
  86. package/dist/main.js.map +1 -0
  87. package/dist/routes.json +1 -0
  88. package/increment-version.js +17 -0
  89. package/jest.config.js +26 -0
  90. package/package.json +51 -0
  91. package/release-version.js +16 -0
  92. package/rspack.config.js +1 -0
  93. package/src/bed-management/bed-management.component.tsx +19 -0
  94. package/src/bed-management/bed-management.scss +0 -0
  95. package/src/billing-management/billing-charge-items/billing-charge-items-modal/billing-charge-items.modal.tsx +79 -0
  96. package/src/billing-management/billing-charge-items/billing-charge-items-modal/billing-charge-items.resource.ts +11 -0
  97. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-item.workspace.tsx +212 -0
  98. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-items.resource.ts +51 -0
  99. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-service.workspace.tsx +296 -0
  100. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/components/concept-search.component.tsx +67 -0
  101. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/components/price.component.tsx +81 -0
  102. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/components/stock-search.component.tsx +107 -0
  103. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/global/billing-charge-commodity.scss +61 -0
  104. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/global/billing-charge-items.scss +59 -0
  105. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/schemas/form-schemas.ts +33 -0
  106. package/src/billing-management/billing-charge-items/billing-charge-items.component.tsx +222 -0
  107. package/src/billing-management/billing-charge-items/billing-charge-items.resource.ts +20 -0
  108. package/src/billing-management/billing-charge-items/billing-charge-items.scss +84 -0
  109. package/src/billing-management/billing-charge-items/type/index.ts +88 -0
  110. package/src/billing-management/billing-charge-items/utils/index.ts +96 -0
  111. package/src/billing-management/billing-management.component.tsx +21 -0
  112. package/src/billing-management/billing-management.scss +0 -0
  113. package/src/billing-management/billing-payment-modes/billing-payment-modes-modal/billing-delete-payment-modes.modal.scss +28 -0
  114. package/src/billing-management/billing-payment-modes/billing-payment-modes-modal/billing-delete-payment-modes.modal.tsx +67 -0
  115. package/src/billing-management/billing-payment-modes/billing-payment-modes-modal/delete-payment-mode.test.tsx +56 -0
  116. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes-form-schema.ts +52 -0
  117. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.resource.ts +35 -0
  118. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.workspace.scss +33 -0
  119. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.workspace.test.tsx +239 -0
  120. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.workspace.tsx +218 -0
  121. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/payment-attributes/payment-mode-attributes.component.tsx +156 -0
  122. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/payment-attributes/payment-mode-attributes.scss +10 -0
  123. package/src/billing-management/billing-payment-modes/billing-payment-modes.component.tsx +243 -0
  124. package/src/billing-management/billing-payment-modes/billing-payment-modes.resource.ts +23 -0
  125. package/src/billing-management/billing-payment-modes/billing-payment-modes.scss +140 -0
  126. package/src/billing-management/billing-payment-modes/type/index.ts +42 -0
  127. package/src/billing-management/billing-payment-points/billing-payment-point-modal/billing-delete-payment-modes.modal.scss +28 -0
  128. package/src/billing-management/billing-payment-points/billing-payment-point-modal/billing-delete-payment-point.modal.tsx +72 -0
  129. package/src/billing-management/billing-payment-points/billing-payment-point-modal/delete-payment-point.test.tsx +56 -0
  130. package/src/billing-management/billing-payment-points/billing-payment-point.component.tsx +202 -0
  131. package/src/billing-management/billing-payment-points/billing-payment-point.resource.ts +16 -0
  132. package/src/billing-management/billing-payment-points/billing-payment-point.scss +0 -0
  133. package/src/billing-management/billing-payment-points/billing-payment-points-workspace/billing-payment-point.resource.ts +39 -0
  134. package/src/billing-management/billing-payment-points/billing-payment-points-workspace/billing-payment-point.workspace.scss +33 -0
  135. package/src/billing-management/billing-payment-points/billing-payment-points-workspace/billing-payment-points.workspace.tsx +194 -0
  136. package/src/billing-management/billing-payment-points/type/index.ts +35 -0
  137. package/src/billing-management/billing-tabs/billing-tabs.component.scss +15 -0
  138. package/src/billing-management/billing-tabs/billing-tabs.component.tsx +36 -0
  139. package/src/components/custom-icon-wrapper/custom-icon-wrapper.component.tsx +17 -0
  140. package/src/components/custom-page-header/custom-page-header.component.tsx +38 -0
  141. package/src/components/custom-page-header/custom-page-header.scss +76 -0
  142. package/src/config-schema.ts +142 -0
  143. package/src/constant/index.ts +1 -0
  144. package/src/dashboard.meta.ts +47 -0
  145. package/src/declarations.d.ts +6 -0
  146. package/src/form-builder/form-builder.component.tsx +19 -0
  147. package/src/form-builder/form-builder.scss +0 -0
  148. package/src/hooks/useConcept.ts +13 -0
  149. package/src/hooks/useQueues.ts +22 -0
  150. package/src/hooks/useSystemSetting.ts +18 -0
  151. package/src/index.ts +133 -0
  152. package/src/left-panel/left-panel.component.tsx +49 -0
  153. package/src/left-panel/left-panel.scss +13 -0
  154. package/src/location-management/components/auto-suggest/autosuggest.component.tsx +149 -0
  155. package/src/location-management/components/auto-suggest/autosuggest.scss +61 -0
  156. package/src/location-management/components/auto-suggest/location-autosuggest.component.tsx +97 -0
  157. package/src/location-management/components/auto-suggest/location-autosuggest.scss +48 -0
  158. package/src/location-management/components/custom-results-tile/results-tile.component.tsx +43 -0
  159. package/src/location-management/components/custom-results-tile/results-tile.scss +86 -0
  160. package/src/location-management/forms/add-location/add-location.workspace.scss +71 -0
  161. package/src/location-management/forms/add-location/add-location.workspace.tsx +199 -0
  162. package/src/location-management/forms/search-location/search-location.workspace.scss +71 -0
  163. package/src/location-management/forms/search-location/search-location.workspace.tsx +214 -0
  164. package/src/location-management/helpers/index.ts +33 -0
  165. package/src/location-management/hooks/UseFacilityLocations.ts +12 -0
  166. package/src/location-management/hooks/useLocation.ts +18 -0
  167. package/src/location-management/hooks/useLocationTags.ts +15 -0
  168. package/src/location-management/location-management-dashboard.component.tsx +21 -0
  169. package/src/location-management/location-management-dashboard.scss +3 -0
  170. package/src/location-management/tables/locations-table.component.tsx +242 -0
  171. package/src/location-management/tables/locations-table.resource.ts +26 -0
  172. package/src/location-management/tables/locations-table.scss +114 -0
  173. package/src/location-management/types/index.ts +120 -0
  174. package/src/queue-management/queue-management-dashboard.component.tsx +23 -0
  175. package/src/queue-management/queue-management-dashboard.scss +8 -0
  176. package/src/queue-management/queue-management-table/queue-management-table.component.tsx +296 -0
  177. package/src/queue-management/queue-management-table/queue-management-table.scss +78 -0
  178. package/src/queue-management/queue-management-table/queue-management.resource.ts +39 -0
  179. package/src/queue-management/queue-management-workspace/queue-room/queue-room-form.scss +56 -0
  180. package/src/queue-management/queue-management-workspace/queue-room/queue-room-form.test.tsx +82 -0
  181. package/src/queue-management/queue-management-workspace/queue-room/queue-room-form.workspace.tsx +169 -0
  182. package/src/queue-management/queue-management-workspace/queue-room/queue-room.resource.ts +20 -0
  183. package/src/queue-management/queue-management-workspace/queue-service/queue-service-form.scss +61 -0
  184. package/src/queue-management/queue-management-workspace/queue-service/queue-service-form.test.tsx +127 -0
  185. package/src/queue-management/queue-management-workspace/queue-service/queue-service-form.workspace.tsx +178 -0
  186. package/src/queue-management/queue-management-workspace/queue-service/queue-service.resource.ts +55 -0
  187. package/src/queue-management/queue-types/index.ts +33 -0
  188. package/src/routes.json +157 -0
  189. package/src/setup-tests.ts +1 -0
  190. package/src/system-info/system-info.component.tsx +338 -0
  191. package/src/system-info/system-info.resource.ts +40 -0
  192. package/src/system-info/system-info.scss +622 -0
  193. package/src/type/index.ts +6 -0
  194. package/translations/am.json +111 -0
  195. package/translations/ar.json +115 -0
  196. package/translations/en.json +111 -0
  197. package/translations/es.json +112 -0
  198. package/translations/fr.json +112 -0
  199. package/translations/he.json +112 -0
  200. package/translations/km.json +110 -0
  201. package/translations/pt.json +112 -0
  202. package/translations/sw.json +111 -0
  203. package/translations/vi.json +110 -0
  204. package/translations/zh.json +110 -0
  205. package/tsconfig.json +5 -0
  206. package/version.js +27 -0
@@ -0,0 +1 @@
1
+ {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"fhir2":">=1.2","webservices.rest":"^2.24.0"},"extensions":[{"name":"system-info-management-dashboard-link","slot":"administration-dashboard-slot","component":"systemInfoLeftPanelLink","meta":{"name":"system-info-management","slot":"system-info-management-homepage-dashboard-slot","title":"System Info"}},{"name":"queue-management-dashboard-link","slot":"administration-dashboard-slot","component":"queueLeftPanelLink","meta":{"name":"queue-management","slot":"queue-management-homepage-dashboard-slot","title":"Queue Management"}},{"name":"location-management-dashboard-link","slot":"administration-dashboard-slot","component":"locationLeftPanelLink","meta":{"name":"location-management","slot":"location-management-homepage-dashboard-slot","title":"Location Management"}},{"name":"bed-management-dashboard-link","slot":"administration-dashboard-slot","component":"bedLeftPanelLink","meta":{"name":"bed-management","slot":"bed-management-homepage-dashboard-slot","title":"Bed Management"}},{"name":"form-builder-dashboard-link","slot":"administration-dashboard-slot","component":"formBuilderLeftPanelLink","meta":{"name":"form-builder","slot":"form-builder-homepage-dashboard-slot","title":"Form Builder"}},{"name":"billing-management-dashboard-link","slot":"administration-dashboard-slot","component":"billingLeftPanelLink","meta":{"name":"billing-management","slot":"billing-management-homepage-dashboard-slot","title":"Billing Management"}},{"name":"queue-management-dashboard-content","slot":"queue-management-homepage-dashboard-slot","component":"queueManagementDashboard"},{"name":"location-management-dashboard-content","slot":"location-management-homepage-dashboard-slot","component":"locationManagementDashboard"},{"name":"bed-management-dashboard-content","slot":"bed-management-homepage-dashboard-slot","component":"bedManagementDashboard"},{"name":"form-builder-dashboard-content","slot":"form-builder-homepage-dashboard-slot","component":"formBuilderDashboard"},{"name":"billing-management-dashboard-content","slot":"billing-management-homepage-dashboard-slot","component":"billingManagementDashboard"},{"name":"system-info-management-dashboard-content","slot":"system-info-management-homepage-dashboard-slot","component":"systemInfoDashboard"}],"workspaces":[{"name":"service-queues-service-form","title":"addNewQueueService","component":"addNewQueueServiceWorkspace","type":"service-queues"},{"name":"service-queues-room-workspace","title":"addNewQueueServiceRoom","component":"addNewQueueServiceRoomWorkspace","type":"service-queues"},{"name":"add-location-workspace","title":"addNewLocationWorkspace","component":"addNewLocationWorkspace","type":"location-management"},{"name":"search-location-workspace","title":"searchLocationWorkspace","component":"searchLocationWorkspace","type":"location-management"},{"name":"payment-mode-workspace","title":"paymentModeWorkspace","component":"paymentModeWorkspace","type":"billing-management"},{"name":"payment-point-workspace","title":"paymentPointWorkspace","component":"paymentPointWorkspace","type":"billing-management"},{"name":"billing-charge-service-workspace","title":"addServiceItem","component":"billableServiceForm","type":"billing-management"},{"name":"billing-charge-item-workspace","title":"addCommodityItem","component":"commodityForm","type":"billing-management"}],"modals":[{"name":"delete-payment-mode-modal","component":"deletePaymentModeModal"},{"name":"delete-payment-point-modal","component":"deletePaymentPointModal"},{"name":"delete-billable-service-modal","component":"deleteBillableService"}],"version":"1.0.0"}
@@ -0,0 +1,17 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ // Read the package.json file
5
+ const packageJsonPath = path.join(__dirname, 'package.json');
6
+ const packageJson = require(packageJsonPath);
7
+
8
+ // Increment the version
9
+ const [major, minor, patch] = packageJson.version.split('.').map(Number);
10
+ const newVersion = `${major}.${minor}.${patch + 1}`;
11
+
12
+ // Update the package.json file with the new version
13
+ packageJson.version = newVersion;
14
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
15
+
16
+ // eslint-disable-next-line no-console
17
+ console.log(`Version incremented to ${newVersion}`);
package/jest.config.js ADDED
@@ -0,0 +1,26 @@
1
+ /** @type {import('jest').Config} */
2
+ module.exports = {
3
+ clearMocks: true,
4
+ transform: {
5
+ '^.+\\.[jt]sx?$': ['@swc/jest'],
6
+ },
7
+ transformIgnorePatterns: ['/node_modules/(?!@openmrs|.+\\.pnp\\.[^\\/]+$)'],
8
+ moduleNameMapper: {
9
+ '\\.(s?css)$': 'identity-obj-proxy',
10
+ '@openmrs/esm-framework': '@openmrs/esm-framework/mock',
11
+ 'lodash-es': 'lodash',
12
+ '^dexie$': require.resolve('dexie'),
13
+ },
14
+ collectCoverageFrom: [
15
+ '**/src/**/*.tsx',
16
+ '!**/node_modules/**',
17
+ '!**/vendor/**',
18
+ '!**/src/**/*.test.*',
19
+ '!**/src/declarations.d.ts',
20
+ ],
21
+ setupFilesAfterEnv: ['<rootDir>/setupTests.ts'],
22
+ testEnvironment: 'jsdom',
23
+ testEnvironmentOptions: {
24
+ url: 'http://localhost/',
25
+ },
26
+ };
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@digihmis/esm-administration-app",
3
+ "version": "1.0.0",
4
+ "description": "Administration microfrontend for the OpenMRS SPA",
5
+ "browser": "dist/digihmis-esm-administration-app.js",
6
+ "main": "src/index.ts",
7
+ "source": true,
8
+ "license": "MPL-2.0",
9
+ "homepage": "https://github.com/its-kios09/DigiHMIS-apps#readme",
10
+ "scripts": {
11
+ "analyze": "rspack --mode=production --env analyze=true",
12
+ "build": "node version.js && rspack --mode=production && node increment-version.js",
13
+ "coverage": "yarn test --coverage",
14
+ "debug": "npm run serve",
15
+ "extract-translations": "i18next 'src/**/*.component.tsx' 'src/index.ts' --config ../../tools/i18next-parser.config.js",
16
+ "lint": "eslint src --ext ts,tsx",
17
+ "serve": "rspack serve --mode=development",
18
+ "start": "openmrs develop",
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
+ "typescript": "tsc"
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/its-kios09/DigiHMIS-apps.git#readme"
35
+ },
36
+ "bugs": {
37
+ "url": "https://github.com/its-kios09/DigiHMIS-apps/issues"
38
+ },
39
+ "dependencies": {
40
+ "lodash-es": "^4.17.15",
41
+ "react-to-print": "2.14.13"
42
+ },
43
+ "peerDependencies": {
44
+ "@carbon/react": "1.x",
45
+ "@openmrs/esm-framework": "8.x",
46
+ "react": "^18.1.0",
47
+ "react-i18next": "16.x",
48
+ "react-router-dom": "6.x",
49
+ "swr": "2.x"
50
+ }
51
+ }
@@ -0,0 +1,16 @@
1
+
2
+ // IMPORTANT: THIS FILE IS AUTO GENERATED! DO NOT MANUALLY EDIT OR CHECKIN!
3
+ /* tslint:disable */
4
+ export const VERSION = {
5
+ "dirty": true,
6
+ "raw": "3342d5c-dirty",
7
+ "hash": "3342d5c",
8
+ "distance": null,
9
+ "tag": null,
10
+ "semver": null,
11
+ "suffix": "3342d5c-dirty",
12
+ "semverString": null,
13
+ "version": "1.0.0",
14
+ "buildDate": "2026-07-27T23:03:38.929Z"
15
+ };
16
+ /* tslint:enable */
@@ -0,0 +1 @@
1
+ module.exports = require('../../tools/rs-pack-code-spliting');
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { ExtensionSlot, useConfig } from '@openmrs/esm-framework';
3
+ import styles from './bed-management.scss';
4
+ import { CustomPageHeader } from '../components/custom-page-header/custom-page-header.component';
5
+ import { ConfigObject } from '../config-schema';
6
+ import { useTranslation } from 'react-i18next';
7
+
8
+ const BedManagementDashboard: React.FC = () => {
9
+ const { t } = useTranslation();
10
+ const { inpatientIcon } = useConfig<ConfigObject>();
11
+
12
+ return (
13
+ <div className={styles.dashboardContainer}>
14
+ <CustomPageHeader subTitle={t('configureBed', 'Configure wards')} iconSrc={inpatientIcon.src} />
15
+ </div>
16
+ );
17
+ };
18
+
19
+ export default BedManagementDashboard;
File without changes
@@ -0,0 +1,79 @@
1
+ import React from 'react';
2
+ import { ModalBody, ModalFooter, Button, InlineLoading, ModalHeader } from '@carbon/react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { showSnackbar, restBaseUrl } from '@openmrs/esm-framework';
5
+ import { mutate } from 'swr';
6
+ import { deleteBillableService } from './billing-charge-items.resource';
7
+ import { type ChargeItems } from '../type';
8
+
9
+ type DeleteBillableServiceModalProps = {
10
+ closeModal: () => void;
11
+ chargeableItem: ChargeItems;
12
+ };
13
+
14
+ const DeleteBillableServiceModal: React.FC<DeleteBillableServiceModalProps> = ({ closeModal, chargeableItem }) => {
15
+ const [isDeleting, setIsDeleting] = React.useState(false);
16
+ const { t } = useTranslation();
17
+
18
+ const handleMutation = () => {
19
+ const url = `${restBaseUrl}/cashier/billableService`;
20
+ mutate((key) => typeof key === 'string' && key.startsWith(url), undefined, { revalidate: true });
21
+ };
22
+
23
+ const handleDelete = () => {
24
+ setIsDeleting(true);
25
+ const chargeableItemUuid = chargeableItem?.uuid;
26
+ if (chargeableItemUuid) {
27
+ deleteBillableService(chargeableItemUuid)
28
+ .then(() => {
29
+ showSnackbar({
30
+ title: t('deleteChargeableItemSuccess', 'Chargeable item deleted successfully'),
31
+ subtitle: t('deleteChargeableItemSuccessMessage', 'The chargeable item has been deleted successfully.'),
32
+ kind: 'success',
33
+ isLowContrast: true,
34
+ timeoutInMs: 5000,
35
+ });
36
+ handleMutation();
37
+ closeModal();
38
+ })
39
+ .catch((error) => {
40
+ showSnackbar({
41
+ title: t('deleteChargeableItemError', 'Error deleting chargeable item'),
42
+ subtitle: t('deleteChargeableItemErrorMessage', 'An error occurred while deleting the chargeable item.'),
43
+ isLowContrast: true,
44
+ timeoutInMs: 5000,
45
+ kind: 'error',
46
+ });
47
+ })
48
+ .finally(() => {
49
+ setIsDeleting(false);
50
+ });
51
+ }
52
+ };
53
+ return (
54
+ <>
55
+ <ModalHeader closeModal={closeModal} title={t('deleteChargeableItems', 'Delete Chargeable Item')} />
56
+ <ModalBody>
57
+ <p>
58
+ {t('deleteChargeableItemMessage', 'Are you sure you want to delete the chargeable item {{name}}?', {
59
+ name: chargeableItem?.name,
60
+ })}
61
+ </p>
62
+ </ModalBody>
63
+ <ModalFooter>
64
+ <Button kind="secondary" onClick={closeModal}>
65
+ {t('cancel', 'Cancel')}
66
+ </Button>
67
+ <Button kind="danger" onClick={handleDelete} disabled={isDeleting}>
68
+ {isDeleting ? (
69
+ <InlineLoading description={t('deleting', 'Deleting') + '...'} />
70
+ ) : (
71
+ <span>{t('delete', 'Delete')}</span>
72
+ )}
73
+ </Button>
74
+ </ModalFooter>
75
+ </>
76
+ );
77
+ };
78
+
79
+ export default DeleteBillableServiceModal;
@@ -0,0 +1,11 @@
1
+ import { openmrsFetch } from '@openmrs/esm-framework';
2
+
3
+ export const deleteBillableService = (uuid: string) => {
4
+ const url = `/ws/rest/v1/cashier/billableService/${uuid}`;
5
+ return openmrsFetch(url, {
6
+ method: 'DELETE',
7
+ headers: {
8
+ 'Content-Type': 'application/json',
9
+ },
10
+ });
11
+ };
@@ -0,0 +1,212 @@
1
+ import React, { useEffect, useMemo } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { ButtonSet, Button, Stack, Toggle, InlineNotification, InlineLoading } from '@carbon/react';
4
+ import { Add } from '@carbon/react/icons';
5
+ import { useForm, FormProvider, useFieldArray, Controller } from 'react-hook-form';
6
+
7
+ import { type DefaultWorkspaceProps, useLayoutType, ResponsiveWrapper, showSnackbar, restBaseUrl } from '@openmrs/esm-framework';
8
+ import styles from './global/billing-charge-commodity.scss';
9
+ import classNames from 'classnames';
10
+ import { zodResolver } from '@hookform/resolvers/zod';
11
+ import PriceField from './components/price.component';
12
+ import { billableFormSchema, BillableFormSchema } from './schemas/form-schemas';
13
+ import { handleMutation } from '../../billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.resource';
14
+ import { formatBillableServicePayloadForSubmission, mapInputToPayloadSchema } from '../utils';
15
+ import { createBillableService } from './billing-charge-items.resource';
16
+ import StockItemSearch from './components/stock-search.component';
17
+
18
+ type CommodityFormProps = DefaultWorkspaceProps & {
19
+ initialValues?: BillableFormSchema;
20
+ };
21
+
22
+ const CommodityForm: React.FC<CommodityFormProps> = ({
23
+ closeWorkspace,
24
+ closeWorkspaceWithSavedChanges,
25
+ promptBeforeClosing,
26
+ initialValues,
27
+ }) => {
28
+ const { t } = useTranslation();
29
+ const isTablet = useLayoutType() === 'tablet';
30
+ const formMethods = useForm<BillableFormSchema>({
31
+ resolver: zodResolver(billableFormSchema),
32
+ defaultValues: initialValues
33
+ ? {
34
+ ...mapInputToPayloadSchema(initialValues),
35
+ serviceType: {
36
+ uuid: initialValues.serviceType?.uuid ?? '',
37
+ display: initialValues.serviceType?.display ?? '',
38
+ },
39
+ }
40
+ : { servicePrices: [], serviceStatus: 'ENABLED' },
41
+ });
42
+
43
+ const {
44
+ setValue,
45
+ control,
46
+ handleSubmit,
47
+ trigger,
48
+ formState: { errors, isDirty, isSubmitting },
49
+ } = formMethods;
50
+
51
+ const { fields, append, remove } = useFieldArray({
52
+ control,
53
+ name: 'servicePrices',
54
+ });
55
+
56
+ useEffect(() => {
57
+ if (initialValues) {
58
+ trigger();
59
+ }
60
+ }, [initialValues, trigger]);
61
+
62
+ const onSubmit = async (formValues: BillableFormSchema) => {
63
+ const payload = formatBillableServicePayloadForSubmission(formValues, initialValues?.['uuid']);
64
+ try {
65
+ const response = await createBillableService(payload, initialValues?.['uuid']);
66
+ if (response.ok) {
67
+ showSnackbar({
68
+ title: t('commodityBillableCreated', 'Commodity price created successfully'),
69
+ subtitle: t('commodityBillableCreatedSubtitle', 'The commodity price has been created successfully'),
70
+ kind: 'success',
71
+ isLowContrast: true,
72
+ timeoutInMs: 5000,
73
+ });
74
+ handleMutation(`${restBaseUrl}/cashier/billableService?v`);
75
+ closeWorkspaceWithSavedChanges();
76
+ }
77
+ } catch (e) {
78
+ const errorMessage =
79
+ e?.responseBody?.error?.message || e?.message || t('unknownError', 'An unknown error occurred');
80
+ showSnackbar({
81
+ title: t('commodityBillableCreationFailed', 'Commodity price creation failed'),
82
+ subtitle: t(
83
+ 'commodityBillableCreationFailedSubtitle',
84
+ 'The commodity price creation failed: {{errorMessage}}',
85
+ {
86
+ errorMessage: String(errorMessage).trim(),
87
+ },
88
+ ),
89
+ kind: 'error',
90
+ isLowContrast: true,
91
+ timeoutInMs: 5000,
92
+ });
93
+ }
94
+ };
95
+
96
+ useEffect(() => {
97
+ promptBeforeClosing(() => isDirty);
98
+ }, [isDirty, promptBeforeClosing]);
99
+
100
+ const renderServicePriceFields = useMemo(
101
+ () =>
102
+ fields.map((field, index) => (
103
+ <PriceField
104
+ key={field.id}
105
+ field={field}
106
+ index={index}
107
+ control={control}
108
+ removeServicePrice={remove}
109
+ errors={errors}
110
+ />
111
+ )),
112
+ [fields, control, remove, errors],
113
+ );
114
+
115
+ function flattenErrors(errors: Record<string, any>): string[] {
116
+ const messages: string[] = [];
117
+
118
+ Object.entries(errors).forEach(([key, value]) => {
119
+ if (Array.isArray(value)) {
120
+ value.forEach((item, index) => {
121
+ Object.entries(item as Record<string, { message: string }>).forEach(([subKey, subVal]) => {
122
+ messages.push(`${key}[${index}].${subKey}: ${subVal.message}`);
123
+ });
124
+ });
125
+ } else if (typeof value === 'object' && value?.message) {
126
+ messages.push(`${key}: ${value.message}`);
127
+ }
128
+ });
129
+
130
+ return messages;
131
+ }
132
+
133
+ const handleError = (err) => {
134
+ console.error(JSON.stringify(err, null, 2));
135
+ const errorMessage = flattenErrors(err).join('; ');
136
+ showSnackbar({
137
+ title: t('serviceCreationFailed', 'Service creation failed'),
138
+ subtitle: t('serviceCreationFailedSubtitle', 'The service creation failed: {{errorMessage}}', {
139
+ errorMessage,
140
+ }),
141
+ kind: 'error',
142
+ isLowContrast: true,
143
+ timeoutInMs: 5000,
144
+ });
145
+ };
146
+
147
+ return (
148
+ <FormProvider {...formMethods}>
149
+ <form onSubmit={handleSubmit(onSubmit, handleError)} className={styles.form}>
150
+ <div className={styles.formContainer}>
151
+ <Stack className={styles.formStackControl} gap={7}>
152
+ <StockItemSearch setValue={setValue} defaultStockItem={initialValues?.name} />
153
+ {errors.concept && (
154
+ <InlineNotification
155
+ kind="error"
156
+ lowContrast={true}
157
+ title={t('conceptMissing', 'Concept missing for {{name}}', { name: initialValues?.name })}
158
+ subtitle={t('conceptMissingSubtitle', 'Please delete the current item and re-create the charge item')}
159
+ />
160
+ )}
161
+ <ResponsiveWrapper>
162
+ <Controller
163
+ control={control}
164
+ name="serviceStatus"
165
+ render={({ field }) => (
166
+ <Toggle
167
+ labelText={t('status', 'Status')}
168
+ labelA="Off"
169
+ labelB="On"
170
+ defaultToggled={field.value === 'ENABLED'}
171
+ id="serviceStatus"
172
+ onToggle={(value) => (value ? field.onChange('ENABLED') : field.onChange('DISABLED'))}
173
+ />
174
+ )}
175
+ />
176
+ </ResponsiveWrapper>
177
+ {renderServicePriceFields}
178
+ <Button size="sm" kind="tertiary" renderIcon={Add} onClick={() => append({})}>
179
+ {t('addPaymentMethod', 'Add payment method')}
180
+ </Button>
181
+ {!!errors.servicePrices && (
182
+ <InlineNotification
183
+ aria-label="closes notification"
184
+ kind="error"
185
+ lowContrast={true}
186
+ statusIconDescription="notification"
187
+ title={t('paymentMethodRequired', 'Payment method required')}
188
+ subtitle={t('atLeastOnePriceRequired', 'At least one price is required')}
189
+ />
190
+ )}
191
+ </Stack>
192
+ </div>
193
+ <ButtonSet className={classNames({ [styles.tablet]: isTablet, [styles.desktop]: !isTablet })}>
194
+ <Button style={{ maxWidth: '50%' }} kind="secondary" onClick={() => closeWorkspace()}>
195
+ {t('cancel', 'Cancel')}
196
+ </Button>
197
+ <Button disabled={isSubmitting || !isDirty} style={{ maxWidth: '50%' }} kind="primary" type="submit">
198
+ {isSubmitting ? (
199
+ <span style={{ display: 'flex', justifyItems: 'center' }}>
200
+ {t('submitting', 'Submitting...')} <InlineLoading status="active" iconDescription="Loading" />
201
+ </span>
202
+ ) : (
203
+ t('saveAndClose', 'Save & close')
204
+ )}
205
+ </Button>
206
+ </ButtonSet>
207
+ </form>
208
+ </FormProvider>
209
+ );
210
+ };
211
+
212
+ export default CommodityForm;
@@ -0,0 +1,51 @@
1
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import useSWR from 'swr';
3
+ import { ServiceConcept, ServiceTypesResponse, StockItemResponse } from '../type';
4
+
5
+ export const createBillableService = (payload: any, uuid?: string) => {
6
+ const url = `${restBaseUrl}/cashier/billableService/${uuid ? `${uuid}` : ''}`;
7
+ return openmrsFetch(url, {
8
+ method: 'POST',
9
+ body: payload,
10
+ headers: {
11
+ 'Content-Type': 'application/json',
12
+ },
13
+ });
14
+ };
15
+
16
+ export function useConceptsSearch(conceptToLookup: string) {
17
+ const conditionsSearchUrl = `${restBaseUrl}/conceptsearch?q=${conceptToLookup}`;
18
+
19
+ const { data, error, isLoading } = useSWR<{ data: { results: Array<ServiceConcept> } }, Error>(
20
+ conceptToLookup ? conditionsSearchUrl : null,
21
+ openmrsFetch,
22
+ );
23
+
24
+ return {
25
+ searchResults: data?.data?.results ?? [],
26
+ error: error,
27
+ isSearching: isLoading,
28
+ };
29
+ }
30
+
31
+ // TODO: Move the uuid to a config file or constant file
32
+
33
+ export function useServiceTypes() {
34
+ const serviceConceptUuid = `d7bd4cc0-90b1-4f22-90f2-ab7fde936727`;
35
+ const url = `/ws/rest/v1/concept/${serviceConceptUuid}?v=custom:(setMembers:(uuid,display,id))`;
36
+ const { data, error, isLoading } = useSWR<{ data: ServiceTypesResponse }>(url, openmrsFetch, {});
37
+ return { serviceTypes: data?.data.setMembers ?? [], error, isLoading };
38
+ }
39
+
40
+ export const useCommodityItem = (searchTerm: string = '') => {
41
+ const url = `${restBaseUrl}/stockmanagement/stockitem?v=default&limit=10&q=${searchTerm}`;
42
+ const { data, error, isLoading, isValidating, mutate } = useSWR<{ data: StockItemResponse }>(url, openmrsFetch);
43
+
44
+ return {
45
+ stockItems: data?.data?.results ?? [],
46
+ isLoading,
47
+ isValidating,
48
+ error,
49
+ mutate,
50
+ };
51
+ };