diff --git a/cypress/e2e/facility_spec/locations.cy.ts b/cypress/e2e/facility_spec/locations.cy.ts index f8006b126d4..59651c7c7c9 100644 --- a/cypress/e2e/facility_spec/locations.cy.ts +++ b/cypress/e2e/facility_spec/locations.cy.ts @@ -24,6 +24,8 @@ describe("Location Management Section", () => { cy.contains("Add New Location").click(); cy.get("[name='name']").type("Test Location"); cy.get("textarea[name='description']").type("Test Description"); + cy.get("#location-type").click(); + cy.get("#location-type-option-ICU").click(); cy.intercept(/\/api\/v1\/facility\/[\w-]+\/asset_location\//).as( "addLocation" ); diff --git a/src/Components/Assets/AssetTypes.tsx b/src/Components/Assets/AssetTypes.tsx index a894c87dcc5..041d3d0a81e 100644 --- a/src/Components/Assets/AssetTypes.tsx +++ b/src/Components/Assets/AssetTypes.tsx @@ -2,12 +2,19 @@ import { BedModel } from "../Facility/models"; import { PerformedByModel } from "../HCX/misc"; import { PatientModel } from "../Patient/models"; +export enum AssetLocationType { + OTHER = "OTHER", + WARD = "WARD", + ICU = "ICU", +} + export interface AssetLocationObject { id: string; name: string; description: string; created_date?: string; modified_date?: string; + location_type: AssetLocationType; middleware_address?: string; facility: { id: string; diff --git a/src/Components/Facility/AddLocationForm.tsx b/src/Components/Facility/AddLocationForm.tsx index e71b68cc95c..81d9bc0750c 100644 --- a/src/Components/Facility/AddLocationForm.tsx +++ b/src/Components/Facility/AddLocationForm.tsx @@ -12,6 +12,8 @@ import { Submit, Cancel } from "../Common/components/ButtonV2"; import TextFormField from "../Form/FormFields/TextFormField"; import TextAreaFormField from "../Form/FormFields/TextAreaFormField"; import Page from "../Common/components/Page"; +import { SelectFormField } from "../Form/FormFields/SelectFormField"; +import { AssetLocationType } from "../Assets/AssetTypes"; const Loading = lazy(() => import("../Common/Loading")); @@ -29,10 +31,12 @@ export const AddLocationForm = (props: LocationFormProps) => { const [description, setDescription] = useState(""); const [facilityName, setFacilityName] = useState(""); const [locationName, setLocationName] = useState(""); + const [locationType, setLocationType] = useState(""); const [errors, setErrors] = useState({ name: "", description: "", middlewareAddress: "", + locationType: "", }); const headerText = !locationId ? "Add Location" : "Update Location"; const buttonText = !locationId ? "Add Location" : "Update Location"; @@ -53,6 +57,7 @@ export const AddLocationForm = (props: LocationFormProps) => { setName(res?.data?.name || ""); setLocationName(res?.data?.name || ""); setDescription(res?.data?.description || ""); + setLocationType(res?.data?.location_type || ""); setMiddlewareAddress(res?.data?.middleware_address || ""); } setIsLoading(false); @@ -66,6 +71,7 @@ export const AddLocationForm = (props: LocationFormProps) => { name: "", description: "", middlewareAddress: "", + locationType: "", }; if (name.trim().length === 0) { @@ -73,6 +79,11 @@ export const AddLocationForm = (props: LocationFormProps) => { formValid = false; } + if (locationType.trim().length === 0) { + error.locationType = "Location Type is required"; + formValid = false; + } + if ( middlewareAddress && middlewareAddress.match( @@ -98,6 +109,7 @@ export const AddLocationForm = (props: LocationFormProps) => { name, description, middleware_address: middlewareAddress, + location_type: locationType, }; const res = await dispatchAction( @@ -172,6 +184,27 @@ export const AddLocationForm = (props: LocationFormProps) => { error={errors.description} /> +
+ title} + optionValue={({ value }) => value} + value={locationType} + required + onChange={({ value }) => setLocationType(value)} + error={errors.locationType} + /> +
{ ? formatDate( props.consultationData.discharge_date ) - : "--/--/----"} + : "--/--/---- --:-- --"}
@@ -294,10 +294,10 @@ export const ConsultationUpdatesTab = (props: ConsultationTabProps) => { Discharge Date {" - "} {props.consultationData.discharge_date - ? formatDate( + ? formatDateTime( props.consultationData.discharge_date ) - : "--/--/----"} + : "--/--/---- --:-- --"}
diff --git a/src/Components/Facility/ConsultationForm.tsx b/src/Components/Facility/ConsultationForm.tsx index 1d4abbedc39..3207787a27d 100644 --- a/src/Components/Facility/ConsultationForm.tsx +++ b/src/Components/Facility/ConsultationForm.tsx @@ -400,7 +400,9 @@ export const ConsultationForm = (props: any) => { cause_of_death: res.data?.discharge_notes || "", death_datetime: res.data?.death_datetime || "", death_confirmed_doctor: res.data?.death_confirmed_doctor || "", - InvestigationAdvice: res.data.investigation, + InvestigationAdvice: Array.isArray(res.data.investigation) + ? res.data.investigation + : [], diagnoses: res.data.diagnoses.sort( (a: ConsultationDiagnosis, b: ConsultationDiagnosis) => ConditionVerificationStatuses.indexOf(a.verification_status) - @@ -410,7 +412,7 @@ export const ConsultationForm = (props: any) => { dispatch({ type: "set_form", form: { ...state.form, ...formData } }); setBed(formData.bed); - if (res.data.last_daily_round) { + if (res.data.last_daily_round && state.form.category) { setDisabledFields((fields) => [...fields, "category"]); } } else { diff --git a/src/Components/Facility/FacilityCard.tsx b/src/Components/Facility/FacilityCard.tsx index 900b6b00f47..c34fed49a6e 100644 --- a/src/Components/Facility/FacilityCard.tsx +++ b/src/Components/Facility/FacilityCard.tsx @@ -160,7 +160,7 @@ export const FacilityCard = (props: { facility: any; userType: any }) => {
0.85 ? "button-danger-border bg-red-500" : "button-primary-border bg-primary-100" @@ -178,7 +178,7 @@ export const FacilityCard = (props: { facility: any; userType: any }) => { )} />{" "}
0.85 ? "text-white" : "text-gray-700" diff --git a/src/Components/Facility/FacilityUsers.tsx b/src/Components/Facility/FacilityUsers.tsx index aba12cc3833..ca2e1d0e363 100644 --- a/src/Components/Facility/FacilityUsers.tsx +++ b/src/Components/Facility/FacilityUsers.tsx @@ -3,7 +3,12 @@ import CountBlock from "../../CAREUI/display/Count"; import CareIcon from "../../CAREUI/icons/CareIcon"; import { RESULTS_PER_PAGE_LIMIT } from "../../Common/constants"; import * as Notification from "../../Utils/Notifications.js"; -import { classNames, isUserOnline, relativeTime } from "../../Utils/utils"; +import { + classNames, + isUserOnline, + relativeTime, + showUserDelete, +} from "../../Utils/utils"; import Pagination from "../Common/Pagination"; import UserDetails from "../Common/UserDetails"; import ButtonV2 from "../Common/components/ButtonV2"; @@ -16,6 +21,7 @@ import useAuthUser from "../../Common/hooks/useAuthUser"; import request from "../../Utils/request/request"; import routes from "../../Redux/api"; import useQuery from "../../Utils/request/useQuery"; +import { UserModel } from "../Users/models"; const Loading = lazy(() => import("../Common/Loading")); @@ -256,7 +262,7 @@ export default function FacilityUsers(props: any) { facilityUserData && facilityUserData.results && facilityUserData.results.length && - (userList = facilityUserData.results.map((user: any) => { + (userList = facilityUserData.results.map((user: UserModel) => { return (
) : null} - {authUser.user_type === "StateAdmin" && ( + {showUserDelete(authUser, user) && (
-
-
+
+
{patient.name} - + {formatAge(patient.age, patient.date_of_birth, true)}
diff --git a/src/Components/Users/ManageUsers.tsx b/src/Components/Users/ManageUsers.tsx index 3b469081754..750603ccf6f 100644 --- a/src/Components/Users/ManageUsers.tsx +++ b/src/Components/Users/ManageUsers.tsx @@ -15,7 +15,12 @@ import UnlinkFacilityDialog from "./UnlinkFacilityDialog"; import UserDeleteDialog from "./UserDeleteDialog"; import UserDetails from "../Common/UserDetails"; import UserFilter from "./UserFilter"; -import { classNames, isUserOnline, relativeTime } from "../../Utils/utils"; +import { + classNames, + isUserOnline, + relativeTime, + showUserDelete, +} from "../../Utils/utils"; import { navigate } from "raviger"; import useFilters from "../../Common/hooks/useFilters"; import useWindowDimensions from "../../Common/hooks/useWindowDimensions"; @@ -159,17 +164,6 @@ export default function ManageUsers() { }); }; - const showDelete = (user: any) => { - if (user.is_superuser) return true; - - if ( - USER_TYPES.indexOf(authUser.user_type) >= USER_TYPES.indexOf("StateAdmin") - ) - return user.state_object?.id === authUser.state; - - return false; - }; - let userList: any[] = []; userListData?.results && @@ -233,7 +227,7 @@ export default function ManageUsers() { aria-label="Online" > ) : null} - {showDelete(user) && ( + {showUserDelete(authUser, user) && ( { element?.scrollIntoView({ behavior: "smooth", block: "center" }); }; +export const showUserDelete = (authUser: UserModel, targetUser: UserModel) => { + // Auth user should be higher in hierarchy than target user + if ( + USER_TYPES.indexOf(authUser.user_type) <= + USER_TYPES.indexOf(targetUser.user_type) + ) + return false; + + if ( + authUser.user_type === "StateAdmin" && + targetUser.state_object?.id === authUser.state + ) + return true; + + if ( + authUser.user_type === "DistrictAdmin" && + targetUser.district_object?.id === authUser.district + ) + return true; + + return false; +}; + export const invalidateFiltersCache = () => { for (const key in localStorage) { if (key.startsWith("filters--")) {