Skip to content

Commit

Permalink
Merge branch 'develop' into fix#6718
Browse files Browse the repository at this point in the history
  • Loading branch information
konavivekramakrishna authored Dec 13, 2023
2 parents 8bf7278 + 0adb29d commit 7da72f4
Show file tree
Hide file tree
Showing 15 changed files with 336 additions and 34 deletions.
2 changes: 2 additions & 0 deletions cypress/e2e/facility_spec/locations.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
);
Expand Down
7 changes: 7 additions & 0 deletions src/Components/Assets/AssetTypes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
33 changes: 33 additions & 0 deletions src/Components/Facility/AddLocationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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"));

Expand All @@ -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<any>({
name: "",
description: "",
middlewareAddress: "",
locationType: "",
});
const headerText = !locationId ? "Add Location" : "Update Location";
const buttonText = !locationId ? "Add Location" : "Update Location";
Expand All @@ -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);
Expand All @@ -66,13 +71,19 @@ export const AddLocationForm = (props: LocationFormProps) => {
name: "",
description: "",
middlewareAddress: "",
locationType: "",
};

if (name.trim().length === 0) {
error.name = "Name is required";
formValid = false;
}

if (locationType.trim().length === 0) {
error.locationType = "Location Type is required";
formValid = false;
}

if (
middlewareAddress &&
middlewareAddress.match(
Expand All @@ -98,6 +109,7 @@ export const AddLocationForm = (props: LocationFormProps) => {
name,
description,
middleware_address: middlewareAddress,
location_type: locationType,
};

const res = await dispatchAction(
Expand Down Expand Up @@ -172,6 +184,27 @@ export const AddLocationForm = (props: LocationFormProps) => {
error={errors.description}
/>
</div>
<div>
<SelectFormField
id="location-type"
name="location_type"
label="Location Type"
options={[
{ title: "ICU", value: AssetLocationType.ICU },
{
title: "WARD",
value: AssetLocationType.WARD,
},
{ title: "OTHER", value: AssetLocationType.OTHER },
]}
optionLabel={({ title }) => title}
optionValue={({ value }) => value}
value={locationType}
required
onChange={({ value }) => setLocationType(value)}
error={errors.locationType}
/>
</div>
<div>
<TextFormField
name="Location Middleware Address"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ export const ConsultationUpdatesTab = (props: ConsultationTabProps) => {
? formatDate(
props.consultationData.discharge_date
)
: "--/--/----"}
: "--/--/---- --:-- --"}
</span>
</div>
<div>
Expand Down Expand Up @@ -294,10 +294,10 @@ export const ConsultationUpdatesTab = (props: ConsultationTabProps) => {
Discharge Date {" - "}
<span className="font-semibold">
{props.consultationData.discharge_date
? formatDate(
? formatDateTime(
props.consultationData.discharge_date
)
: "--/--/----"}
: "--/--/---- --:-- --"}
</span>
</div>
<div>
Expand Down
6 changes: 4 additions & 2 deletions src/Components/Facility/ConsultationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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) -
Expand All @@ -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 {
Expand Down
174 changes: 174 additions & 0 deletions src/Components/Facility/Consultations/Mews.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import { DailyRoundsModel } from "../../Patient/models";
import RecordMeta from "../../../CAREUI/display/RecordMeta";
import { classNames } from "../../../Utils/utils";

const getRespScore = (value?: number) => {
if (typeof value !== "number") return;

if (value < 8) return 2;
if (value <= 8) return 1;
if (value <= 17) return 0;
if (value <= 20) return 1;
if (value <= 29) return 2;
return 3;
};

const getHeartRateScore = (value?: number) => {
if (typeof value !== "number") return;

if (value < 40) return 2;
if (value <= 50) return 1;
if (value <= 100) return 0;
if (value <= 110) return 1;
if (value <= 129) return 2;
return 3;
};

const getSystolicBPScore = (value?: number) => {
if (typeof value !== "number") return;

if (value <= 70) return 3;
if (value <= 80) return 2;
if (value <= 100) return 1;
if (value <= 159) return 0;
if (value <= 199) return 1;
if (value <= 220) return 2;
return 3;
};

const getTempRange = (value?: number) => {
console.log(value);
if (typeof value !== "number") return;

if (value < 95) return 2;
if (value <= 96.8) return 1;
if (value <= 100.4) return 0;
if (value <= 101.3) return 1;
return 2;
};

const getLOCRange = (value?: DailyRoundsModel["consciousness_level"]) => {
if (!value) return;

return {
UNRESPONSIVE: 3,
RESPONDS_TO_PAIN: 2,
RESPONDS_TO_VOICE: 1,
ALERT: 0,
AGITATED_OR_CONFUSED: 1,
ONSET_OF_AGITATION_AND_CONFUSION: 2,
UNKNOWN: undefined,
}[value];
};

export const Mews = ({ dailyRound }: { dailyRound: DailyRoundsModel }) => {
const mewsCard = (isMissing: boolean, data: string[] | number) => {
if (isMissing) {
return (
<>
<div className="tooltip mt-2 text-gray-800">
<p className="my-auto text-center text-2xl font-bold">N/A</p>
<div className="tooltip-text tooltip-bottom w-48 -translate-x-1/2 translate-y-3 whitespace-pre-wrap text-xs font-medium lg:w-64">
<span className="font-bold">{(data as string[]).join(", ")}</span>{" "}
data is missing from the last log update.
</div>
</div>
<div>
<RecordMeta
time={dailyRound.modified_date}
prefix={"Updated"}
className="mx-auto mt-2 w-10/12 text-xs font-medium leading-none text-gray-800"
inlineClassName="flex flex-wrap items-center justify-center"
/>
<div className="mt-1 flex h-2 w-full flex-col items-center justify-center rounded-b-lg bg-gray-500"></div>
</div>
</>
);
} else {
const value = Number(data);
return (
<>
<div className="tooltip mt-2">
<p className="my-auto text-center text-2xl font-bold">{data}</p>
<div className="tooltip-text tooltip-bottom w-48 -translate-x-1/2 translate-y-3 whitespace-pre-wrap text-xs font-medium lg:w-64">
<p>
Resp. Rate: <span className="font-bold">{dailyRound.resp}</span>
</p>
<p>
Heart Rate:{" "}
<span className="font-bold">{dailyRound.pulse}</span>
</p>
<p>
Systolic BP:{" "}
<span className="font-bold">{dailyRound.bp?.systolic}</span>
</p>
<p>
Temperature:{" "}
<span className="font-bold">{dailyRound.temperature}</span>
</p>
<p>
Consciousness:{" "}
<span className="font-bold capitalize">
{dailyRound.consciousness_level
?.replaceAll("_", " ")
.toLowerCase()}
</span>
</p>
</div>
</div>
<div>
<RecordMeta
time={dailyRound.modified_date}
prefix={"Updated"}
className="mx-auto mt-2 w-10/12 text-xs font-medium leading-none text-gray-800"
inlineClassName="flex flex-wrap items-center justify-center"
/>
<div
className={classNames(
"mt-1 flex h-2 w-full flex-col items-center justify-center rounded-b-lg",
value <= 2 && "bg-primary-500",
value <= 3 && "bg-yellow-300",
value <= 5 && "bg-warning-600",
value > 6 && "bg-danger-500"
)}
></div>
</div>
</>
);
}
};

const scores = {
"Respiratory rate": getRespScore(dailyRound.resp),
"Heart rate": getHeartRateScore(dailyRound.pulse),
"Systolic BP": getSystolicBPScore(dailyRound.bp?.systolic),
Temperature: getTempRange(
dailyRound.temperature ? parseFloat(dailyRound.temperature) : undefined
),
"Level of Consciousness": getLOCRange(dailyRound.consciousness_level),
};

if (Object.values(scores).some((value) => value === undefined)) {
return (
<div className="flex h-fit flex-col justify-start rounded-lg border border-black">
<p className="pt-1 text-center font-bold text-gray-900">MEWS Score</p>
{mewsCard(
true,
Object.entries(scores)
.filter(([_, value]) => value === undefined)
.map(([key]) => key)
)}
</div>
);
}

return (
<div className="flex h-fit flex-col justify-start rounded-lg border border-black">
<p className="pt-1 text-center font-bold text-gray-900">MEWS Score</p>
{mewsCard(
false,
Object.values(scores as Record<string, number>).reduce((p, v) => p + v)
)}
</div>
);
};
4 changes: 2 additions & 2 deletions src/Components/Facility/FacilityCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export const FacilityCard = (props: { facility: any; userType: any }) => {
<div className="flex w-full flex-wrap justify-between gap-2 py-2">
<div className="flex flex-wrap gap-2">
<div
className={`tooltip ml-auto flex h-[38px] w-fit items-center justify-center rounded-md px-2 text-xl ${
className={`tooltip button-size-default ml-auto flex w-fit items-center justify-center rounded-md px-2 ${
facility.patient_count / facility.bed_count > 0.85
? "button-danger-border bg-red-500"
: "button-primary-border bg-primary-100"
Expand All @@ -178,7 +178,7 @@ export const FacilityCard = (props: { facility: any; userType: any }) => {
)}
/>{" "}
<dt
className={`my-1 text-sm font-semibold ${
className={`text-sm font-semibold ${
facility.patient_count / facility.bed_count > 0.85
? "text-white"
: "text-gray-700"
Expand Down
12 changes: 9 additions & 3 deletions src/Components/Facility/FacilityUsers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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"));

Expand Down Expand Up @@ -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 (
<div
key={`usr_${user.id}`}
Expand Down Expand Up @@ -299,7 +305,7 @@ export default function FacilityUsers(props: any) {
aria-label="Online"
></i>
) : null}
{authUser.user_type === "StateAdmin" && (
{showUserDelete(authUser, user) && (
<button
type="button"
className="focus:ring-blue m-3 w-20 self-end rounded-md border border-red-500 bg-white px-3 py-2 text-center text-sm font-medium leading-4 text-red-700 transition duration-150 ease-in-out hover:text-red-500 hover:shadow focus:border-red-300 focus:outline-none active:bg-gray-50 active:text-red-800"
Expand Down
Loading

0 comments on commit 7da72f4

Please sign in to comment.