Skip to content

Commit 969c3e0

Browse files
committed
Changing implementation
1 parent d1fc0f5 commit 969c3e0

File tree

4 files changed

+173
-185
lines changed

4 files changed

+173
-185
lines changed

src/change-location/change-location-modal.tsx

Lines changed: 109 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,21 @@
11
import React, { useCallback, useState } from "react";
22
import {
33
Button,
4-
ContentSwitcher,
4+
Dropdown,
55
Form,
6-
Hospital,
76
Layer,
87
ModalHeader,
98
ModalBody,
109
ModalFooter,
1110
Select,
1211
SelectItem,
12+
showSnackbar,
1313
Stack,
14-
Switch,
15-
TaskLocation,
1614
InlineNotification,
1715
InlineLoading,
1816
} from "@carbon/react";
1917
import {
2018
DefaultWorkspaceProps,
21-
showSnackbar,
2219
useLayoutType,
2320
useSession,
2421
} from "@openmrs/esm-framework";
@@ -27,7 +24,14 @@ import styles from "./change-location-link.scss";
2724
import { useTranslation } from "react-i18next";
2825
import { zodResolver } from "@hookform/resolvers/zod";
2926
import z from "zod";
30-
import { Provider, saveProvider, useClinicLocations, useRoomLocations } from "./change-location.resource";
27+
import {
28+
getProvider,
29+
Provider,
30+
saveProvider,
31+
useRoomLocations,
32+
} from "./change-location.resource";
33+
import { DEFAULT_LOCATION_ATTRIBUTE_TYPE_UUID, locationChangerList } from "../constants";
34+
import { LocationOption } from "../types";
3135

3236
type ChangeLocationProps = DefaultWorkspaceProps;
3337

