@openmrs/esm-stock-management-app 1.0.1-pre.327

Sign up to get free protection for your applications and to get access to all the features.
Files changed (366) hide show
  1. package/.editorconfig +12 -0
  2. package/.eslintignore +2 -0
  3. package/.eslintrc +39 -0
  4. package/.husky/pre-commit +4 -0
  5. package/.husky/pre-push +6 -0
  6. package/.prettierignore +14 -0
  7. package/.turbo.json +18 -0
  8. package/.yarn/plugins/@yarnpkg/plugin-outdated.cjs +35 -0
  9. package/LICENSE +401 -0
  10. package/README.md +3 -0
  11. package/__mocks__/react-i18next.js +55 -0
  12. package/dist/26.js +2 -0
  13. package/dist/26.js.LICENSE.txt +32 -0
  14. package/dist/26.js.map +1 -0
  15. package/dist/294.js +2 -0
  16. package/dist/294.js.LICENSE.txt +9 -0
  17. package/dist/294.js.map +1 -0
  18. package/dist/375.js +2 -0
  19. package/dist/375.js.LICENSE.txt +40 -0
  20. package/dist/375.js.map +1 -0
  21. package/dist/46.js +1 -0
  22. package/dist/46.js.map +1 -0
  23. package/dist/484.js +1 -0
  24. package/dist/484.js.map +1 -0
  25. package/dist/574.js +1 -0
  26. package/dist/629.js +1 -0
  27. package/dist/629.js.map +1 -0
  28. package/dist/707.js +1 -0
  29. package/dist/707.js.map +1 -0
  30. package/dist/800.js +2 -0
  31. package/dist/800.js.LICENSE.txt +3 -0
  32. package/dist/800.js.map +1 -0
  33. package/dist/935.js +2 -0
  34. package/dist/935.js.LICENSE.txt +19 -0
  35. package/dist/935.js.map +1 -0
  36. package/dist/979.js +1 -0
  37. package/dist/979.js.map +1 -0
  38. package/dist/main.js +2 -0
  39. package/dist/main.js.LICENSE.txt +60 -0
  40. package/dist/main.js.map +1 -0
  41. package/dist/openmrs-esm-stock-management-app.js +1 -0
  42. package/dist/openmrs-esm-stock-management-app.js.buildmanifest.json +356 -0
  43. package/dist/openmrs-esm-stock-management-app.js.map +1 -0
  44. package/dist/routes.json +1 -0
  45. package/i18next-parser.config.js +89 -0
  46. package/jest.config.js +25 -0
  47. package/package.json +116 -0
  48. package/src/config-schema.ts +18 -0
  49. package/src/constants.ts +214 -0
  50. package/src/core/api/api.ts +34 -0
  51. package/src/core/api/types/Auditable.ts +9 -0
  52. package/src/core/api/types/BaseOpenmrsData.ts +4 -0
  53. package/src/core/api/types/BaseOpenmrsMetadata.ts +6 -0
  54. package/src/core/api/types/BaseOpenmrsObject.ts +3 -0
  55. package/src/core/api/types/BatchJob.ts +121 -0
  56. package/src/core/api/types/DashboardExtension.ts +8 -0
  57. package/src/core/api/types/Location.ts +16 -0
  58. package/src/core/api/types/LocationTree.ts +7 -0
  59. package/src/core/api/types/OpenmrsData.ts +5 -0
  60. package/src/core/api/types/OpenmrsMetadata.ts +8 -0
  61. package/src/core/api/types/OpenmrsObject.ts +3 -0
  62. package/src/core/api/types/PageableResult.ts +15 -0
  63. package/src/core/api/types/Party.ts +8 -0
  64. package/src/core/api/types/RecordPermission.ts +9 -0
  65. package/src/core/api/types/Retireable.ts +9 -0
  66. package/src/core/api/types/Voidable.ts +9 -0
  67. package/src/core/api/types/concept/Concept.ts +24 -0
  68. package/src/core/api/types/concept/ConceptName.ts +14 -0
  69. package/src/core/api/types/concept/Drug.ts +14 -0
  70. package/src/core/api/types/identity/Credentials.ts +4 -0
  71. package/src/core/api/types/identity/Patient.ts +3 -0
  72. package/src/core/api/types/identity/Person.ts +4 -0
  73. package/src/core/api/types/identity/PriviledgeScope.ts +9 -0
  74. package/src/core/api/types/identity/Privilege.ts +5 -0
  75. package/src/core/api/types/identity/Role.ts +5 -0
  76. package/src/core/api/types/identity/Session.ts +16 -0
  77. package/src/core/api/types/identity/User.ts +19 -0
  78. package/src/core/api/types/identity/UserRoleScope.ts +17 -0
  79. package/src/core/api/types/identity/UserRoleScopeLocation.ts +7 -0
  80. package/src/core/api/types/identity/UserRoleScopeOperationType.ts +6 -0
  81. package/src/core/api/types/stockItem/ImportResult.ts +9 -0
  82. package/src/core/api/types/stockItem/StockBatch.ts +8 -0
  83. package/src/core/api/types/stockItem/StockBatchDTO.ts +8 -0
  84. package/src/core/api/types/stockItem/StockItem.ts +63 -0
  85. package/src/core/api/types/stockItem/StockItemInventory.ts +10 -0
  86. package/src/core/api/types/stockItem/StockItemPackagingUOM.ts +20 -0
  87. package/src/core/api/types/stockItem/StockItemTransaction.ts +22 -0
  88. package/src/core/api/types/stockItem/StockRule.ts +28 -0
  89. package/src/core/api/types/stockOperation/LocationType.ts +4 -0
  90. package/src/core/api/types/stockOperation/StockOperation.ts +36 -0
  91. package/src/core/api/types/stockOperation/StockOperationAction.ts +24 -0
  92. package/src/core/api/types/stockOperation/StockOperationDTO.ts +64 -0
  93. package/src/core/api/types/stockOperation/StockOperationItem.ts +13 -0
  94. package/src/core/api/types/stockOperation/StockOperationItemCost.ts +14 -0
  95. package/src/core/api/types/stockOperation/StockOperationItemDTO.ts +29 -0
  96. package/src/core/api/types/stockOperation/StockOperationLinkDTO.ts +13 -0
  97. package/src/core/api/types/stockOperation/StockOperationStatus.ts +18 -0
  98. package/src/core/api/types/stockOperation/StockOperationType.ts +162 -0
  99. package/src/core/api/types/stockOperation/StockSource.ts +8 -0
  100. package/src/core/components/carbon/controlled-combo-box/controlled-combo-box.component.tsx +37 -0
  101. package/src/core/components/carbon/controlled-combo-box/controlled-combo-box.resource.tsx +0 -0
  102. package/src/core/components/carbon/controlled-combo-box/controlled-combo-box.scss +0 -0
  103. package/src/core/components/carbon/controlled-combo-box/controlled-combo-box.test.tsx +8 -0
  104. package/src/core/components/carbon/controlled-dropdown/controlled-dropdown.component.tsx +40 -0
  105. package/src/core/components/carbon/controlled-dropdown/controlled-dropdown.resource.tsx +0 -0
  106. package/src/core/components/carbon/controlled-dropdown/controlled-dropdown.scss +0 -0
  107. package/src/core/components/carbon/controlled-dropdown/controlled-dropdown.test.tsx +8 -0
  108. package/src/core/components/carbon/controlled-number-input/controlled-number-input.component.tsx +44 -0
  109. package/src/core/components/carbon/controlled-number-input/controlled-number-input.resource.tsx +0 -0
  110. package/src/core/components/carbon/controlled-number-input/controlled-number-input.scss +0 -0
  111. package/src/core/components/carbon/controlled-number-input/controlled-number-input.test.tsx +8 -0
  112. package/src/core/components/carbon/controlled-radio-button-group/controlled-radio-button-group.component.tsx +54 -0
  113. package/src/core/components/carbon/controlled-radio-button-group/controlled-radio-button-group.resource.tsx +0 -0
  114. package/src/core/components/carbon/controlled-radio-button-group/controlled-radio-button-group.scss +0 -0
  115. package/src/core/components/carbon/controlled-radio-button-group/controlled-radio-button-group.test.tsx +8 -0
  116. package/src/core/components/carbon/controlled-text-area/controlled-text-area.component.tsx +37 -0
  117. package/src/core/components/carbon/controlled-text-area/controlled-text-area.resource.tsx +0 -0
  118. package/src/core/components/carbon/controlled-text-area/controlled-text-area.scss +0 -0
  119. package/src/core/components/carbon/controlled-text-area/controlled-text-area.test.tsx +11 -0
  120. package/src/core/components/carbon/controlled-text-input/controlled-text-input.component.tsx +37 -0
  121. package/src/core/components/carbon/controlled-text-input/controlled-text-input.resource.tsx +0 -0
  122. package/src/core/components/carbon/controlled-text-input/controlled-text-input.scss +0 -0
  123. package/src/core/components/carbon/controlled-text-input/controlled-text-input.test.tsx +8 -0
  124. package/src/core/components/carbon/types.ts +7 -0
  125. package/src/core/components/card/metrics-card-component.tsx +102 -0
  126. package/src/core/components/card/metrics-card.scss +78 -0
  127. package/src/core/components/overlay/hook.ts +47 -0
  128. package/src/core/components/overlay/overlay.component.tsx +52 -0
  129. package/src/core/components/overlay/overlay.scss +97 -0
  130. package/src/core/components/side-nav/side-nav.component.tsx +62 -0
  131. package/src/core/components/side-nav/side-nav.scss +126 -0
  132. package/src/core/components/side-nav/types.ts +6 -0
  133. package/src/core/components/table/table.component.tsx +239 -0
  134. package/src/core/components/table/table.scss +173 -0
  135. package/src/core/components/table/types.ts +8 -0
  136. package/src/core/components/tabs/types.ts +7 -0
  137. package/src/core/components/tabs/vertical-tabs.component.tsx +53 -0
  138. package/src/core/components/tabs/vertical-tabs.scss +126 -0
  139. package/src/core/hooks/debounce-hook.ts +35 -0
  140. package/src/core/print/PrintStyles.ts +774 -0
  141. package/src/core/print/PrintTemplate.ts +65 -0
  142. package/src/core/print/printUtils.ts +19 -0
  143. package/src/core/utils/alert.ts +10 -0
  144. package/src/core/utils/datetimeUtils.ts +84 -0
  145. package/src/core/utils/debounce.ts +21 -0
  146. package/src/core/utils/imageUtils.ts +82 -0
  147. package/src/core/utils/stringUtils.ts +27 -0
  148. package/src/core/utils/utils.ts +70 -0
  149. package/src/createDashboardLink.tsx +43 -0
  150. package/src/dashboard/stock-management-dashboard-side-nav.component.tsx +50 -0
  151. package/src/dashboard/stock-management-dashboard.component.tsx +41 -0
  152. package/src/dashboard/stock-management-dashboard.scss +8 -0
  153. package/src/dashboard.meta.ts +5 -0
  154. package/src/declarations.d.ts +6 -0
  155. package/src/index.ts +64 -0
  156. package/src/root.component.tsx +12 -0
  157. package/src/root.scss +174 -0
  158. package/src/routes.json +53 -0
  159. package/src/setup-tests.ts +1 -0
  160. package/src/stock-app-menu-item/item.component.tsx +21 -0
  161. package/src/stock-app-menu-item/item.resource.ts +0 -0
  162. package/src/stock-app-menu-item/item.scss +17 -0
  163. package/src/stock-batch/stock-batch.resource.ts +79 -0
  164. package/src/stock-home/stock-home-detail-card.scss +211 -0
  165. package/src/stock-home/stock-home-detail-cards.component.tsx +62 -0
  166. package/src/stock-home/stock-home-inventory-card.component.tsx +80 -0
  167. package/src/stock-home/stock-home-inventory-expiry.resource.tsx +32 -0
  168. package/src/stock-home/stock-home-inventory-items.resource.tsx +28 -0
  169. package/src/stock-home/stock-home-issuing-card.component.tsx +84 -0
  170. package/src/stock-home/stock-home-issuing.resource.tsx +18 -0
  171. package/src/stock-home/stock-home-landing-page-component.tsx +14 -0
  172. package/src/stock-home/stock-home-metrics.tsx +112 -0
  173. package/src/stock-home/stock-home-receiving-card.component.tsx +66 -0
  174. package/src/stock-home/stock-home-receiving.resource.tsx +17 -0
  175. package/src/stock-home/stock-home.scss +13 -0
  176. package/src/stock-home/useDisposalList.tsx +18 -0
  177. package/src/stock-home/useStockList.tsx +36 -0
  178. package/src/stock-items/add-bulk-stock-item/add-stock-items-bulk-import-action-button.component.tsx +26 -0
  179. package/src/stock-items/add-bulk-stock-item/stock-items-bulk-import.component.tsx +109 -0
  180. package/src/stock-items/add-bulk-stock-item/stock-items-bulk-import.resource.ts +14 -0
  181. package/src/stock-items/add-bulk-stock-item/stock-items-bulk-import.scss +0 -0
  182. package/src/stock-items/add-stock-item/add-stock-action-button.component.tsx +21 -0
  183. package/src/stock-items/add-stock-item/add-stock-item.component.tsx +84 -0
  184. package/src/stock-items/add-stock-item/add-stock-item.resource.tsx +36 -0
  185. package/src/stock-items/add-stock-item/add-stock-item.scss +5 -0
  186. package/src/stock-items/add-stock-item/batch-information/batch-information.component.tsx +98 -0
  187. package/src/stock-items/add-stock-item/batch-information/batch-information.resource.tsx +71 -0
  188. package/src/stock-items/add-stock-item/batch-information/batch-information.scss +0 -0
  189. package/src/stock-items/add-stock-item/concepts-selector/concepts-selector.component.tsx +79 -0
  190. package/src/stock-items/add-stock-item/concepts-selector/concepts-selector.resource.tsx +0 -0
  191. package/src/stock-items/add-stock-item/concepts-selector/concepts-selector.scss +0 -0
  192. package/src/stock-items/add-stock-item/concepts-selector/concepts-selector.test.tsx +8 -0
  193. package/src/stock-items/add-stock-item/dispensing-package-measurement/dispensing-package-measurement.component.tsx +76 -0
  194. package/src/stock-items/add-stock-item/dispensing-unit-selector/dispensing-unit-selector.component.tsx +66 -0
  195. package/src/stock-items/add-stock-item/dispensing-unit-selector/dispensing-unit-selector.resource.tsx +0 -0
  196. package/src/stock-items/add-stock-item/dispensing-unit-selector/dispensing-unit-selector.scss +0 -0
  197. package/src/stock-items/add-stock-item/dispensing-unit-selector/dispensing-unit-selector.test.tsx +8 -0
  198. package/src/stock-items/add-stock-item/drug-selector/drug-selector.component.tsx +83 -0
  199. package/src/stock-items/add-stock-item/drug-selector/drug-selector.resource.tsx +50 -0
  200. package/src/stock-items/add-stock-item/drug-selector/drug-selector.scss +0 -0
  201. package/src/stock-items/add-stock-item/packaging-units/packaging-units.component.tsx +255 -0
  202. package/src/stock-items/add-stock-item/packaging-units/packaging-units.resource.tsx +38 -0
  203. package/src/stock-items/add-stock-item/packaging-units/packaging-units.scss +21 -0
  204. package/src/stock-items/add-stock-item/packaging-units/validationSchema.ts +14 -0
  205. package/src/stock-items/add-stock-item/packaging-units-concept-selector/packaging-units-concept-selector.component.tsx +95 -0
  206. package/src/stock-items/add-stock-item/preferred-vendor-selector/preferred-vendor-selector.component.tsx +70 -0
  207. package/src/stock-items/add-stock-item/preferred-vendor-selector/preferred-vendor-selector.resource.tsx +0 -0
  208. package/src/stock-items/add-stock-item/preferred-vendor-selector/preferred-vendor-selector.scss +0 -0
  209. package/src/stock-items/add-stock-item/preferred-vendor-selector/preferred-vendor-selector.test.tsx +8 -0
  210. package/src/stock-items/add-stock-item/quantities/quantities.component.tsx +83 -0
  211. package/src/stock-items/add-stock-item/quantities/quantities.resource.tsx +69 -0
  212. package/src/stock-items/add-stock-item/quantities/quantities.scss +0 -0
  213. package/src/stock-items/add-stock-item/stock-item-category-selector/stock-item-category-selector.component.tsx +67 -0
  214. package/src/stock-items/add-stock-item/stock-item-category-selector/stock-item-category-selector.resource.tsx +0 -0
  215. package/src/stock-items/add-stock-item/stock-item-category-selector/stock-item-category-selector.scss +0 -0
  216. package/src/stock-items/add-stock-item/stock-item-category-selector/stock-item-category-selector.test.tsx +8 -0
  217. package/src/stock-items/add-stock-item/stock-item-details/stock-item-details.component.tsx +239 -0
  218. package/src/stock-items/add-stock-item/stock-item-details/stock-item-details.resource.tsx +14 -0
  219. package/src/stock-items/add-stock-item/stock-item-details/stock-item-details.scss +13 -0
  220. package/src/stock-items/add-stock-item/stock-item-rules/add-stock-rule-button.component.tsx +30 -0
  221. package/src/stock-items/add-stock-item/stock-item-rules/add-stock-rules.component.tsx +424 -0
  222. package/src/stock-items/add-stock-item/stock-item-rules/add-stock-rules.scss +18 -0
  223. package/src/stock-items/add-stock-item/stock-item-rules/delete-stock-rule-modal.component.tsx +47 -0
  224. package/src/stock-items/add-stock-item/stock-item-rules/edit-stock-rule.component.tsx +37 -0
  225. package/src/stock-items/add-stock-item/stock-item-rules/edit-stock-rule.scss +0 -0
  226. package/src/stock-items/add-stock-item/stock-item-rules/stock-item-rules.component.tsx +222 -0
  227. package/src/stock-items/add-stock-item/stock-item-rules/stock-item-rules.resource.tsx +72 -0
  228. package/src/stock-items/add-stock-item/stock-item-rules/stock-item-rules.scss +13 -0
  229. package/src/stock-items/add-stock-item/stock-item-rules/stock-rules-delete.component.tsx +67 -0
  230. package/src/stock-items/add-stock-item/stock-item-rules/stock-rules-delete.scss +0 -0
  231. package/src/stock-items/add-stock-item/stock-item-rules/stock-rules-filter.component.tsx +38 -0
  232. package/src/stock-items/add-stock-item/stock-item-rules/stock-rules-filter.scss +13 -0
  233. package/src/stock-items/add-stock-item/stock-item-rules/stock-rules.resource.ts +79 -0
  234. package/src/stock-items/add-stock-item/stock-item-units-edit/stock-item-units-edit.component.tsx +132 -0
  235. package/src/stock-items/add-stock-item/stock-rules/stock-rules.component.tsx +16 -0
  236. package/src/stock-items/add-stock-item/stock-rules/stock-rules.resource.tsx +0 -0
  237. package/src/stock-items/add-stock-item/stock-rules/stock-rules.scss +0 -0
  238. package/src/stock-items/add-stock-item/transactions/transactions.component.tsx +151 -0
  239. package/src/stock-items/add-stock-item/transactions/transactions.resource.tsx +109 -0
  240. package/src/stock-items/add-stock-item/transactions/transactions.scss +0 -0
  241. package/src/stock-items/components/filter-stock-items/filter-stock-items.component.tsx +28 -0
  242. package/src/stock-items/components/filter-stock-items/filter-stock-items.resource.tsx +0 -0
  243. package/src/stock-items/components/filter-stock-items/filter-stock-items.scss +3 -0
  244. package/src/stock-items/edit-stock-item/edit-stock-item-action-menu.component.tsx +30 -0
  245. package/src/stock-items/stock-item.utils.tsx +62 -0
  246. package/src/stock-items/stock-items-table.component.tsx +266 -0
  247. package/src/stock-items/stock-items-table.resource.ts +58 -0
  248. package/src/stock-items/stock-items-table.scss +66 -0
  249. package/src/stock-items/stock-items.component.tsx +12 -0
  250. package/src/stock-items/stock-items.resource.ts +365 -0
  251. package/src/stock-items/types.ts +8 -0
  252. package/src/stock-items/validationSchema.ts +67 -0
  253. package/src/stock-locations/stock-locations-table.component.tsx +69 -0
  254. package/src/stock-locations/stock-locations-table.resource.tsx +73 -0
  255. package/src/stock-locations/stock-locations-table.scss +0 -0
  256. package/src/stock-locations/stock-locations.component.tsx +12 -0
  257. package/src/stock-locations/stock-locations.resource.ts +0 -0
  258. package/src/stock-lookups/stock-lookups.resource.ts +306 -0
  259. package/src/stock-management-admin-card-link.component.tsx +29 -0
  260. package/src/stock-management-header/stock-management-Illustration.tsx +35 -0
  261. package/src/stock-management-header/stock-management-header.component.tsx +37 -0
  262. package/src/stock-management-header/stock-management-header.scss +58 -0
  263. package/src/stock-management.component.tsx +6 -0
  264. package/src/stock-operations/add-stock-operation/add-stock-operation.component.tsx +491 -0
  265. package/src/stock-operations/add-stock-operation/add-stock-operation.resource.tsx +33 -0
  266. package/src/stock-operations/add-stock-operation/add-stock-operation.scss +44 -0
  267. package/src/stock-operations/add-stock-operation/add-stock-operation.utils.tsx +241 -0
  268. package/src/stock-operations/add-stock-operation/add-stock-utils.ts +110 -0
  269. package/src/stock-operations/add-stock-operation/base-operation-details.component.tsx +352 -0
  270. package/src/stock-operations/add-stock-operation/stock-items-addition-row.component.tsx +347 -0
  271. package/src/stock-operations/add-stock-operation/stock-items-addition-row.resource.tsx +0 -0
  272. package/src/stock-operations/add-stock-operation/stock-items-addition-row.scss +0 -0
  273. package/src/stock-operations/add-stock-operation/stock-items-addition-row.test.tsx +11 -0
  274. package/src/stock-operations/add-stock-operation/stock-items-addition.component.scss +5 -0
  275. package/src/stock-operations/add-stock-operation/stock-items-addition.component.tsx +272 -0
  276. package/src/stock-operations/add-stock-operation/stock-operation-context/useStockOperationContext.tsx +22 -0
  277. package/src/stock-operations/add-stock-operation/stock-operation-submission.component.tsx +188 -0
  278. package/src/stock-operations/add-stock-operation/types.ts +55 -0
  279. package/src/stock-operations/add-stock-operation/validationSchema.ts +45 -0
  280. package/src/stock-operations/batch-no-selector/batch-no-selector.component.tsx +100 -0
  281. package/src/stock-operations/batch-no-selector/batch-no-selector.resource.tsx +46 -0
  282. package/src/stock-operations/batch-no-selector/batch-no-selector.scss +0 -0
  283. package/src/stock-operations/batch-no-selector/batch-no-selector.test.tsx +11 -0
  284. package/src/stock-operations/edit-stock-operation/edit-stock-operation-action-menu.component.tsx +73 -0
  285. package/src/stock-operations/party-selector/party-selector.component.tsx +58 -0
  286. package/src/stock-operations/qty-uom-selector/qty-uom-selector.component.tsx +65 -0
  287. package/src/stock-operations/qty-uom-selector/qty-uom-selector.resource.tsx +0 -0
  288. package/src/stock-operations/qty-uom-selector/qty-uom-selector.scss +0 -0
  289. package/src/stock-operations/qty-uom-selector/qty-uom-selector.test.tsx +11 -0
  290. package/src/stock-operations/stock-item-selector/stock-item-selector.component.tsx +74 -0
  291. package/src/stock-operations/stock-item-selector/stock-item-selector.resource.tsx +47 -0
  292. package/src/stock-operations/stock-item-selector/stock-item-selector.scss +0 -0
  293. package/src/stock-operations/stock-item-selector/stock-item-selector.test.tsx +11 -0
  294. package/src/stock-operations/stock-operation-operations-filter/stock-operation-operations-filter.component.tsx +27 -0
  295. package/src/stock-operations/stock-operation-operations-filter/stock-operation-operations-filter.scss +13 -0
  296. package/src/stock-operations/stock-operation-reason-selector/stock-operation-reason-selector.component.tsx +65 -0
  297. package/src/stock-operations/stock-operation-sources-filter/stock-operation-sources-filter.component.tsx +30 -0
  298. package/src/stock-operations/stock-operation-sources-filter/stock-operation-sources-filter.scss +13 -0
  299. package/src/stock-operations/stock-operation-statuses-filter/stock-operation-statuses-filter.component.tsx +32 -0
  300. package/src/stock-operations/stock-operation-statuses-filter/stock-operation-statuses-filter.scss +13 -0
  301. package/src/stock-operations/stock-operation-types-selector/stock-operation-types-selector.component.tsx +80 -0
  302. package/src/stock-operations/stock-operation.utils.tsx +106 -0
  303. package/src/stock-operations/stock-operations-dialog/stock-operations-approve-button.component.tsx +36 -0
  304. package/src/stock-operations/stock-operations-dialog/stock-operations-approve-dispatch-button.component.tsx +36 -0
  305. package/src/stock-operations/stock-operations-dialog/stock-operations-cancel-button.component.tsx +37 -0
  306. package/src/stock-operations/stock-operations-dialog/stock-operations-complete-button.component.tsx +36 -0
  307. package/src/stock-operations/stock-operations-dialog/stock-operations-completed-dispatch-button.component.tsx +36 -0
  308. package/src/stock-operations/stock-operations-dialog/stock-operations-dialog.component.tsx +167 -0
  309. package/src/stock-operations/stock-operations-dialog/stock-operations-dialog.scss +14 -0
  310. package/src/stock-operations/stock-operations-dialog/stock-operations-issue-stock-button.component.tsx +58 -0
  311. package/src/stock-operations/stock-operations-dialog/stock-operations-print-button.component.tsx +160 -0
  312. package/src/stock-operations/stock-operations-dialog/stock-operations-reject-button.component.tsx +37 -0
  313. package/src/stock-operations/stock-operations-dialog/stock-operations-return-button.component.tsx +37 -0
  314. package/src/stock-operations/stock-operations-table.component.tsx +524 -0
  315. package/src/stock-operations/stock-operations-table.resource.tsx +77 -0
  316. package/src/stock-operations/stock-operations-table.scss +0 -0
  317. package/src/stock-operations/stock-operations.component.tsx +12 -0
  318. package/src/stock-operations/stock-operations.resource.ts +238 -0
  319. package/src/stock-operations/stock-print-reports/GoodsReceivedNote.tsx +147 -0
  320. package/src/stock-operations/stock-print-reports/RequisitionDocument.tsx +153 -0
  321. package/src/stock-operations/stock-print-reports/StockOperationReport.tsx +133 -0
  322. package/src/stock-operations/stock-print-reports/StockTransferDocument.tsx +161 -0
  323. package/src/stock-operations/swr-revalidation.ts +7 -0
  324. package/src/stock-operations/users-selector/users-selector.component.tsx +77 -0
  325. package/src/stock-operations/users-selector/users-selector.resource.tsx +47 -0
  326. package/src/stock-operations/validation-schema.ts +195 -0
  327. package/src/stock-reports/ReportType.ts +63 -0
  328. package/src/stock-reports/stock-reports.component.tsx +0 -0
  329. package/src/stock-reports/stock-reports.resource.ts +0 -0
  330. package/src/stock-settings/stock-settings.component.tsx +11 -0
  331. package/src/stock-settings/stock-settings.resource.ts +0 -0
  332. package/src/stock-sources/add-stock-source-button.component.tsx +21 -0
  333. package/src/stock-sources/add-stock-sources/add-stock-sources.component.tsx +152 -0
  334. package/src/stock-sources/add-stock-sources/add-stock-sources.scss +18 -0
  335. package/src/stock-sources/delete-stock-modal.component.tsx +47 -0
  336. package/src/stock-sources/edit-stock-source/edit-stock-source.component.tsx +35 -0
  337. package/src/stock-sources/edit-stock-source/edit-stock-source.scss +0 -0
  338. package/src/stock-sources/stock-sources-delete/stock-sources-delate.scss +0 -0
  339. package/src/stock-sources/stock-sources-delete/stock-sources-delete.component.tsx +72 -0
  340. package/src/stock-sources/stock-sources-filter/stock-sources-filter.component.tsx +35 -0
  341. package/src/stock-sources/stock-sources-filter/stock-sources-filter.scss +13 -0
  342. package/src/stock-sources/stock-sources-items-table.component.tsx +213 -0
  343. package/src/stock-sources/stock-sources-items-table.resource.ts +56 -0
  344. package/src/stock-sources/stock-sources.component.tsx +12 -0
  345. package/src/stock-sources/stock-sources.resource.ts +80 -0
  346. package/src/stock-sources/stock-sources.scss +220 -0
  347. package/src/stock-sources/swr-revalidation.ts +7 -0
  348. package/src/stock-tabs/commodity-tabs.component.tsx +43 -0
  349. package/src/stock-tabs/commodity-tabs.scss +0 -0
  350. package/src/stock-user-role-scopes/add-stock-user-role-scope-button.component.tsx +21 -0
  351. package/src/stock-user-role-scopes/add-stock-user-scope/add-stock-user-role-scope.component.tsx +525 -0
  352. package/src/stock-user-role-scopes/add-stock-user-scope/add-stock-user-role-scope.scss +37 -0
  353. package/src/stock-user-role-scopes/delete-stock-user-scope/delete-stock-user-scope.component.tsx +73 -0
  354. package/src/stock-user-role-scopes/delete-stock-user-scope/delete-stock-user-scope.scss +0 -0
  355. package/src/stock-user-role-scopes/delete-stock-user-scope-modal.component.tsx +47 -0
  356. package/src/stock-user-role-scopes/edit-stock-user-scope/edit-stock-user-scope-action-menu.component.tsx +35 -0
  357. package/src/stock-user-role-scopes/stock-user-role-scopes-items-table.component.tsx +284 -0
  358. package/src/stock-user-role-scopes/stock-user-role-scopes-items-table.resource.ts +31 -0
  359. package/src/stock-user-role-scopes/stock-user-role-scopes.component.tsx +12 -0
  360. package/src/stock-user-role-scopes/stock-user-role-scopes.resource.ts +76 -0
  361. package/src/stock-user-role-scopes/stock-user-role-scopes.scss +61 -0
  362. package/src/stock-user-role-scopes/swr-revalidation.ts +7 -0
  363. package/src/utils.ts +10 -0
  364. package/translations/en.json +24 -0
  365. package/tsconfig.json +23 -0
  366. package/webpack.config.js +1 -0
