@kenyaemr/esm-bed-management-app 1.0.1-pre.11

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 (137) hide show
  1. package/.editorconfig +12 -0
  2. package/.eslintignore +2 -0
  3. package/.eslintrc +37 -0
  4. package/.husky/pre-commit +4 -0
  5. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  6. package/.idea/modules.xml +8 -0
  7. package/.idea/vcs.xml +6 -0
  8. package/.prettierignore +14 -0
  9. package/.turbo.json +18 -0
  10. package/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs +541 -0
  11. package/.yarn/plugins/@yarnpkg/plugin-version.cjs +550 -0
  12. package/.yarn/versions/3d353a50.yml +0 -0
  13. package/LICENSE +373 -0
  14. package/README.md +40 -0
  15. package/dist/207.js +1 -0
  16. package/dist/207.js.map +1 -0
  17. package/dist/26.js +2 -0
  18. package/dist/26.js.LICENSE.txt +32 -0
  19. package/dist/26.js.map +1 -0
  20. package/dist/283.js +1 -0
  21. package/dist/283.js.map +1 -0
  22. package/dist/294.js +2 -0
  23. package/dist/294.js.LICENSE.txt +9 -0
  24. package/dist/294.js.map +1 -0
  25. package/dist/330.js +2 -0
  26. package/dist/330.js.LICENSE.txt +44 -0
  27. package/dist/330.js.map +1 -0
  28. package/dist/404.js +1 -0
  29. package/dist/404.js.map +1 -0
  30. package/dist/455.js +2 -0
  31. package/dist/455.js.LICENSE.txt +9 -0
  32. package/dist/455.js.map +1 -0
  33. package/dist/558.js +2 -0
  34. package/dist/558.js.LICENSE.txt +14 -0
  35. package/dist/558.js.map +1 -0
  36. package/dist/574.js +1 -0
  37. package/dist/629.js +1 -0
  38. package/dist/629.js.map +1 -0
  39. package/dist/637.js +1 -0
  40. package/dist/637.js.map +1 -0
  41. package/dist/707.js +1 -0
  42. package/dist/707.js.map +1 -0
  43. package/dist/800.js +2 -0
  44. package/dist/800.js.LICENSE.txt +3 -0
  45. package/dist/800.js.map +1 -0
  46. package/dist/850.js +1 -0
  47. package/dist/850.js.map +1 -0
  48. package/dist/884.js +1 -0
  49. package/dist/884.js.map +1 -0
  50. package/dist/933.js +1 -0
  51. package/dist/933.js.map +1 -0
  52. package/dist/esm-kenyaemr-bed-management-app.js +1 -0
  53. package/dist/esm-kenyaemr-bed-management-app.js.buildmanifest.json +506 -0
  54. package/dist/esm-kenyaemr-bed-management-app.js.map +1 -0
  55. package/dist/main.js +1 -0
  56. package/dist/main.js.map +1 -0
  57. package/dist/routes.json +1 -0
  58. package/i18next-parser.config.js +89 -0
  59. package/jest.config.js +0 -0
  60. package/package.json +112 -0
  61. package/src/__mocks__/react-i18next.js +55 -0
  62. package/src/admin-card-link.component.tsx +27 -0
  63. package/src/assets/landing-page.png +0 -0
  64. package/src/assets/logo.svg +1 -0
  65. package/src/bed-administration/bed-administration-form.component.tsx +326 -0
  66. package/src/bed-administration/bed-administration-form.scss +0 -0
  67. package/src/bed-administration/bed-administration-table.component.tsx +317 -0
  68. package/src/bed-administration/bed-administration-table.scss +112 -0
  69. package/src/bed-administration/bed-administration-types.ts +20 -0
  70. package/src/bed-administration/bed-administration.resource.ts +59 -0
  71. package/src/bed-administration/edit-bed-form.component.tsx +100 -0
  72. package/src/bed-administration/new-bed-form.component.tsx +112 -0
  73. package/src/bed-admission/active-patients/active-patients-table.component.tsx +299 -0
  74. package/src/bed-admission/active-patients/active-visits.resource.ts +171 -0
  75. package/src/bed-admission/active-patients/admission-action-button-styles.scss +0 -0
  76. package/src/bed-admission/active-patients/admission-action-button.component.tsx +26 -0
  77. package/src/bed-admission/active-patients/index.tsx +15 -0
  78. package/src/bed-admission/active-patients/patient-queues.resource.ts +136 -0
  79. package/src/bed-admission/active-patients/styles.scss +284 -0
  80. package/src/bed-admission/active-patients/view-action-menu.component.tsx +33 -0
  81. package/src/bed-admission/admitted-patients/active-admissions.resource.ts +125 -0
  82. package/src/bed-admission/admitted-patients/admitted-patients-table.component.tsx +280 -0
  83. package/src/bed-admission/admitted-patients/admitted-patients.component.tsx +22 -0
  84. package/src/bed-admission/admitted-patients/location-combo-box.component.tsx +55 -0
  85. package/src/bed-admission/admitted-patients/styles.scss +284 -0
  86. package/src/bed-admission/bed-admission-tabs-styles.scss +30 -0
  87. package/src/bed-admission/bed-admission-tabs.component.tsx +69 -0
  88. package/src/bed-admission/bed-admission.component.tsx +15 -0
  89. package/src/bed-admission/bed-admission.resource.ts +52 -0
  90. package/src/bed-admission/bed-layout/bed-layout-list.component.tsx +101 -0
  91. package/src/bed-admission/bed-layout/bed-layout.component.tsx +64 -0
  92. package/src/bed-admission/bed-layout/bed-layout.scss +118 -0
  93. package/src/bed-admission/bed-layout/min-bed-layout.component.tsx +26 -0
  94. package/src/bed-admission/bed-tag/bed-tag-administration-table.component.tsx +217 -0
  95. package/src/bed-admission/bed-tag/bed-tags-admin-form.component.tsx +131 -0
  96. package/src/bed-admission/bed-tag/edit-tag-form.component.tsx +80 -0
  97. package/src/bed-admission/bed-tag/new-tag-form.component.tsx +83 -0
  98. package/src/bed-admission/bed-type/bed-type-admin-form.component.tsx +173 -0
  99. package/src/bed-admission/bed-type/bed-type-administration-table.component.tsx +222 -0
  100. package/src/bed-admission/bed-type/edit-bed-type.component.tsx +80 -0
  101. package/src/bed-admission/bed-type/new-bed-type-form.component.tsx +87 -0
  102. package/src/bed-admission/createDashboardLink.tsx +47 -0
  103. package/src/bed-admission/discharged-patients/discharged-patients.componet.tsx +19 -0
  104. package/src/bed-admission/helpers/functions.ts +102 -0
  105. package/src/bed-admission/types.ts +133 -0
  106. package/src/config-schema.ts +31 -0
  107. package/src/declarations.d.ts +7 -0
  108. package/src/empty-state/empty-state.component.tsx +69 -0
  109. package/src/empty-state/empty-state.scss +62 -0
  110. package/src/header/header.component.tsx +51 -0
  111. package/src/header/header.scss +72 -0
  112. package/src/header/illustration.component.tsx +13 -0
  113. package/src/home.component.tsx +15 -0
  114. package/src/home.scss +5 -0
  115. package/src/index.ts +78 -0
  116. package/src/left-panel/left-panel.component.tsx +33 -0
  117. package/src/left-panel/left-panel.scss +41 -0
  118. package/src/left-panel-link.component.tsx +49 -0
  119. package/src/root.component.tsx +39 -0
  120. package/src/root.scss +11 -0
  121. package/src/routes.json +56 -0
  122. package/src/setup-tests.ts +1 -0
  123. package/src/summary/summary.component.tsx +74 -0
  124. package/src/summary/summary.resource.ts +211 -0
  125. package/src/summary/summary.scss +72 -0
  126. package/src/types.ts +163 -0
  127. package/src/ward-card/ward-card.component.tsx +41 -0
  128. package/src/ward-card/ward-card.scss +51 -0
  129. package/src/ward-with-beds/ward-with-beds.component.tsx +186 -0
  130. package/src/ward-with-beds/ward-with-beds.scss +27 -0
  131. package/src/workspace/allocate-bed-workspace.component.tsx +188 -0
  132. package/src/workspace/allocate-bed.scss +124 -0
  133. package/src/workspace/overlay.component.tsx +55 -0
  134. package/src/workspace/overlay.scss +96 -0
  135. package/translations/en.json +7 -0
  136. package/tsconfig.json +23 -0
  137. package/webpack.config.js +1 -0