@@ -36,21 +40,24 @@ const ChangeLocationModal: React.FC<ChangeLocationProps> = ({
3640
}) => {
3741
const { t } = useTranslation();
3842
const isTablet = useLayoutType() === "tablet";
39-
const [tabType, setTabType] = useState("Change room");
4043
const session = useSession();
44+
const sessionUser = useSession();
4145
const currentLocation = session?.sessionLocation?.uuid;
46+
const locationList = locationChangerList.map((item) => ({
47+
id: item.id,
48+
label: item.label,
49+
}));
50+
const [selectedLocationOption, setSelectedLocationOption] = useState<LocationOption | undefined>();
4251
const [isChangingRoom, setIsChangingRoom] = useState(false);
43-
const [selectedClinicRoom, setselectedClinicRoom] = useState<string | undefined>();
52+
const [selectedClinicRoom, setselectedClinicRoom] = useState<
53+
string | undefined
54+
>();
4455
const [selectedClinic, setSelectedClinic] = useState<string | undefined>();
45-
const { roomLocations, error: errorFetchingRooms } = useRoomLocations(selectedClinic);
46-
const {clinicsList, error: errorFetchingClinics} = useClinicLocations();
47-
48-
const handleTabTypeChange = ({ name }) => {
49-
setTabType(name);
50-
};
56+
const { roomLocations, error: errorFetchingRooms } =
57+
useRoomLocations(sessionUser?.sessionLocation?.uuid);
5158

5259
const changeLocationSchema = z.object({
53-
clinicRoom: z.string().optional(),
60+
clinicRoom: z.string().min(1, "Room is required"),
5461
});
5562

5663
const {
@@ -61,104 +68,99 @@ const ChangeLocationModal: React.FC<ChangeLocationProps> = ({
6168
resolver: zodResolver(changeLocationSchema),
6269
});
6370

64-
const onSubmit: SubmitHandler<any> = useCallback(
71+
const onSubmit: SubmitHandler<z.infer<typeof changeLocationSchema>> = useCallback(
6572
(data) => {
6673
setIsChangingRoom(true);
6774

68-
const newLocationUuid = data.clinicRoom ?? data.clinic;
69-
const providerUuid = session?.currentProvider?.uuid;
70-
const personUuid = session?.user?.person?.uuid;
75+
const userUuid = sessionUser?.user?.uuid;
76+
const roomUuid = data.clinicRoom;
77+
78+
if (!userUuid || !roomUuid) return;
79+
80+
getProvider(userUuid)
81+
.then((response) => {
82+
const provider = response?.data?.results?.[0];
83+
const providerUuid = provider?.uuid;
84+
85+
if (!providerUuid) throw new Error("Provider not found");
7186

72-
const payload: Provider = {
73-
uuid: providerUuid,
74-
person: { uuid: personUuid },
75-
attributes: [
76-
{
77-
attributeType: {
78-
uuid: "13a721e4-68e5-4f7a-8aee-3cbcec127179",
79-
display: "Default Location",
80-
},
81-
value: {
82-
uuid: newLocationUuid,
83-
display: roomLocations.find(loc => loc.uuid === newLocationUuid)?.display || "Selected Location"
84-
}
85-
}
86-
],
87-
};
87+
// find the existing location attribute (if any)
88+
const existingLocationAttr = provider.attributes?.find(
89+
(attr) => attr.attributeType?.uuid === DEFAULT_LOCATION_ATTRIBUTE_TYPE_UUID
90+
);
8891

89-
saveProvider(payload)
90-
.then(() => {
91-
closeWorkspace();
92-
showSnackbar({
93-
title: t("locationChanged", "Default location updated"),
94-
kind: "success",
95-
});
96-
})
97-
.catch((error) => {
98-
const errorMessage =
99-
error?.responseBody?.message || error?.message || "An unexpected error occurred";
100-
console.error("Provider update failed:", errorMessage);
101-
})
102-
.finally(() => {
103-
setIsChangingRoom(false);
104-
});
92+
// keep all other attributes
93+
const otherAttributes = provider.attributes?.filter(
94+
(attr) => attr.attributeType?.uuid !== DEFAULT_LOCATION_ATTRIBUTE_TYPE_UUID
95+
) ?? [];
96+
97+
// include the updated one with its UUID (if it exists)
98+
const updatedAttributes = [
99+
...otherAttributes,
100+
{
101+
...(existingLocationAttr?.uuid && { uuid: existingLocationAttr.uuid }),
102+
attributeType: { uuid: DEFAULT_LOCATION_ATTRIBUTE_TYPE_UUID },
103+
value: roomUuid, // ✅ plain string
104+
}
105+
];
106+
107+
108+
109+
110+
return saveProvider(providerUuid, updatedAttributes);
111+
})
112+
.then(() => {
113+
close();
114+
showSnackbar({
115+
title: t("locationChangedSuccessfully", "Location changed successfully"),
116+
kind: "success",
117+
});
118+
})
119+
.catch((error) => {
120+
const errorMessage = error?.responseBody?.message ?? error?.message;
121+
showSnackbar({
122+
title: t("locationChangeFailed", "Location change failed"),
123+
subtitle: errorMessage,
124+
kind: "error",
125+
});
126+
})
127+
.finally(() => {
128+
setIsChangingRoom(false);
129+
});
105130
},
106-
[session, closeWorkspace, t, roomLocations]
131+
[sessionUser?.user?.uuid, close, t]
107132
);
108133

109134

135+
136+
const onError = () => setIsChangingRoom(false);
137+
138+
110139
return (
111-
<Form onSubmit={handleSubmit(onSubmit)}>
140+
<Form onSubmit={handleSubmit(onSubmit, onError)}>
112141
<ModalHeader
113142
closeModal={close}
114143
title={t("changeLocation", "Change location")}
115144
/>
116145
<ModalBody>
117-
118-
<ContentSwitcher onChange={handleTabTypeChange}>
119-
<Switch name="Change room" text={t("changeRoom", "Switch room")} />
120-
<Switch name="Change clinic" text={t("changeClinic", "Switch only clinic")} />
121-
</ContentSwitcher>
122-
123146
<Stack gap={5} className={styles.languageOptionsContainer}>
124147
<ResponsiveWrapper isTablet={isTablet}>
125-
{tabType === "Change room" && (
126-
<><Controller
127-
name="clinicLocation"
128-
control={control}
129-
defaultValue=""
130-
render={({ field }) => (
131-
<Select
132-
{...field}
133-
id="clinicLocation"
134-
name="clinicLocation"
135-
labelText="Select clinic"
136-
disabled={errorFetchingClinics}
137-
invalidText={errors.root?.message}
138-
value={field.value}
139-
onChange={(e) => {
140-
const selectedValue = e.target.value;
141-
field.onChange(selectedValue);
142-
setSelectedClinic(selectedValue);
143-
}}
144-
>
145-
{!field.value && (
146-
<SelectItem
147-
value=""
148-
text={t(
149-
"selectClinic",
150-
"Choose clinic"
151-
)}
152-
/>
153-
)}
154-
155-
{clinicsList.map(({ uuid, display }) => (
156-
<SelectItem key={uuid} value={uuid} text={display} />
157-
))}
158-
</Select>
148+
<Dropdown
149+
id="location-options"
150+
titleText={t(
151+
"locationChangerOptions",
152+
"Select location change option"
159153
)}
154+
itemToString={(item) => (item ? item.label : "")}
155+
items={locationList}
156+
label="Choose option"
157+
selectedItem={selectedLocationOption}
158+
onChange={(event) =>
159+
setSelectedLocationOption(event.selectedItem)
160+
}
160161
/>
161-
<Controller
162+
{selectedLocationOption?.id === "switchRoom" && (
163+
<Controller
162164
name="clinicRoom"
163165
control={control}
164166
defaultValue={currentLocation}
@@ -168,7 +170,7 @@ const onSubmit: SubmitHandler<any> = useCallback(
168170
id="clinicRoom"
169171
name="clinicRoom"
170172
labelText="Select room to change to"
171-
disabled={!selectedClinic || errorFetchingRooms}
173+
disabled={errorFetchingRooms}
172174
invalidText={errors.locationTo?.message}
173175
value={field.value}
174176
onChange={(e) => {
@@ -180,10 +182,7 @@ const onSubmit: SubmitHandler<any> = useCallback(
180182
{!field.value && (
181183
<SelectItem
182184
value=""
183-
text={t(
184-
"selectRoom",
185-
"Choose room"
186-
)}
185+
text={t("selectRoom", "Choose room")}
187186
/>
188187
)}
189188

@@ -192,20 +191,19 @@ const onSubmit: SubmitHandler<any> = useCallback(
192191
))}
193192
</Select>
194193
)}
195-
/></>
196-
)}
197-
{tabType === "Change clinic" && (
194+
/>)}
195+
{selectedLocationOption?.id === "" && (
198196
<Controller
199-
name="clinic"
197+
name="clinicLocation"
200198
control={control}
201-
defaultValue={currentLocation}
199+
defaultValue=""
202200
render={({ field }) => (
203201
<Select
204202
{...field}
205-
id="clinic"
206-
name="clinic"
207-
labelText="Select clinic to change to"
208-
disabled={errorFetchingClinics}
203+
id="clinicLocation"
204+
name="clinicLocation"
205+
labelText="Select clinic"
206+
// disabled={errorFetchingClinics}
209207
invalidText={errors.root?.message}
210208
value={field.value}
211209
onChange={(e) => {
@@ -217,16 +215,13 @@ const onSubmit: SubmitHandler<any> = useCallback(
217215
{!field.value && (
218216
<SelectItem
219217
value=""
220-
text={t(
221-
"selectClinic",
222-
"Choose clinic"
223-
)}
218+
text={t("selectClinic", "Choose clinic")}
224219
/>
225220
)}
226221

227-
{clinicsList.map(({ uuid, display }) => (
222+
{/* {clinicsList.map(({ uuid, display }) => (
228223
<SelectItem key={uuid} value={uuid} text={display} />
229-
))}
224+
))} */}
230225
</Select>
231226
)}
232227
/>)}

0 commit comments

Comments
 (0)