@@ -0,0 +1,84 @@
1
+ import React, { useState } from "react";
2
+ import { useTranslation } from "react-i18next";
3
+ import StockItemDetails from "./stock-item-details/stock-item-details.component";
4
+ import StockItemRules from "./stock-item-rules/stock-item-rules.component";
5
+ import { TabItem } from "../../core/components/tabs/types";
6
+ import PackagingUnits from "./packaging-units/packaging-units.component";
7
+ import Transactions from "./transactions/transactions.component";
8
+ import BatchInformation from "./batch-information/batch-information.component";
9
+ import StockQuantities from "./quantities/quantities.component";
10
+ import VerticalTabs from "../../core/components/tabs/vertical-tabs.component";
11
+ import { StockItemDTO } from "../../core/api/types/stockItem/StockItem";
12
+ import { SaveStockItem } from "../types";
13
+
14
+ interface AddStockItemProps {
15
+ isEditing?: boolean;
16
+ model?: StockItemDTO;
17
+ onSave?: SaveStockItem;
18
+ }
19
+
20
+ const AddEditStockItem: React.FC<AddStockItemProps> = ({
21
+ isEditing,
22
+ model,
23
+ onSave,
24
+ }) => {
25
+ const { t } = useTranslation();
26
+ const [selectedTab, setSelectedTab] = useState(0);
27
+ const handleTabChange = (index: number) => {
28
+ setSelectedTab(index);
29
+ };
30
+ const tabs: TabItem[] = [
31
+ {
32
+ name: t("stockItemDetails", "Stock Item Details"),
33
+ component: (
34
+ <StockItemDetails
35
+ handleTabChange={handleTabChange}
36
+ model={model}
37
+ onSave={onSave}
38
+ isEditing={isEditing}
39
+ />
40
+ ),
41
+ },
42
+ {
43
+ name: t("packagingUnits", "Packaging Units"),
44
+ component: (
45
+ <PackagingUnits
46
+ isEditing
47
+ handleTabChange={handleTabChange}
48
+ stockItemUuid={model.uuid}
49
+ />
50
+ ),
51
+ disabled: !isEditing,
52
+ },
53
+ {
54
+ name: t("transactions", "Transactions"),
55
+ component: <Transactions stockItemUuid={model.uuid} />,
56
+ disabled: !isEditing,
57
+ },
58
+ {
59
+ name: t("batchInformation", "Batch Information"),
60
+ component: <BatchInformation stockItemUuid={model.uuid} />,
61
+ disabled: !isEditing,
62
+ },
63
+ {
64
+ name: t("quantities", "Quantities"),
65
+ component: <StockQuantities stockItemUuid={model.uuid} />,
66
+ disabled: !isEditing,
67
+ },
68
+ {
69
+ name: t("stockRules", "Stock Rules"),
70
+ component: <StockItemRules stockItemUuid={model.uuid} />,
71
+ disabled: !isEditing,
72
+ },
73
+ ];
74
+
75
+ return (
76
+ <VerticalTabs
77
+ onChange={handleTabChange}
78
+ tabs={tabs}
79
+ selectedIndex={selectedTab}
80
+ />
81
+ );
82
+ };
83
+
84
+ export default AddEditStockItem;
@@ -0,0 +1,36 @@
1
+ import { StockItemDTO } from "../../core/api/types/stockItem/StockItem";
2
+
3
+ export const initialValues: StockItemDTO = {
4
+ uuid: undefined,
5
+ isDrug: undefined,
6
+ drugUuid: undefined,
7
+ drugName: undefined,
8
+ conceptUuid: undefined,
9
+ commonName: undefined,
10
+ acronym: undefined,
11
+ conceptName: undefined,
12
+ hasExpiration: undefined,
13
+ preferredVendorUuid: undefined,
14
+ preferredVendorName: undefined,
15
+ purchasePrice: undefined,
16
+ purchasePriceUoMUuid: undefined,
17
+ purchasePriceUoMName: undefined,
18
+ dispensingUnitName: undefined,
19
+ dispensingUnitUuid: undefined,
20
+ dispensingUnitPackagingUoMUuid: undefined,
21
+ dispensingUnitPackagingUoMName: undefined,
22
+ defaultStockOperationsUoMUuid: undefined,
23
+ defaultStockOperationsUoMName: undefined,
24
+ reorderLevel: undefined,
25
+ reorderLevelUoMUuid: undefined,
26
+ reorderLevelUoMName: undefined,
27
+ dateCreated: undefined,
28
+ creatorGivenName: undefined,
29
+ creatorFamilyName: undefined,
30
+ voided: undefined,
31
+ packagingUnits: undefined,
32
+ permission: undefined,
33
+ categoryUuid: undefined,
34
+ categoryName: undefined,
35
+ expiryNotice: undefined,
36
+ };
@@ -0,0 +1,5 @@
1
+ .formContainer {
2
+ max-height: calc(100vh - 100px);
3
+ overflow: scroll;
4
+ padding: 0 1rem;
5
+ }
@@ -0,0 +1,98 @@
1
+ import React, { useEffect, useMemo } from "react";
2
+ import { useTranslation } from "react-i18next";
3
+ import { ResourceRepresentation } from "../../../core/api/api";
4
+ import { formatDisplayDate } from "../../../core/utils/datetimeUtils";
5
+ import { DataTableSkeleton, Tile } from "@carbon/react";
6
+ import DataList from "../../../core/components/table/table.component";
7
+ import styles from "../../stock-items-table.scss";
8
+ import { useStockItemBatchInformationHook } from "./batch-information.resource";
9
+
10
+ interface BatchInformationProps {
11
+ onSubmit?: () => void;
12
+ stockItemUuid: string;
13
+ }
14
+
15
+ const BatchInformation: React.FC<BatchInformationProps> = ({
16
+ stockItemUuid,
17
+ }) => {
18
+ const {
19
+ isLoading,
20
+ items,
21
+
22
+ totalCount,
23
+ setCurrentPage,
24
+ setStockItemUuid,
25
+ } = useStockItemBatchInformationHook(ResourceRepresentation.Default);
26
+ const { t } = useTranslation();
27
+
28
+ useEffect(() => {
29
+ setStockItemUuid(stockItemUuid);
30
+ }, [stockItemUuid, setStockItemUuid]);
31
+ const tableHeaders = useMemo(
32
+ () => [
33
+ {
34
+ key: "location",
35
+ header: t("location", "Location"),
36
+ },
37
+ {
38
+ key: "batch",
39
+ header: t("batchNumber", "Batch Number"),
40
+ },
41
+ {
42
+ key: "quantity",
43
+ header: t("quantity", "Quantity"),
44
+ },
45
+ {
46
+ key: "packaging",
47
+ header: t("packagingUnit", "Packaging Unit"),
48
+ },
49
+ {
50
+ key: "expires",
51
+ header: t("expires", "Expires"),
52
+ },
53
+ ],
54
+ []
55
+ );
56
+
57
+ const tableRows = useMemo(() => {
58
+ return items?.map((row, index) => ({
59
+ ...row,
60
+ id: `${row.partyUuid}${row.stockBatchUuid}${index}`,
61
+ key: `${row.partyUuid}${row.stockBatchUuid}${index}`,
62
+ uuid: `${row.partyUuid}${row.stockBatchUuid}${index}`,
63
+ expires: formatDisplayDate(row?.expiration),
64
+ location: row?.partyName,
65
+ quantity: row?.quantity?.toLocaleString() ?? "",
66
+ batch: row.batchNumber ?? "",
67
+ packaging: row.quantityUoM ?? "",
68
+ }));
69
+ }, [items]);
70
+
71
+ if (isLoading) {
72
+ return <DataTableSkeleton role="progressbar" />;
73
+ }
74
+
75
+ if (items?.length > 0) {
76
+ return (
77
+ <DataList
78
+ columns={tableHeaders}
79
+ data={tableRows}
80
+ totalItems={totalCount}
81
+ goToPage={setCurrentPage}
82
+ hasToolbar={false}
83
+ />
84
+ );
85
+ }
86
+
87
+ return (
88
+ <div className={styles.tileContainer}>
89
+ <Tile className={styles.tile}>
90
+ <p className={styles.content}>
91
+ {t("batchInfoToDisplay", "No batch information to display")}
92
+ </p>
93
+ </Tile>
94
+ </div>
95
+ );
96
+ };
97
+
98
+ export default BatchInformation;
@@ -0,0 +1,71 @@
1
+ import { ResourceRepresentation } from "../../../core/api/api";
2
+ import { useEffect, useMemo, useState } from "react";
3
+ import {
4
+ StockItemInventoryFilter,
5
+ useStockItemInventory,
6
+ } from "../../stock-items.resource";
7
+
8
+ export function useStockItemBatchInformationHook(v?: ResourceRepresentation) {
9
+ const [stockItemFilter, setStockItemFilter] =
10
+ useState<StockItemInventoryFilter>({
11
+ startIndex: 0,
12
+ v: v || ResourceRepresentation.Default,
13
+ limit: 10,
14
+ q: null,
15
+ totalCount: true,
16
+ includeBatchNo: true,
17
+ });
18
+
19
+ const pageSizes = [10, 20, 30, 40, 50];
20
+ const [currentPageSize, setPageSize] = useState(10);
21
+ const [searchString, setSearchString] = useState(null);
22
+
23
+ const [currentPage, setCurrentPage] = useState(1);
24
+
25
+ const [stockItemUuid, setStockItemUuid] = useState<string | null>();
26
+ const [partyUuid, setPartyUuid] = useState<string | null>();
27
+ const [locationUuid, setLocationUuid] = useState<string | null>();
28
+ const [stockBatchUuid, setStockBatchUuid] = useState<string | null>();
29
+
30
+ useEffect(() => {
31
+ setStockItemFilter({
32
+ startIndex: currentPage - 1,
33
+ v: ResourceRepresentation.Default,
34
+ limit: currentPageSize,
35
+ q: searchString,
36
+ totalCount: true,
37
+ stockItemUuid: stockItemUuid,
38
+ partyUuid: partyUuid,
39
+ locationUuid: locationUuid,
40
+ stockBatchUuid: stockBatchUuid,
41
+ includeBatchNo: true,
42
+ });
43
+ }, [
44
+ searchString,
45
+ currentPage,
46
+ currentPageSize,
47
+ stockItemUuid,
48
+ partyUuid,
49
+ locationUuid,
50
+ stockBatchUuid,
51
+ ]);
52
+
53
+ const { items, isLoading, isError } = useStockItemInventory(stockItemFilter);
54
+
55
+ return {
56
+ items: items.results ?? [],
57
+ totalCount: items.totalCount,
58
+ currentPage,
59
+ currentPageSize,
60
+ setCurrentPage,
61
+ setPageSize,
62
+ pageSizes,
63
+ isLoading,
64
+ isError,
65
+ setSearchString,
66
+ setStockItemUuid,
67
+ setLocationUuid,
68
+ setPartyUuid,
69
+ setStockBatchUuid,
70
+ };
71
+ }
@@ -0,0 +1,79 @@
1
+ import React, { ReactNode, useMemo, useState } from "react";
2
+ import { Concept } from "../../../core/api/types/concept/Concept";
3
+ import { Control, Controller, FieldValues } from "react-hook-form";
4
+ import { useConcepts } from "../../../stock-lookups/stock-lookups.resource";
5
+ import { ComboBox, TextInputSkeleton } from "@carbon/react";
6
+
7
+ interface ConceptsSelectorProps<T> {
8
+ conceptUuid?: string;
9
+ onConceptUuidChange?: (unit: Concept) => void;
10
+ title?: string;
11
+ placeholder?: string;
12
+ invalid?: boolean;
13
+ invalidText?: ReactNode;
14
+
15
+ // Control
16
+ controllerName: string;
17
+ name: string;
18
+ control: Control<FieldValues, T>;
19
+ }
20
+
21
+ const ConceptsSelector = <T,>(props: ConceptsSelectorProps<T>) => {
22
+ const {
23
+ items: { results: concepts },
24
+ isLoading,
25
+ } = useConcepts({});
26
+ const [inputValue, setInputValue] = useState("");
27
+ const handleInputChange = (value) => {
28
+ setInputValue(value);
29
+ };
30
+
31
+ const filteredConcepts = useMemo(() => {
32
+ return inputValue.trim() === ""
33
+ ? concepts
34
+ : concepts.filter((concept) =>
35
+ concept.display
36
+ .toLowerCase()
37
+ .includes(inputValue.trim().toLowerCase())
38
+ );
39
+ }, [inputValue, concepts]);
40
+
41
+ if (isLoading) return <TextInputSkeleton />;
42
+
43
+ return (
44
+ <Controller
45
+ name={props.controllerName}
46
+ control={props.control}
47
+ render={({ field: { onChange, ref } }) => (
48
+ <ComboBox
49
+ titleText={props.title}
50
+ name={props.name}
51
+ control={props.control}
52
+ controllerName={props.controllerName}
53
+ id={props.name}
54
+ size={"md"}
55
+ items={filteredConcepts}
56
+ onChange={(data: { selectedItem: Concept }) => {
57
+ props.onConceptUuidChange?.(data.selectedItem);
58
+ onChange(data.selectedItem.uuid);
59
+ }}
60
+ initialSelectedItem={
61
+ concepts?.find((p) => p.uuid === props.conceptUuid) || {}
62
+ }
63
+ itemToString={(item?: Concept) =>
64
+ item && item?.display ? `${item?.display}` : ""
65
+ }
66
+ shouldFilterItem={() => true}
67
+ onInputChange={(event) => handleInputChange(event)}
68
+ inputValue={inputValue}
69
+ placeholder={props.placeholder}
70
+ ref={ref}
71
+ invalid={props.invalid}
72
+ invalidText={props.invalidText}
73
+ />
74
+ )}
75
+ />
76
+ );
77
+ };
78
+
79
+ export default ConceptsSelector;
@@ -0,0 +1,8 @@
1
+ import { cleanup } from "@testing-library/react";
2
+
3
+ describe("Test the concepts selector", () => {
4
+ afterEach(cleanup);
5
+ it(`renders without dying`, () => {
6
+ // render(<ConceptsSelector />);
7
+ });
8
+ });
@@ -0,0 +1,76 @@
1
+ import React, { ReactNode, useState } from "react";
2
+ import { Control, Controller, FieldValues } from "react-hook-form";
3
+ import { StockItemPackagingUOMDTO } from "../../../core/api/types/stockItem/StockItemPackagingUOM";
4
+ import { Select, SelectItem, SelectSkeleton } from "@carbon/react";
5
+
6
+ interface DispensingPackageMeasurementProps<T> {
7
+ dispensingUnitPackagingUoMUuid?: string;
8
+ onDispensingUnitPackagingUoMUuidChange?: (
9
+ unit: StockItemPackagingUOMDTO
10
+ ) => void;
11
+ isLoading?: boolean;
12
+ packagingUnits?: StockItemPackagingUOMDTO[];
13
+ title?: string;
14
+ placeholder?: string;
15
+ invalid?: boolean;
16
+ invalidText?: ReactNode;
17
+
18
+ // Control
19
+ controllerName: string;
20
+ name: string;
21
+ control: Control<FieldValues, T>;
22
+ }
23
+
24
+ const DispensingPackageMeasurement = <T,>(
25
+ props: DispensingPackageMeasurementProps<T>
26
+ ) => {
27
+ const [item, setItem] = useState("");
28
+
29
+ if (props.isLoading) return <SelectSkeleton />;
30
+
31
+ if (!(props.packagingUnits && props.packagingUnits.length > 0)) return <></>;
32
+ return (
33
+ <Controller
34
+ name={props.controllerName}
35
+ control={props.control}
36
+ render={({ field: { onChange, value, ref } }) => (
37
+ <Select
38
+ labelText={props.title}
39
+ name={props.name}
40
+ control={props.control}
41
+ controllerName={props.controllerName}
42
+ id={props.name}
43
+ size={"md"}
44
+ onChange={(data: { selectedItem?: StockItemPackagingUOMDTO }) => {
45
+ props.onDispensingUnitPackagingUoMUuidChange?.(data?.selectedItem);
46
+ onChange(data?.selectedItem?.uuid);
47
+ setItem(data?.selectedItem?.uuid);
48
+ }}
49
+ ref={ref}
50
+ value={item}
51
+ invalid={props.invalid}
52
+ invalidText={props.invalidText}
53
+ >
54
+ {!item ? (
55
+ <SelectItem disabled hidden value={null} text={props.placeholder} />
56
+ ) : (
57
+ ""
58
+ )}
59
+ {props.packagingUnits?.map((uom, index) => {
60
+ return (
61
+ <SelectItem
62
+ key={`${index}-${uom.uuid}`}
63
+ value={uom.uuid}
64
+ text={uom.packagingUomName}
65
+ >
66
+ {uom?.packagingUomName}
67
+ </SelectItem>
68
+ );
69
+ })}
70
+ </Select>
71
+ )}
72
+ />
73
+ );
74
+ };
75
+
76
+ export default DispensingPackageMeasurement;
@@ -0,0 +1,66 @@
1
+ import React, { ReactNode } from "react";
2
+ import { ComboBox, TextInputSkeleton } from "@carbon/react";
3
+ import { useConceptById } from "../../../stock-lookups/stock-lookups.resource";
4
+ import { DISPENSING_UNITS_CONCEPT_ID } from "../../../constants";
5
+ import { Concept } from "../../../core/api/types/concept/Concept";
6
+ import { Control, Controller, FieldValues } from "react-hook-form";
7
+
8
+ interface DispensingUnitSelectorProps<T> {
9
+ dispensingUnitUuid?: string;
10
+ onDispensingUnitChange?: (unit: Concept) => void;
11
+ title?: string;
12
+ placeholder?: string;
13
+ invalid?: boolean;
14
+ invalidText?: ReactNode;
15
+
16
+ // Control
17
+ controllerName: string;
18
+ name: string;
19
+ control: Control<FieldValues, T>;
20
+ }
21
+
22
+ const DispensingUnitSelector = <T,>(props: DispensingUnitSelectorProps<T>) => {
23
+ const {
24
+ items: { setMembers: dispensingUnits },
25
+ isLoading,
26
+ } = useConceptById(DISPENSING_UNITS_CONCEPT_ID);
27
+
28
+ if (isLoading) return <TextInputSkeleton />;
29
+
30
+ return (
31
+ <Controller
32
+ name={props.controllerName}
33
+ control={props.control}
34
+ render={({ field: { onChange, value, ref } }) => (
35
+ <ComboBox
36
+ titleText={props.title}
37
+ name={props.name}
38
+ control={props.control}
39
+ controllerName={props.controllerName}
40
+ id={props.name}
41
+ size={"md"}
42
+ items={dispensingUnits || []}
43
+ onChange={(data: { selectedItem: Concept }) => {
44
+ props.onDispensingUnitChange?.(data.selectedItem);
45
+ onChange(data.selectedItem.uuid);
46
+ }}
47
+ initialSelectedItem={
48
+ dispensingUnits?.find((p) => p.uuid === props.dispensingUnitUuid) ||
49
+ {}
50
+ }
51
+ itemToString={(item?: Concept) =>
52
+ item && item?.display ? `${item?.display}` : ""
53
+ }
54
+ shouldFilterItem={() => true}
55
+ value={dispensingUnits?.find((p) => p.uuid === value)?.display ?? ""}
56
+ placeholder={props.placeholder}
57
+ ref={ref}
58
+ invalid={props.invalid}
59
+ invalidText={props.invalidText}
60
+ />
61
+ )}
62
+ />
63
+ );
64
+ };
65
+
66
+ export default DispensingUnitSelector;
@@ -0,0 +1,8 @@
1
+ import { cleanup } from "@testing-library/react";
2
+
3
+ describe("Test the dispensing unit selector", () => {
4
+ afterEach(cleanup);
5
+ it(`renders without dying`, () => {
6
+ // render(<DispensingUnitSelector />);
7
+ });
8
+ });
@@ -0,0 +1,83 @@
1
+ import React, { ReactNode, useMemo, useState } from "react";
2
+ import { ComboBox, InlineLoading } from "@carbon/react";
3
+ import { Drug } from "../../../core/api/types/concept/Drug";
4
+ import { Control, Controller, FieldValues } from "react-hook-form";
5
+ import { useDrugsHook } from "./drug-selector.resource";
6
+
7
+ interface DrugSelectorProps<T> {
8
+ placeholder?: string;
9
+ drugUuid?: string;
10
+ onDrugChanged?: (drug: Drug) => void;
11
+ title?: string;
12
+ invalid?: boolean;
13
+ invalidText?: ReactNode;
14
+
15
+ // Control
16
+ controllerName: string;
17
+ name: string;
18
+ control: Control<FieldValues, T>;
19
+ }
20
+
21
+ const DrugSelector = <T,>(props: DrugSelectorProps<T>) => {
22
+ const { isLoading, drugList } = useDrugsHook();
23
+
24
+ const [inputValue, setInputValue] = useState("");
25
+ const handleInputChange = (value) => {
26
+ setInputValue(value);
27
+ };
28
+ const filteredDrugs = useMemo(() => {
29
+ return inputValue.trim() === ""
30
+ ? drugList
31
+ : drugList.filter((drug) =>
32
+ drug.name.toLowerCase().includes(inputValue.trim().toLowerCase())
33
+ );
34
+ }, [inputValue, drugList]);
35
+
36
+ return (
37
+ <div>
38
+ <Controller
39
+ name={props.controllerName}
40
+ control={props.control}
41
+ render={({ field: { onChange, ref } }) => (
42
+ <ComboBox
43
+ titleText={props.title}
44
+ name={props.name}
45
+ control={props.control}
46
+ controllerName={props.controllerName}
47
+ id={props.name}
48
+ size={"md"}
49
+ items={filteredDrugs || []}
50
+ initialSelectedItem={
51
+ drugList?.find((p) => p.uuid === props.drugUuid) ?? ""
52
+ }
53
+ itemToString={drugName}
54
+ onChange={(data: { selectedItem: Drug }) => {
55
+ props.onDrugChanged?.(data.selectedItem);
56
+ onChange(data.selectedItem.uuid);
57
+ }}
58
+ onInputChange={(event) => handleInputChange(event)}
59
+ inputValue={inputValue}
60
+ placeholder={props.placeholder}
61
+ invalid={props.invalid}
62
+ invalidText={props.invalidText}
63
+ ref={ref}
64
+ />
65
+ )}
66
+ />
67
+ {isLoading && (
68
+ <InlineLoading
69
+ status="active"
70
+ iconDescription="Searching"
71
+ description="Searching..."
72
+ />
73
+ )}
74
+ </div>
75
+ );
76
+ };
77
+ function drugName(item: Drug): string {
78
+ return item
79
+ ? `${item.name}${item.concept ? ` (${item.concept.display})` : ""}`
80
+ : "";
81
+ }
82
+
83
+ export default DrugSelector;
@@ -0,0 +1,50 @@
1
+ import { ResourceRepresentation } from "../../../core/api/api";
2
+ import { useEffect, useState } from "react";
3
+ import {
4
+ ConceptFilterCriteria,
5
+ useDrugs,
6
+ } from "../../../stock-lookups/stock-lookups.resource";
7
+ import { debounce } from "../../../core/utils/debounce";
8
+
9
+ export function useDrugsHook(filter?: ConceptFilterCriteria) {
10
+ const [conceptFilter, setConceptFilter] = useState<ConceptFilterCriteria>(
11
+ filter || {
12
+ v: ResourceRepresentation.Default,
13
+ startIndex: 0,
14
+ }
15
+ );
16
+
17
+ const {
18
+ items: { results: drugList },
19
+ isLoading,
20
+ } = useDrugs(conceptFilter);
21
+
22
+ const [searchString, setSearchString] = useState("");
23
+
24
+ // Drug filter type
25
+ const [limit, setLimit] = useState(filter?.limit || 10);
26
+ const [representation, setRepresentation] = useState(
27
+ filter?.v || ResourceRepresentation.Default
28
+ );
29
+
30
+ useEffect(() => {
31
+ debounce(
32
+ () =>
33
+ setConceptFilter({
34
+ startIndex: 0,
35
+ v: representation,
36
+ limit: limit,
37
+ q: searchString,
38
+ }),
39
+ 500
40
+ );
41
+ }, [searchString, limit, representation]);
42
+
43
+ return {
44
+ drugList,
45
+ setLimit,
46
+ setRepresentation,
47
+ setSearchString,
48
+ isLoading,
49
+ };
50
+ }