@@ -0,0 +1,131 @@
1
+ import React, { useState } from "react";
2
+ import { z } from "zod";
3
+ import { useForm, Controller } from "react-hook-form";
4
+ import { zodResolver } from "@hookform/resolvers/zod";
5
+ import {
6
+ Button,
7
+ ComposedModal,
8
+ Form,
9
+ FormGroup,
10
+ ModalBody,
11
+ ModalFooter,
12
+ ModalHeader,
13
+ Stack,
14
+ TextInput,
15
+ InlineNotification,
16
+ } from "@carbon/react";
17
+ import { useTranslation } from "react-i18next";
18
+ import { Location } from "@openmrs/esm-framework";
19
+ import type { BedTagData } from "../../types";
20
+
21
+ const BedTagAdministrationSchema = z.object({
22
+ name: z.string().max(255),
23
+ });
24
+
25
+ interface BedTagAdministrationFormProps {
26
+ showModal: boolean;
27
+ onModalChange: (showModal: boolean) => void;
28
+ availableBedTypes: Array<BedTagData>;
29
+ allLocations: Location[];
30
+ handleCreateQuestion?: (formData: BedTagData) => void;
31
+ handleDeleteBedTag?: () => void;
32
+ headerTitle: string;
33
+ initialData: BedTagData;
34
+ }
35
+
36
+ interface ErrorType {
37
+ message: string;
38
+ }
39
+
40
+ const BedTagsAdministrationForm: React.FC<BedTagAdministrationFormProps> = ({
41
+ showModal,
42
+ onModalChange,
43
+ handleCreateQuestion,
44
+ headerTitle,
45
+ initialData,
46
+ }) => {
47
+ const { t } = useTranslation();
48
+
49
+ const [showErrorNotification, setShowErrorNotification] = useState(false);
50
+ const [formStateError, setFormStateError] = useState("");
51
+
52
+ const {
53
+ handleSubmit,
54
+ control,
55
+ formState: { isDirty },
56
+ } = useForm<BedTagData>({
57
+ mode: "all",
58
+ resolver: zodResolver(BedTagAdministrationSchema),
59
+ defaultValues: {
60
+ name: initialData.name || "",
61
+ },
62
+ });
63
+
64
+ const onSubmit = (formData: BedTagData) => {
65
+ const result = BedTagAdministrationSchema.safeParse(formData);
66
+ if (result.success) {
67
+ setShowErrorNotification(false);
68
+ handleCreateQuestion(formData);
69
+ }
70
+ };
71
+
72
+ const onError = (error: { [key: string]: ErrorType }) => {
73
+ setFormStateError(Object.entries(error)[0][1].message);
74
+ setShowErrorNotification(true);
75
+ };
76
+
77
+ return (
78
+ <ComposedModal
79
+ open={showModal}
80
+ onClose={() => onModalChange(false)}
81
+ preventCloseOnClickOutside
82
+ >
83
+ <ModalHeader title={headerTitle} />
84
+ <Form onSubmit={handleSubmit(onSubmit, onError)}>
85
+ <ModalBody hasScrollingContent>
86
+ <Stack gap={3}>
87
+ <FormGroup legendText={""}>
88
+ <Controller
89
+ name="name"
90
+ control={control}
91
+ render={({ field, fieldState }) => (
92
+ <>
93
+ <TextInput
94
+ id="bedTag"
95
+ labelText={t("bedTag", "Bed Tag Name")}
96
+ placeholder={t("bedTagPlaceholder", "")}
97
+ invalidText={fieldState.error?.message}
98
+ {...field}
99
+ />
100
+ </>
101
+ )}
102
+ />
103
+ </FormGroup>
104
+
105
+ {showErrorNotification && (
106
+ <InlineNotification
107
+ lowContrast
108
+ title={t("error", "Error")}
109
+ style={{ minWidth: "100%", margin: "0rem", padding: "0rem" }}
110
+ role="alert"
111
+ kind="error"
112
+ subtitle={t("pleaseFillField", formStateError) + "."}
113
+ onClose={() => setShowErrorNotification(false)}
114
+ />
115
+ )}
116
+ </Stack>
117
+ </ModalBody>
118
+ <ModalFooter>
119
+ <Button onClick={() => onModalChange(false)} kind="secondary">
120
+ {t("cancel", "Cancel")}
121
+ </Button>
122
+ <Button disabled={!isDirty} type="submit">
123
+ <span>{t("save", "Save")}</span>
124
+ </Button>
125
+ </ModalFooter>
126
+ </Form>
127
+ </ComposedModal>
128
+ );
129
+ };
130
+
131
+ export default BedTagsAdministrationForm;
@@ -0,0 +1,80 @@
1
+ import React, { useCallback } from "react";
2
+ import { useTranslation } from "react-i18next";
3
+ import { showToast, showNotification, useConfig } from "@openmrs/esm-framework";
4
+
5
+ import { editBedTag, useBedTag } from "../../summary/summary.resource";
6
+ import { BedTagDataAdministration } from "../../bed-administration/bed-administration-types";
7
+ import BedTagsAdministrationForm from "./bed-tags-admin-form.component";
8
+ import { BedTagData, Mutator } from "../../types";
9
+
10
+ interface EditBedTagFormProps {
11
+ showModal: boolean;
12
+ onModalChange: (showModal: boolean) => void;
13
+ editData: BedTagData;
14
+ mutate: Mutator;
15
+ }
16
+
17
+ const EditBedTagForm: React.FC<EditBedTagFormProps> = ({
18
+ showModal,
19
+ onModalChange,
20
+ editData,
21
+ mutate,
22
+ }) => {
23
+ const { t } = useTranslation();
24
+
25
+ const headerTitle = t("editBed", "Edit Tag");
26
+ const { bedTypeData } = useBedTag();
27
+ const availableBedTypes = bedTypeData ? bedTypeData : [];
28
+
29
+ const handleCreateQuestion = useCallback(
30
+ (formData: BedTagDataAdministration) => {
31
+ const bedUuid = editData.uuid;
32
+ const { name } = formData;
33
+ const bedPayload = {
34
+ name,
35
+ };
36
+ editBedTag({ bedPayload, bedTagId: bedUuid })
37
+ .then(() => {
38
+ showToast({
39
+ title: t("formSaved", "Bed Tag"),
40
+ kind: "success",
41
+ critical: true,
42
+ description:
43
+ bedPayload.name +
44
+ " " +
45
+ t("saveSuccessMessage", "was saved successfully."),
46
+ });
47
+
48
+ mutate();
49
+ onModalChange(false);
50
+ })
51
+ .catch((error) => {
52
+ showNotification({
53
+ title: t("errorCreatingForm", "Error creating bed"),
54
+ kind: "error",
55
+ critical: true,
56
+ description: error?.message,
57
+ });
58
+ onModalChange(false);
59
+ });
60
+ onModalChange(false);
61
+ },
62
+ [onModalChange, mutate, editData, t]
63
+ );
64
+
65
+ return (
66
+ <>
67
+ <BedTagsAdministrationForm
68
+ onModalChange={onModalChange}
69
+ availableBedTypes={availableBedTypes}
70
+ showModal={showModal}
71
+ handleCreateQuestion={handleCreateQuestion}
72
+ headerTitle={headerTitle}
73
+ initialData={editData}
74
+ allLocations={[]}
75
+ />
76
+ </>
77
+ );
78
+ };
79
+
80
+ export default EditBedTagForm;
@@ -0,0 +1,83 @@
1
+ import React, { useCallback } from "react";
2
+ import { useTranslation } from "react-i18next";
3
+ import { showToast, showNotification, useConfig } from "@openmrs/esm-framework";
4
+ import { useBedType } from "../../bed-administration/bed-administration.resource";
5
+ import BedTagsAdministrationForm from "./bed-tags-admin-form.component";
6
+ import { saveBedTag, useLocationsByTag } from "../../summary/summary.resource";
7
+ import { BedTagData, Mutator } from "../../types";
8
+
9
+ interface BedTagFormProps {
10
+ showModal: boolean;
11
+ onModalChange: (showModal: boolean) => void;
12
+ mutate: Mutator;
13
+ }
14
+
15
+ const NewTagForm: React.FC<BedTagFormProps> = ({
16
+ showModal,
17
+ onModalChange,
18
+ mutate,
19
+ }) => {
20
+ const { t } = useTranslation();
21
+ const { admissionLocationTagUuid } = useConfig();
22
+ const { data: admissionLocations } = useLocationsByTag(
23
+ admissionLocationTagUuid
24
+ );
25
+ const headerTitle = t("addBedTag", "Create Bed Tag");
26
+ const { bedTypes } = useBedType();
27
+ const availableBedTypes = bedTypes ? bedTypes : [];
28
+
29
+ const initialData: BedTagData = {
30
+ uuid: "",
31
+ name: "",
32
+ };
33
+
34
+ const handleCreateQuestion = useCallback(
35
+ (formData: BedTagData) => {
36
+ const { name } = formData;
37
+
38
+ const bedObject = {
39
+ name,
40
+ };
41
+
42
+ saveBedTag({ bedPayload: bedObject })
43
+ .then(() => {
44
+ showToast({
45
+ title: t("formCreated", "Add Bed Tag"),
46
+ kind: "success",
47
+ critical: true,
48
+ description: `Tag ${name} was created successfully.`,
49
+ });
50
+
51
+ mutate();
52
+ onModalChange(false);
53
+ })
54
+ .catch((error) => {
55
+ showNotification({
56
+ title: t("errorCreatingForm", "Error creating bed"),
57
+ kind: "error",
58
+ critical: true,
59
+ description: error?.message,
60
+ });
61
+ onModalChange(false);
62
+ });
63
+ onModalChange(false);
64
+ },
65
+ [onModalChange, mutate, t]
66
+ );
67
+
68
+ return (
69
+ <>
70
+ <BedTagsAdministrationForm
71
+ onModalChange={onModalChange}
72
+ allLocations={admissionLocations}
73
+ availableBedTypes={availableBedTypes}
74
+ showModal={showModal}
75
+ handleCreateQuestion={handleCreateQuestion}
76
+ headerTitle={headerTitle}
77
+ initialData={initialData}
78
+ />
79
+ </>
80
+ );
81
+ };
82
+
83
+ export default NewTagForm;
@@ -0,0 +1,173 @@
1
+ import React, { useState } from "react";
2
+ import { z } from "zod";
3
+ import { useForm, Controller } from "react-hook-form";
4
+ import { zodResolver } from "@hookform/resolvers/zod";
5
+ import {
6
+ Button,
7
+ ComposedModal,
8
+ Form,
9
+ FormGroup,
10
+ ModalBody,
11
+ ModalFooter,
12
+ ModalHeader,
13
+ Stack,
14
+ TextArea,
15
+ TextInput,
16
+ InlineNotification,
17
+ } from "@carbon/react";
18
+ import { useTranslation } from "react-i18next";
19
+ import { Location } from "@openmrs/esm-framework";
20
+ import type { BedType, BedTypeData } from "../../types";
21
+
22
+ const BedTypeAdministrationSchema = z.object({
23
+ name: z.string().max(255),
24
+ displayName: z.string().max(255),
25
+ description: z.string().max(255),
26
+ });
27
+
28
+ interface BedAdministrationFormProps {
29
+ showModal: boolean;
30
+ onModalChange: (showModal: boolean) => void;
31
+ availableBedTypes: Array<BedType>;
32
+ allLocations: Location[];
33
+ handleCreateQuestion?: (formData: BedTypeData) => void;
34
+ headerTitle: string;
35
+ initialData: BedTypeData;
36
+ }
37
+
38
+ interface ErrorType {
39
+ message: string;
40
+ }
41
+
42
+ const BedTypeAdministrationForm: React.FC<BedAdministrationFormProps> = ({
43
+ showModal,
44
+ onModalChange,
45
+ handleCreateQuestion,
46
+ headerTitle,
47
+ initialData,
48
+ }) => {
49
+ const { t } = useTranslation();
50
+
51
+ const [showErrorNotification, setShowErrorNotification] = useState(false);
52
+ const [formStateError, setFormStateError] = useState("");
53
+
54
+ const {
55
+ handleSubmit,
56
+ control,
57
+ formState: { isDirty },
58
+ } = useForm<BedTypeData>({
59
+ mode: "all",
60
+ resolver: zodResolver(BedTypeAdministrationSchema),
61
+ defaultValues: {
62
+ name: initialData.name || "",
63
+ displayName: initialData.displayName || "",
64
+ description: initialData.description || "",
65
+ },
66
+ });
67
+
68
+ const onSubmit = (formData: BedTypeData) => {
69
+ const result = BedTypeAdministrationSchema.safeParse(formData);
70
+ if (result.success) {
71
+ setShowErrorNotification(false);
72
+ handleCreateQuestion(formData);
73
+ }
74
+ };
75
+
76
+ const onError = (error: { [key: string]: ErrorType }) => {
77
+ setFormStateError(Object.entries(error)[0][1].message);
78
+ setShowErrorNotification(true);
79
+ };
80
+
81
+ return (
82
+ <ComposedModal
83
+ open={showModal}
84
+ onClose={() => onModalChange(false)}
85
+ preventCloseOnClickOutside
86
+ >
87
+ <ModalHeader title={headerTitle} />
88
+ <Form onSubmit={handleSubmit(onSubmit, onError)}>
89
+ <ModalBody hasScrollingContent>
90
+ <Stack gap={3}>
91
+ <FormGroup legendText={""}>
92
+ <Controller
93
+ name="name"
94
+ control={control}
95
+ render={({ field, fieldState }) => (
96
+ <>
97
+ <TextInput
98
+ id="bedName"
99
+ labelText={t("bedName", "Bed Name")}
100
+ placeholder={t("bedTypePlaceholder", "")}
101
+ invalidText={fieldState.error?.message}
102
+ {...field}
103
+ />
104
+ </>
105
+ )}
106
+ />
107
+ </FormGroup>
108
+ <FormGroup legendText={""}>
109
+ <Controller
110
+ name="displayName"
111
+ control={control}
112
+ render={({ field, fieldState }) => (
113
+ <>
114
+ <TextInput
115
+ id="displayName"
116
+ labelText={t("displayName", "Display Name")}
117
+ placeholder={t("displayNamePlaceholder", "")}
118
+ invalidText={fieldState.error?.message}
119
+ {...field}
120
+ />
121
+ </>
122
+ )}
123
+ />
124
+ </FormGroup>
125
+ <FormGroup>
126
+ <Controller
127
+ name="description"
128
+ control={control}
129
+ render={({ field, fieldState }) => (
130
+ <>
131
+ <TextArea
132
+ rows={2}
133
+ id="description"
134
+ invalidText={fieldState?.error?.message}
135
+ labelText={t("description", "Description")}
136
+ {...field}
137
+ placeholder={t(
138
+ "description",
139
+ "Enter the bed description"
140
+ )}
141
+ />
142
+ </>
143
+ )}
144
+ />
145
+ </FormGroup>
146
+
147
+ {showErrorNotification && (
148
+ <InlineNotification
149
+ lowContrast
150
+ title={t("error", "Error")}
151
+ style={{ minWidth: "100%", margin: "0rem", padding: "0rem" }}
152
+ role="alert"
153
+ kind="error"
154
+ subtitle={t("pleaseFillField", formStateError) + "."}
155
+ onClose={() => setShowErrorNotification(false)}
156
+ />
157
+ )}
158
+ </Stack>
159
+ </ModalBody>
160
+ <ModalFooter>
161
+ <Button onClick={() => onModalChange(false)} kind="secondary">
162
+ {t("cancel", "Cancel")}
163
+ </Button>
164
+ <Button disabled={!isDirty} type="submit">
165
+ <span>{t("save", "Save")}</span>
166
+ </Button>
167
+ </ModalFooter>
168
+ </Form>
169
+ </ComposedModal>
170
+ );
171
+ };
172
+
173
+ export default BedTypeAdministrationForm;
@@ -0,0 +1,222 @@
1
+ import React, { useEffect, useMemo, useState } from "react";
2
+ import { useTranslation } from "react-i18next";
3
+ import {
4
+ Button,
5
+ DataTable,
6
+ DataTableSkeleton,
7
+ InlineLoading,
8
+ Pagination,
9
+ Table,
10
+ TableBody,
11
+ TableCell,
12
+ TableContainer,
13
+ TableHead,
14
+ TableHeader,
15
+ TableRow,
16
+ Tile,
17
+ } from "@carbon/react";
18
+ import { Add, Edit } from "@carbon/react/icons";
19
+ import {
20
+ isDesktop as desktopLayout,
21
+ useConfig,
22
+ useLayoutType,
23
+ } from "@openmrs/esm-framework";
24
+ import { CardHeader, ErrorState } from "@openmrs/esm-patient-common-lib";
25
+ import type { BedTypeData } from "../../types";
26
+ import { useBedType } from "../../summary/summary.resource";
27
+ import Header from "../../header/header.component";
28
+ import BedTypeForm from "./new-bed-type-form.component";
29
+ import styles from "../../bed-administration/bed-administration-table.scss";
30
+ import EditBedTypeForm from "./edit-bed-type.component";
31
+
32
+ const BedTypeAdministrationTable: React.FC = () => {
33
+ const { t } = useTranslation();
34
+ const headerTitle = t("bedType", "Bed Type");
35
+ const layout = useLayoutType();
36
+ const isTablet = layout === "tablet";
37
+ const responsiveSize = isTablet ? "lg" : "sm";
38
+ const isDesktop = desktopLayout(layout);
39
+ const [showEditBedModal, setShowEditBedModal] = useState(false);
40
+ const [isBedDataLoading, setIsBedDataLoading] = useState(false);
41
+ const [showBedTypeModal, setAddBedTypeModal] = useState(false);
42
+ const [currentPage, setCurrentPage] = useState(1);
43
+ const [editData, setEditData] = useState<BedTypeData>();
44
+ const [pageSize] = useState(10);
45
+ const { bedTypeData, isError, loading, validate, mutate } = useBedType();
46
+ const [currentPageSize, setPageSize] = useState(10);
47
+ const pageSizes = [10, 20, 30, 40, 50];
48
+ const tableHeaders = [
49
+ {
50
+ header: t("name", "Name"),
51
+ key: "name",
52
+ },
53
+ {
54
+ header: t("displayName", "Display Name"),
55
+ key: "displayName",
56
+ },
57
+ {
58
+ header: t("description", "Description"),
59
+ key: "description",
60
+ },
61
+ {
62
+ key: "actions",
63
+ header: t("actions", "Actions"),
64
+ },
65
+ ];
66
+
67
+ const tableRows = useMemo(() => {
68
+ return bedTypeData?.map((entry) => ({
69
+ id: entry.uuid,
70
+ name: entry?.name,
71
+ displayName: entry?.displayName,
72
+ description: entry?.description,
73
+ actions: (
74
+ <>
75
+ <Button
76
+ enterDelayMs={300}
77
+ renderIcon={Edit}
78
+ onClick={(e) => {
79
+ e.preventDefault();
80
+ setEditData(entry);
81
+ setShowEditBedModal(true);
82
+ setAddBedTypeModal(false);
83
+ }}
84
+ kind={"ghost"}
85
+ iconDescription={t("editBedType", "Edit Bed Type")}
86
+ hasIconOnly
87
+ size={responsiveSize}
88
+ tooltipAlignment="start"
89
+ />
90
+ </>
91
+ ),
92
+ }));
93
+ }, [responsiveSize, bedTypeData, t]);
94
+
95
+ if (isBedDataLoading || loading) {
96
+ return (
97
+ <>
98
+ <Header route="Bed Type" />
99
+ <div className={styles.widgetCard}>
100
+ <DataTableSkeleton role="progressbar" compact={isDesktop} zebra />
101
+ </div>
102
+ </>
103
+ );
104
+ }
105
+
106
+ if (isError) {
107
+ return (
108
+ <>
109
+ <Header route="Bed Type" />
110
+ <div className={styles.widgetCard}>
111
+ <ErrorState error={isError} headerTitle={headerTitle} />
112
+ </div>
113
+ </>
114
+ );
115
+ }
116
+
117
+ return (
118
+ <>
119
+ <Header route="Bed Type" />
120
+
121
+ <div className={styles.widgetCard}>
122
+ {showBedTypeModal ? (
123
+ <BedTypeForm
124
+ onModalChange={setAddBedTypeModal}
125
+ showModal={showBedTypeModal}
126
+ mutate={mutate}
127
+ />
128
+ ) : null}
129
+ {showEditBedModal ? (
130
+ <EditBedTypeForm
131
+ onModalChange={setShowEditBedModal}
132
+ showModal={showEditBedModal}
133
+ editData={editData}
134
+ mutate={mutate}
135
+ />
136
+ ) : null}
137
+ <CardHeader title={headerTitle}>
138
+ <span className={styles.backgroundDataFetchingIndicator}>
139
+ <span>{validate ? <InlineLoading /> : null}</span>
140
+ </span>
141
+ {bedTypeData?.length ? (
142
+ <Button
143
+ kind="ghost"
144
+ renderIcon={(props) => <Add size={16} {...props} />}
145
+ onClick={() => setAddBedTypeModal(true)}
146
+ >
147
+ {t("addBedtype", "Add Bed Type")}
148
+ </Button>
149
+ ) : null}
150
+ </CardHeader>
151
+ <DataTable
152
+ rows={tableRows}
153
+ headers={tableHeaders}
154
+ isSortable
155
+ size={isTablet ? "lg" : "sm"}
156
+ useZebraStyles
157
+ >
158
+ {({ rows, headers, getTableProps }) => (
159
+ <TableContainer>
160
+ <Table {...getTableProps()}>
161
+ <TableHead>
162
+ <TableRow>
163
+ {headers.map((header) => (
164
+ <TableHeader>
165
+ {header.header?.content ?? header.header}
166
+ </TableHeader>
167
+ ))}
168
+ </TableRow>
169
+ </TableHead>
170
+ <TableBody>
171
+ {rows.map((row) => (
172
+ <TableRow key={row.id}>
173
+ {row.cells.map((cell) => (
174
+ <TableCell key={cell.id}>
175
+ {cell.value?.content ?? cell.value}
176
+ </TableCell>
177
+ ))}
178
+ </TableRow>
179
+ ))}
180
+ </TableBody>
181
+ </Table>
182
+ {rows.length === 0 ? (
183
+ <div className={styles.tileContainer}>
184
+ <Tile className={styles.tile}>
185
+ <div className={styles.tileContent}>
186
+ <p className={styles.content}>
187
+ {t("No data", "No data to display")}
188
+ </p>
189
+ <p className={styles.helper}>
190
+ {t("checkFilters", "Check the filters above")}
191
+ </p>
192
+ </div>
193
+ <p className={styles.separator}>{t("or", "or")}</p>
194
+ <Button
195
+ kind="ghost"
196
+ size="sm"
197
+ renderIcon={(props) => <Add size={16} {...props} />}
198
+ onClick={() => setAddBedTypeModal(true)}
199
+ >
200
+ {t("bedType", "Add Bed Type")}
201
+ </Button>
202
+ </Tile>
203
+ </div>
204
+ ) : null}
205
+ <Pagination
206
+ page={currentPage}
207
+ pageSize={pageSize}
208
+ pageSizes={[10, 20, 30, 40, 50]}
209
+ totalItems={bedTypeData.length}
210
+ onChange={({ page, pageSize }) => {
211
+ setCurrentPage(page);
212
+ setPageSize(pageSize);
213
+ }}
214
+ />
215
+ </TableContainer>
216
+ )}
217
+ </DataTable>
218
+ </div>
219
+ </>
220
+ );
221
+ };
222
+ export default BedTypeAdministrationTable;