@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,156 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Controller, Control, useFormContext } from 'react-hook-form';
4
+ import { ResponsiveWrapper } from '@openmrs/esm-framework';
5
+ import { TextInput, Button, Dropdown, Toggle } from '@carbon/react';
6
+ import styles from './payment-mode-attributes.scss';
7
+ import { PAYMENT_MODE_ATTRIBUTE_FORMATS } from '../../../../constant';
8
+
9
+ type PaymentModeAttributeFields = {
10
+ field: Record<string, any>;
11
+ index: number;
12
+ control: Control<Record<string, any>>;
13
+ removeAttributeType: (index: number) => void;
14
+ errors: Record<string, any>;
15
+ };
16
+
17
+ const PaymentModeAttributeFields: React.FC<PaymentModeAttributeFields> = ({
18
+ field,
19
+ index,
20
+ control,
21
+ removeAttributeType,
22
+ errors,
23
+ }) => {
24
+ const { t } = useTranslation();
25
+ const { watch } = useFormContext();
26
+ const retired = watch(`attributeTypes.${index}.retired`);
27
+
28
+ return (
29
+ <div className={styles.paymentModeAttributes}>
30
+ <ResponsiveWrapper>
31
+ <Controller
32
+ control={control}
33
+ name={`attributeTypes.${index}.name`}
34
+ render={({ field }) => (
35
+ <TextInput
36
+ {...field}
37
+ labelText={t('attributeName', 'Attribute name')}
38
+ placeholder={t('enterAttributeName', 'Enter attribute name')}
39
+ invalid={!!errors?.attributeTypes?.[index]?.name}
40
+ invalidText={errors?.attributeTypes?.[index]?.name?.message}
41
+ id={`attributeTypes.${index}.name`}
42
+ />
43
+ )}
44
+ />
45
+ </ResponsiveWrapper>
46
+ <ResponsiveWrapper>
47
+ <Controller
48
+ control={control}
49
+ name={`attributeTypes.${index}.description`}
50
+ render={({ field }) => (
51
+ <TextInput
52
+ {...field}
53
+ labelText={t('attributeDescription', 'Attribute description')}
54
+ placeholder={t('enterAttributeDescription', 'Enter attribute description')}
55
+ invalid={!!errors?.attributeTypes?.[index]?.description}
56
+ invalidText={errors?.attributeTypes?.[index]?.description?.message}
57
+ id={`attributeTypes.${index}.description`}
58
+ />
59
+ )}
60
+ />
61
+ </ResponsiveWrapper>
62
+ <ResponsiveWrapper>
63
+ <Controller
64
+ control={control}
65
+ name={`attributeTypes.${index}.retired`}
66
+ render={({ field }) => (
67
+ <Toggle
68
+ {...field}
69
+ labelText={t('attributeEnabled', 'Attribute enabled')}
70
+ labelA="Off"
71
+ labelB="On"
72
+ toggled={!field.value}
73
+ id={`attributeTypes.${index}.retired`}
74
+ onToggle={(value) => field.onChange(!value)}
75
+ />
76
+ )}
77
+ />
78
+ </ResponsiveWrapper>
79
+ {retired && (
80
+ <ResponsiveWrapper>
81
+ <Controller
82
+ control={control}
83
+ name={`attributeTypes.${index}.retiredReason`}
84
+ render={({ field }) => (
85
+ <TextInput
86
+ id={`attributeTypes.${index}.retireReason`}
87
+ {...field}
88
+ labelText={t('attributeRetiredReason', 'Attribute retired reason')}
89
+ placeholder={t('enterAttributeRetiredReason', 'Enter attribute retired reason')}
90
+ invalid={!!errors?.attributeTypes?.[index]?.retiredReason}
91
+ invalidText={errors?.attributeTypes?.[index]?.retiredReason?.message}
92
+ />
93
+ )}
94
+ />
95
+ </ResponsiveWrapper>
96
+ )}
97
+ <ResponsiveWrapper>
98
+ <Controller
99
+ control={control}
100
+ name={`attributeTypes.${index}.format`}
101
+ render={({ field }) => (
102
+ <Dropdown
103
+ {...field}
104
+ label={t('attributeFormat', 'Attribute format')}
105
+ id={`attributeTypes.${index}.format`}
106
+ titleText={t('attributeFormat', 'Attribute format')}
107
+ aria-placeholder={t('selectAttributeFormat', 'Select attribute format')}
108
+ onChange={(event) => field.onChange(event.selectedItem)}
109
+ initialSelectedItem={field.value}
110
+ helperText={t('attributeFormatHelperText', 'The format of the attribute value e.g Free text, Number')}
111
+ items={PAYMENT_MODE_ATTRIBUTE_FORMATS}
112
+ invalid={!!errors?.attributeTypes?.[index]?.format}
113
+ invalidText={errors?.attributeTypes?.[index]?.format?.message}
114
+ />
115
+ )}
116
+ />
117
+ </ResponsiveWrapper>
118
+ <ResponsiveWrapper>
119
+ <Controller
120
+ control={control}
121
+ name={`attributeTypes.${index}.regExp`}
122
+ render={({ field }) => (
123
+ <TextInput
124
+ {...field}
125
+ id={`attributeTypes.${index}.regExp`}
126
+ labelText={t('regExp', 'Regular expression')}
127
+ placeholder={t('enterRegExp', 'Enter regular expression')}
128
+ />
129
+ )}
130
+ />
131
+ </ResponsiveWrapper>
132
+ <ResponsiveWrapper>
133
+ <Controller
134
+ control={control}
135
+ name={`attributeTypes.${index}.required`}
136
+ render={({ field }) => (
137
+ <Toggle
138
+ {...field}
139
+ labelText={t('attributeRequired', 'Attribute required')}
140
+ labelA="Off"
141
+ labelB="On"
142
+ toggled={field.value}
143
+ id={`attributeTypes.${index}.required`}
144
+ onToggle={(value) => field.onChange(value)}
145
+ />
146
+ )}
147
+ />
148
+ </ResponsiveWrapper>
149
+ <Button size="sm" kind="danger--tertiary" onClick={() => removeAttributeType(index)}>
150
+ {t('remove', 'Remove')}
151
+ </Button>
152
+ </div>
153
+ );
154
+ };
155
+
156
+ export default PaymentModeAttributeFields;
@@ -0,0 +1,10 @@
1
+ @use '@carbon/layout';
2
+ @use '@carbon/colors';
3
+
4
+ .paymentModeAttributes {
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: layout.$spacing-05;
8
+ outline: 1px solid colors.$gray-10;
9
+ padding: layout.$spacing-05;
10
+ }
@@ -0,0 +1,243 @@
1
+ import React, { useMemo, useState } from 'react';
2
+ import {
3
+ Button,
4
+ DataTable,
5
+ DataTableSkeleton,
6
+ Table,
7
+ TableBody,
8
+ TableCell,
9
+ TableContainer,
10
+ TableHead,
11
+ TableHeader,
12
+ TableRow,
13
+ TableExpandHeader,
14
+ TableExpandRow,
15
+ TableExpandedRow,
16
+ Layer,
17
+ Pagination,
18
+ Tile,
19
+ IconButton,
20
+ } from '@carbon/react';
21
+ import { Add, Edit, TrashCan } from '@carbon/react/icons';
22
+ import { launchWorkspace, useLayoutType, ErrorState, showModal } from '@openmrs/esm-framework';
23
+ import { useTranslation } from 'react-i18next';
24
+ import startCase from 'lodash-es/startCase';
25
+ import styles from './billing-payment-modes.scss';
26
+ import { CardHeader } from '@openmrs/esm-patient-common-lib';
27
+ import { PaymentMethod } from './type';
28
+ import { usePaymentModes } from './billing-payment-modes.resource';
29
+
30
+ const PaymentModeTable = () => {
31
+ const { t } = useTranslation();
32
+ const layout = useLayoutType();
33
+ const isTablet = layout === 'tablet';
34
+ const responsiveSize = isTablet ? 'lg' : 'sm';
35
+
36
+ const { paymentModes, isLoading, error } = usePaymentModes(false);
37
+
38
+ // Pagination state
39
+ const [currentPage, setCurrentPage] = useState(1);
40
+ const [currentPageSize, setCurrentPageSize] = useState(10);
41
+ const pageSizes = [10, 20, 30, 40, 50];
42
+
43
+ const headers = [
44
+ {
45
+ key: 'dateCreated',
46
+ header: t('dateCreated', 'Date Created'),
47
+ },
48
+ {
49
+ key: 'name',
50
+ header: t('name', 'Name'),
51
+ },
52
+ {
53
+ key: 'description',
54
+ header: t('description', 'Description'),
55
+ },
56
+ {
57
+ key: 'retired',
58
+ header: t('retired', 'Retired'),
59
+ },
60
+ ];
61
+
62
+ // Transform payment modes to table rows
63
+ const tableRows = useMemo(() => {
64
+ if (!paymentModes) {
65
+ return [];
66
+ }
67
+
68
+ return paymentModes.map((mode) => ({
69
+ id: mode.uuid,
70
+ dateCreated: new Date(mode.auditInfo.dateCreated).toLocaleDateString(),
71
+ name: mode.name,
72
+ description: mode.description || '-',
73
+ retired: mode.retired ? t('yes', 'Yes') : t('no', 'No'),
74
+ paymentMode: mode, // Store full object for expandable row
75
+ }));
76
+ }, [paymentModes, t]);
77
+
78
+ // Paginated rows
79
+ const paginatedRows = useMemo(() => {
80
+ const startIndex = (currentPage - 1) * currentPageSize;
81
+ const endIndex = startIndex + currentPageSize;
82
+ return tableRows.slice(startIndex, endIndex);
83
+ }, [tableRows, currentPage, currentPageSize]);
84
+
85
+ const handleAddPaymentMode = () => {
86
+ launchWorkspace('payment-mode-workspace');
87
+ };
88
+
89
+ const showDeletePaymentModeModal = (paymentMode: PaymentMethod) => {
90
+ const dispose = showModal('delete-payment-mode-modal', {
91
+ closeModal: () => dispose(),
92
+ paymentMode,
93
+ });
94
+ };
95
+
96
+ if (isLoading) {
97
+ return (
98
+ <div className={styles.section}>
99
+ <h3>{t('paymentModes', 'Payment Modes')}</h3>
100
+ <DataTableSkeleton role="progressbar" compact={!isTablet} zebra />
101
+ </div>
102
+ );
103
+ }
104
+
105
+ if (error) {
106
+ return <ErrorState error={error} headerTitle={t('paymentModes', 'Payment Modes')} />;
107
+ }
108
+
109
+ return (
110
+ <div className={styles.section}>
111
+ <CardHeader title={t('paymentModes', 'Payment Modes')}>
112
+ <Button kind="ghost" renderIcon={(props) => <Add size={16} {...props} />} onClick={handleAddPaymentMode}>
113
+ {t('addPaymentMode', 'Add Payment Mode')}
114
+ </Button>
115
+ </CardHeader>
116
+ <Layer>
117
+ <DataTable rows={paginatedRows} headers={headers} isSortable size={responsiveSize} useZebraStyles>
118
+ {({ rows, headers, getHeaderProps, getRowProps, getTableProps, getExpandedRowProps }) => (
119
+ <TableContainer>
120
+ <Table {...getTableProps()} aria-label={t('paymentModesTable', 'Payment modes table')}>
121
+ <TableHead>
122
+ <TableRow>
123
+ <TableExpandHeader />
124
+ {headers.map((header) => (
125
+ <TableHeader key={header.key} {...getHeaderProps({ header })}>
126
+ {header.header}
127
+ </TableHeader>
128
+ ))}
129
+ <TableHeader>{t('actions', 'Actions')}</TableHeader>
130
+ </TableRow>
131
+ </TableHead>
132
+ <TableBody>
133
+ {rows.map((row, index) => {
134
+ const paymentMode = paginatedRows[index]?.paymentMode;
135
+ return (
136
+ <React.Fragment key={row.id}>
137
+ <TableExpandRow {...getRowProps({ row })}>
138
+ {row.cells.map((cell) => (
139
+ <TableCell key={cell.id}>{cell.value}</TableCell>
140
+ ))}
141
+ <TableCell>
142
+ <div style={{ display: 'flex', gap: '0.5rem' }}>
143
+ <IconButton
144
+ kind="ghost"
145
+ size={responsiveSize}
146
+ label={t('edit', 'Edit')}
147
+ onClick={() =>
148
+ launchWorkspace('payment-mode-workspace', {
149
+ workspaceTitle: t('editPaymentMode', 'Edit Payment Mode'),
150
+ initialPaymentMode: paymentMode,
151
+ })
152
+ }>
153
+ <Edit />
154
+ </IconButton>
155
+ <IconButton
156
+ kind="danger--ghost"
157
+ size={responsiveSize}
158
+ label={t('delete', 'Delete')}
159
+ onClick={() => showDeletePaymentModeModal(paymentMode)}>
160
+ <TrashCan />
161
+ </IconButton>
162
+ </div>
163
+ </TableCell>
164
+ </TableExpandRow>
165
+ <TableExpandedRow
166
+ colSpan={headers.length + 2}
167
+ className="demo-expanded-td"
168
+ {...getExpandedRowProps({ row })}>
169
+ {paymentMode && <PaymentModeAttributes paymentMode={paymentMode} />}
170
+ </TableExpandedRow>
171
+ </React.Fragment>
172
+ );
173
+ })}
174
+ </TableBody>
175
+ </Table>
176
+ {tableRows.length === 0 ? (
177
+ <div className={styles.tileContainer}>
178
+ <Tile className={styles.tile}>
179
+ <div className={styles.tileContent}>
180
+ <p className={styles.content}>{t('noPaymentModesFound', 'No payment modes found')}</p>
181
+ <p className={styles.emptyStateHelperText}>
182
+ {t('checkFilters', 'Please check the filters above and try again')}
183
+ </p>
184
+ </div>
185
+ </Tile>
186
+ </div>
187
+ ) : null}
188
+ {tableRows.length > 0 && (
189
+ <Pagination
190
+ forwardText={t('nextPage', 'Next page')}
191
+ backwardText={t('previousPage', 'Previous page')}
192
+ page={currentPage}
193
+ pageSize={currentPageSize}
194
+ pageSizes={pageSizes}
195
+ totalItems={tableRows.length}
196
+ className={styles.pagination}
197
+ onChange={({ pageSize, page }) => {
198
+ if (pageSize !== currentPageSize) {
199
+ setCurrentPageSize(pageSize);
200
+ setCurrentPage(1);
201
+ }
202
+ if (page !== currentPage) {
203
+ setCurrentPage(page);
204
+ }
205
+ }}
206
+ />
207
+ )}
208
+ </TableContainer>
209
+ )}
210
+ </DataTable>
211
+ </Layer>
212
+ </div>
213
+ );
214
+ };
215
+
216
+ const PaymentModeAttributes: React.FC<{ paymentMode: PaymentMethod }> = ({ paymentMode }) => {
217
+ const { t } = useTranslation();
218
+ const { attributeTypes } = paymentMode;
219
+
220
+ return (
221
+ <div className={styles.attributeContainer}>
222
+ {attributeTypes.map((attributeType, index) =>
223
+ Object.entries(attributeType).map(([key, value]) => {
224
+ if (key === 'uuid') {
225
+ return null;
226
+ }
227
+ return <AttributeCard key={`${index}-${key}`} label={key} value={JSON.stringify(value)} />;
228
+ }),
229
+ )}
230
+ </div>
231
+ );
232
+ };
233
+
234
+ const AttributeCard: React.FC<{ label: string; value: string }> = ({ label, value }) => {
235
+ return (
236
+ <div className={styles.attributeCard}>
237
+ <div className={styles.attributeLabel}>{startCase(label).replace(/\s+/g, ' ')}</div>
238
+ <div className={styles.attributeValue}>{value.replace(/['"]/g, '')}</div>
239
+ </div>
240
+ );
241
+ };
242
+
243
+ export default PaymentModeTable;
@@ -0,0 +1,23 @@
1
+ import { openmrsFetch, restBaseUrl, useConfig } from '@openmrs/esm-framework';
2
+ import useSWR from 'swr';
3
+ import { PaymentMethod } from './type';
4
+ import { ConfigObject } from '../../config-schema';
5
+
6
+ export const usePaymentModes = (excludeWaiver: boolean = true) => {
7
+ const { excludedPaymentMode } = useConfig<ConfigObject>();
8
+ const url = `${restBaseUrl}/cashier/paymentMode?v=full`;
9
+ const { data, isLoading, error, mutate } = useSWR<{ data: { results: Array<PaymentMethod> } }>(url, openmrsFetch, {
10
+ errorRetryCount: 2,
11
+ });
12
+ const allowedPaymentModes =
13
+ excludedPaymentMode?.length > 0
14
+ ? (data?.data?.results.filter((mode) => !excludedPaymentMode.some((excluded) => excluded.uuid === mode.uuid)) ??
15
+ [])
16
+ : (data?.data?.results ?? []);
17
+ return {
18
+ paymentModes: excludeWaiver ? allowedPaymentModes : data?.data?.results,
19
+ isLoading,
20
+ mutate,
21
+ error,
22
+ };
23
+ };
@@ -0,0 +1,140 @@
1
+ @use '@carbon/layout';
2
+ @use '@carbon/type';
3
+ @use '@carbon/colors';
4
+
5
+ :global(.cds--tab-content) {
6
+ padding: 0 !important;
7
+ padding-top: var(--cds-layout-density-padding-inline-local) !important;
8
+ }
9
+
10
+ .adminPage {
11
+ // padding: layout.$spacing-05;
12
+ background: var(--cds-field);
13
+ }
14
+
15
+ .section {
16
+ margin-bottom: layout.$spacing-07;
17
+
18
+ &:last-child {
19
+ margin-bottom: 0;
20
+ }
21
+ }
22
+
23
+ .sectionHeader {
24
+ display: flex;
25
+ justify-content: space-between;
26
+ align-items: center;
27
+ margin-bottom: layout.$spacing-05;
28
+ padding-bottom: layout.$spacing-03;
29
+ border-bottom: 1px solid var(--cds-border-subtle);
30
+
31
+ h3 {
32
+ margin: 0;
33
+ color: var(--cds-text-primary);
34
+ font-size: 1.25rem;
35
+ font-weight: 600;
36
+ }
37
+ }
38
+
39
+ @media (max-width: 768px) {
40
+ .adminPage {
41
+ padding: layout.$spacing-03;
42
+ }
43
+
44
+ .sectionHeader {
45
+ flex-direction: column;
46
+ align-items: flex-start;
47
+ gap: layout.$spacing-03;
48
+
49
+ h3 {
50
+ font-size: 1.125rem;
51
+ }
52
+ }
53
+ }
54
+
55
+ .tileContainer {
56
+ border-top: 1px solid colors.$gray-20;
57
+ padding: 3rem 0;
58
+ }
59
+
60
+ .tile {
61
+ margin: auto;
62
+ width: fit-content;
63
+ background: colors.$gray-20;
64
+ }
65
+
66
+ .tileContent {
67
+ display: flex;
68
+ flex-direction: column;
69
+ align-items: center;
70
+ }
71
+
72
+ .content {
73
+ @include type.type-style('heading-compact-02');
74
+ color: colors.$gray-70;
75
+ margin-bottom: layout.$spacing-03;
76
+ }
77
+
78
+ .singleLineDisplay {
79
+ white-space: nowrap;
80
+ }
81
+
82
+ .emptyStateHelperText {
83
+ @include type.type-style('helper-text-02');
84
+ }
85
+
86
+ // Expanded row styles for payment mode attributes
87
+ .attributeContainer {
88
+ display: grid;
89
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
90
+ gap: layout.$spacing-05;
91
+ padding: layout.$spacing-05;
92
+ background-color: var(--cds-layer-01);
93
+ border-top: 1px solid var(--cds-border-subtle-01);
94
+ }
95
+
96
+ .attributeCard {
97
+ display: flex;
98
+ flex-direction: column;
99
+ padding: layout.$spacing-04;
100
+ background-color: var(--cds-layer-02);
101
+ border-radius: 4px;
102
+ border: 1px solid var(--cds-border-subtle-01);
103
+ transition: all 0.15s ease-in-out;
104
+
105
+ &:hover {
106
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
107
+ border-color: var(--cds-border-subtle-02);
108
+ }
109
+ }
110
+
111
+ .attributeLabel {
112
+ @include type.type-style('label-01');
113
+ color: var(--cds-text-secondary);
114
+ margin-bottom: layout.$spacing-02;
115
+ font-weight: 600;
116
+ text-transform: capitalize;
117
+ }
118
+
119
+ .attributeValue {
120
+ @include type.type-style('body-compact-01');
121
+ color: var(--cds-text-primary);
122
+ word-break: break-word;
123
+ overflow-wrap: break-word;
124
+ }
125
+
126
+ .pagination {
127
+ border-top: 1px solid var(--cds-border-subtle-01);
128
+ }
129
+
130
+ @media (max-width: 768px) {
131
+ .attributeContainer {
132
+ grid-template-columns: 1fr;
133
+ padding: layout.$spacing-03;
134
+ gap: layout.$spacing-03;
135
+ }
136
+
137
+ .attributeCard {
138
+ padding: layout.$spacing-03;
139
+ }
140
+ }
@@ -0,0 +1,42 @@
1
+ export interface PaymentMethod {
2
+ uuid: string;
3
+ name: string;
4
+ description: string;
5
+ retired: boolean;
6
+ retireReason: null;
7
+ auditInfo: AuditInfo;
8
+ attributeTypes: AttributeType[];
9
+ sortOrder: null;
10
+ resourceVersion: string;
11
+ }
12
+ export interface AttributeType {
13
+ uuid?: string;
14
+ name: string;
15
+ description: string;
16
+ retired: boolean;
17
+ attributeOrder?: number;
18
+ format?: string;
19
+ foreignKey?: string | null;
20
+ regExp?: string | null;
21
+ required: boolean;
22
+ value?: string;
23
+ }
24
+
25
+ export interface AuditInfo {
26
+ creator: Creator;
27
+ dateCreated: string;
28
+ changedBy: null;
29
+ dateChanged: null;
30
+ }
31
+
32
+ export interface Creator {
33
+ uuid: string;
34
+ display: string;
35
+ links: Link[];
36
+ }
37
+
38
+ export interface Link {
39
+ rel: string;
40
+ uri: string;
41
+ resourceAlias: string;
42
+ }
@@ -0,0 +1,28 @@
1
+ @use '@carbon/type';
2
+ @use '@carbon/layout';
3
+
4
+ .modalHeaderLabel {
5
+ @include type.type-style('heading-compact-02');
6
+
7
+ & > div {
8
+ display: none;
9
+ }
10
+ }
11
+ .button_spinner {
12
+ padding: 0;
13
+ margin-right: layout.$spacing-03;
14
+ }
15
+
16
+ .loading_wrapper {
17
+ display: flex;
18
+ align-items: center;
19
+ }
20
+
21
+ .contentContainer {
22
+ padding-left: layout.$spacing-05;
23
+ }
24
+
25
+ .contentValue {
26
+ @include type.type-style('heading-compact-02');
27
+ margin-bottom: layout.$spacing-03;
28
+ }