From a097fb62b418f374d828698c124db1b7598eae16 Mon Sep 17 00:00:00 2001 From: Rashmik <146672184+rash-27@users.noreply.github.com> Date: Wed, 28 Feb 2024 09:43:24 +0530 Subject: [PATCH 1/6] Fix Translations in login page (#7264) * Fix Translations in login page * remove console logs --------- Co-authored-by: Rithvik Nishad --- src/CAREUI/interactive/LegendInput.tsx | 10 +++++----- src/Components/Auth/Login.tsx | 10 ++++++---- src/Components/Common/LanguageSelectorLogin.tsx | 5 ++--- src/Locale/en/Auth.json | 1 + src/Locale/kn/Auth.json | 2 ++ src/Locale/ml/Auth.json | 2 ++ src/Locale/mr/Auth.json | 2 ++ src/Locale/ta/Auth.json | 2 ++ src/Providers/HistoryAPIProvider.tsx | 1 - 9 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/CAREUI/interactive/LegendInput.tsx b/src/CAREUI/interactive/LegendInput.tsx index eabff046353..789412d7635 100644 --- a/src/CAREUI/interactive/LegendInput.tsx +++ b/src/CAREUI/interactive/LegendInput.tsx @@ -1,7 +1,7 @@ import CareIcon from "../icons/CareIcon"; import { classNames } from "../../Utils/utils"; import { RefObject, useRef, useState, useEffect } from "react"; - +import { useTranslation } from "react-i18next"; type InputProps = { id?: string; name: string; @@ -19,7 +19,7 @@ type InputProps = { onKeyDown?: (e: any) => void; onKeyPress?: (e: any) => void; disabled?: boolean; - error?: boolean; + error?: string; className?: string; outerClassName?: string; size?: "small" | "medium" | "large"; @@ -30,6 +30,7 @@ export default function LegendInput(props: InputProps) { /** * Useful for small input forms. Should only be used in special cases. */ + const { t } = useTranslation(); const [showPassword, setShowPassword] = useState(false); const inputRef = useRef(null); const ref = props.ref || inputRef; @@ -66,7 +67,6 @@ export default function LegendInput(props: InputProps) { useEffect(() => { ref.current && testAutoFill(ref.current); }, [ref.current]); - return (
{props.label && ( @@ -149,8 +149,8 @@ export default function LegendInput(props: InputProps) { )}
- {props.error && ( -
{props.error}
+ {!!props.error && ( +
{t(props.error)}
)} ); diff --git a/src/Components/Auth/Login.tsx b/src/Components/Auth/Login.tsx index 62c9d632769..9e2e4f6686a 100644 --- a/src/Components/Auth/Login.tsx +++ b/src/Components/Auth/Login.tsx @@ -68,18 +68,19 @@ export const Login = (props: { forgot?: boolean }) => { ) { if (!form[key].match(/\w/)) { hasError = true; - err[key] = t("field_required"); + err[key] = "field_required"; } } if (!form[key]) { hasError = true; - err[key] = t("field_required"); + err[key] = "field_required"; } }); if (hasError) { setErrors(err); return false; } + return form; }; @@ -92,6 +93,7 @@ export const Login = (props: { forgot?: boolean }) => { const handleSubmit = async (e: any) => { e.preventDefault(); + setLoading(true); FiltersCache.invaldiateAll(); const validated = validateData(); @@ -111,12 +113,12 @@ export const Login = (props: { forgot?: boolean }) => { if (typeof form.username === "string") { if (!form.username.match(/\w/)) { hasError = true; - err.username = t("field_required"); + err.username = "field_required"; } } if (!form.username) { hasError = true; - err.username = t("field_required"); + err.username = "field_required"; } if (hasError) { diff --git a/src/Components/Common/LanguageSelectorLogin.tsx b/src/Components/Common/LanguageSelectorLogin.tsx index b6fd1ffb57e..51edc8b8320 100644 --- a/src/Components/Common/LanguageSelectorLogin.tsx +++ b/src/Components/Common/LanguageSelectorLogin.tsx @@ -4,8 +4,7 @@ import { LANGUAGE_NAMES } from "../../Locale/config"; import { classNames } from "../../Utils/utils"; export const LanguageSelectorLogin = () => { - const { i18n } = useTranslation(); - + const { i18n, t } = useTranslation(); useEffect(() => { document.documentElement.setAttribute("lang", i18n.language); }, [i18n]); @@ -20,7 +19,7 @@ export const LanguageSelectorLogin = () => { return (
- Available in: + {t("available_in")}
{Object.keys(LANGUAGE_NAMES).map((e: string) => ( diff --git a/src/Locale/en/Auth.json b/src/Locale/en/Auth.json index 89ba7cea4d6..e99cae72f7f 100644 --- a/src/Locale/en/Auth.json +++ b/src/Locale/en/Auth.json @@ -29,6 +29,7 @@ "password_reset_success": "Password Reset successfully", "password_reset_failure": "Password Reset Failed", "reset_password": "Reset Password", + "available_in":"Available in", "sign_out": "Sign Out", "back_to_login": "Back to login", "min_password_len_8": "Minimum password length 8", diff --git a/src/Locale/kn/Auth.json b/src/Locale/kn/Auth.json index ff13e8e15b1..fb36b254b38 100644 --- a/src/Locale/kn/Auth.json +++ b/src/Locale/kn/Auth.json @@ -22,6 +22,8 @@ "register_page_title": "ಆಸ್ಪತ್ರೆ ನಿರ್ವಾಹಕರಾಗಿ ನೋಂದಾಯಿಸಿ", "auth_login_title": "ಅಧಿಕೃತ ಲಾಗಿನ್", "forget_password": "ಪಾಸ್ವರ್ಡ್ ಮರೆತಿರಾ?", + "back_to_login": "ಲಾಗಿನ್ ಪುಟಕ್ಕೆ ಹಿಂತಿರುಗಿ", + "available_in":"ಲಭ್ಯವಿರುವ ಭಾಷೆಗಳು", "forget_password_instruction": "ನಿಮ್ಮ ಬಳಕೆದಾರ ಹೆಸರನ್ನು ನಮೂದಿಸಿ ಮತ್ತು ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲು ನಾವು ನಿಮಗೆ ಲಿಂಕ್ ಅನ್ನು ಕಳುಹಿಸುತ್ತೇವೆ.", "send_reset_link": "ಮರುಹೊಂದಿಸುವ ಲಿಂಕ್ ಕಳುಹಿಸಿ", "already_a_member": "ಈಗಾಗಲೇ ಸದಸ್ಯರೇ?", diff --git a/src/Locale/ml/Auth.json b/src/Locale/ml/Auth.json index 15b2e179aad..199bce684ec 100644 --- a/src/Locale/ml/Auth.json +++ b/src/Locale/ml/Auth.json @@ -21,6 +21,8 @@ "register_hospital": "ആശുപത്രി രജിസ്റ്റർ ചെയ്യുക", "register_page_title": "ആശുപത്രി അഡ്മിനിസ്ട്രേറ്ററായി രജിസ്റ്റർ ചെയ്യുക", "auth_login_title": "അംഗീകൃത ലോഗിൻ", + "back_to_login": "ലോഗിൻ പേജിലേക്ക് മടങ്ങുക", + "available_in":"ലഭ്യമായ ഭാഷകൾ", "forget_password": "പാസ്‌വേഡ് മറന്നോ?", "forget_password_instruction": "നിങ്ങളുടെ യൂസർനെയിം/ഉപയോക്തൃനാമം നൽകുക. പാസ്‌വേഡ് പുന: സജ്ജമാക്കാൻ ഞങ്ങൾ ഒരു ലിങ്ക് അയയ്‌ക്കുന്നതായിരിക്കും.", "send_reset_link": "പുന: സജ്ജീകരണ ലിങ്ക് അയയ്‌ക്കുക", diff --git a/src/Locale/mr/Auth.json b/src/Locale/mr/Auth.json index c0b356dd943..2154366c4f6 100644 --- a/src/Locale/mr/Auth.json +++ b/src/Locale/mr/Auth.json @@ -21,6 +21,8 @@ "register_hospital": "हॉस्पिटलचे नाव नोंदवा", "register_page_title": "हॉस्पिटल व्यवस्थापक म्हणून नोंदणी करा", "auth_login_title": "अधिकृत लॉगिन", + "back_to_login": "लॉगिन पृष्ठावर परत या", + "available_in":"उपलब्ध भाषा", "forget_password": "पासवर्ड विसरलात?", "forget_password_instruction": "युजरनेम प्रविष्ट करा आणि आम्ही तुम्हाला पासवर्ड रीसेट करण्यासाठी एक लिंक पाठवू.", "send_reset_link": "रीसेट लिंक पाठवा", diff --git a/src/Locale/ta/Auth.json b/src/Locale/ta/Auth.json index ef5260536e7..1d5e15f241a 100644 --- a/src/Locale/ta/Auth.json +++ b/src/Locale/ta/Auth.json @@ -21,6 +21,8 @@ "register_hospital": "மருத்துவமனை பதிவு", "register_page_title": "மருத்துவமனை நிர்வாகியாக பதிவு செய்யுங்கள்", "auth_login_title": "அங்கீகரிக்கப்பட்ட உள்நுழைவு", + "back_to_login": "உள்நுழைவு பக்கத்திற்குத் திரும்பு", + "available_in":"கிடைக்கும் மொழிகள்", "forget_password": "கடவுச்சொல்லை மறந்துவிட்டீர்களா?", "forget_password_instruction": "உங்கள் பயனர்பெயரை உள்ளிடவும், உங்கள் கடவுச்சொல்லை மீட்டமைக்க ஒரு இணைப்பை நாங்கள் உங்களுக்கு அனுப்புவோம்.", "send_reset_link": "மீட்டமை இணைப்பை அனுப்பவும்", diff --git a/src/Providers/HistoryAPIProvider.tsx b/src/Providers/HistoryAPIProvider.tsx index 3fa4b6fab86..77634b1e875 100644 --- a/src/Providers/HistoryAPIProvider.tsx +++ b/src/Providers/HistoryAPIProvider.tsx @@ -26,7 +26,6 @@ export default function HistoryAPIProvider(props: { children: ReactNode }) { }, { onInitial: true } ); - const resetHistory = () => setHistory((history) => history.slice(0, 1)); return ( From bfa368116606bbe64cf7c19256c8e1d6c453d435 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Wed, 28 Feb 2024 09:43:57 +0530 Subject: [PATCH 2/6] Fixes issues with redirection on login (#7237) * Fixes redirect not working upon login fixes #6900 * Add cypress tests --- cypress/e2e/auth_spec/redirect.cy.ts | 32 +++++++++++++++++++++++++++ cypress/pageobject/Login/LoginPage.ts | 14 ++++++++++++ src/Providers/AuthUserProvider.tsx | 5 ++++- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 cypress/e2e/auth_spec/redirect.cy.ts diff --git a/cypress/e2e/auth_spec/redirect.cy.ts b/cypress/e2e/auth_spec/redirect.cy.ts new file mode 100644 index 00000000000..671a896a94f --- /dev/null +++ b/cypress/e2e/auth_spec/redirect.cy.ts @@ -0,0 +1,32 @@ +import { cy, describe, it, beforeEach, Cypress } from "local-cypress"; +import LoginPage from "../../pageobject/Login/LoginPage"; + +describe("redirect", () => { + const loginPage = new LoginPage(); + + beforeEach(() => { + cy.log("Logging in the user devdistrictadmin"); + }); + + it("Check if login redirects to the right url", () => { + cy.awaitUrl("/resource/board", true); + loginPage.loginManuallyAsDistrictAdmin(); + loginPage.ensureLoggedIn(); + cy.url().should("include", "/resource/board"); + }); + + it("Check if the redirect param works", () => { + const baseUrl = Cypress.config("baseUrl"); + cy.awaitUrl(`login?redirect=${baseUrl}/resource/board`, true); + loginPage.loginManuallyAsDistrictAdmin(); + loginPage.ensureLoggedIn(); + cy.url().should("include", "/resource/board"); + }); + + it("Check to ensure that redirect is the same origin", () => { + cy.awaitUrl("login?redirect=https://google.com", true); + loginPage.loginManuallyAsDistrictAdmin(); + loginPage.ensureLoggedIn(); + cy.url().should("include", "/facility"); + }); +}); diff --git a/cypress/pageobject/Login/LoginPage.ts b/cypress/pageobject/Login/LoginPage.ts index f4f188f11d6..94e52c33613 100644 --- a/cypress/pageobject/Login/LoginPage.ts +++ b/cypress/pageobject/Login/LoginPage.ts @@ -10,9 +10,23 @@ class LoginPage { cy.loginByApi("devdoctor", "Coronasafe@123"); } + loginAsStaff(): void { + cy.loginByApi("staffdev", "Coronasafe@123"); + } + + loginManuallyAsDistrictAdmin(): void { + cy.get("input[id='username']").type("devdistrictadmin"); + cy.get("input[id='password']").type("Coronasafe@123"); + cy.get("button").contains("Login").click(); + } + login(username: string, password: string): void { cy.loginByApi(username, password); } + + ensureLoggedIn(): void { + cy.get("p").contains("Sign Out").should("exist"); + } } export default LoginPage; diff --git a/src/Providers/AuthUserProvider.tsx b/src/Providers/AuthUserProvider.tsx index 5435b0f0b45..63da9474f2b 100644 --- a/src/Providers/AuthUserProvider.tsx +++ b/src/Providers/AuthUserProvider.tsx @@ -42,7 +42,10 @@ export default function AuthUserProvider({ children, unauthorized }: Props) { localStorage.setItem(LocalStorageKeys.refreshToken, query.data.refresh); await refetch(); - navigate(getRedirectOr("/")); + + if (location.pathname === "/" || location.pathname === "/login") { + navigate(getRedirectOr("/")); + } } return query; From b3f61460f5c1b51429e4be9246472661ebf4fc98 Mon Sep 17 00:00:00 2001 From: Kshitij Verma <101321276+kshitijv256@users.noreply.github.com> Date: Wed, 28 Feb 2024 09:44:21 +0530 Subject: [PATCH 3/6] removed unused filters from notifications (#7235) --- src/Common/constants.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Common/constants.tsx b/src/Common/constants.tsx index 1d3e8c8db40..60530cb0634 100644 --- a/src/Common/constants.tsx +++ b/src/Common/constants.tsx @@ -565,11 +565,6 @@ export const NOTIFICATION_EVENTS: NotificationEvent[] = [ text: "Patient Updated", icon: "l-edit", }, - { - id: "PATIENT_DELETED", - text: "Patient Deleted", - icon: "l-user-minus", - }, { id: "PATIENT_CONSULTATION_CREATED", text: "Patient Consultation Created", @@ -580,11 +575,6 @@ export const NOTIFICATION_EVENTS: NotificationEvent[] = [ text: "Patient Consultation Updated", icon: "l-heart-medical", }, - { - id: "PATIENT_CONSULTATION_DELETED", - text: "Patient Consultation Deleted", - icon: "l-heartbeat", - }, { id: "INVESTIGATION_SESSION_CREATED", text: "Investigation Session Created", From b38789a628e127c94b3aac3a8fb6f77afaab4089 Mon Sep 17 00:00:00 2001 From: Ashesh <3626859+Ashesh3@users.noreply.github.com> Date: Wed, 28 Feb 2024 09:45:30 +0530 Subject: [PATCH 4/6] Add Uptime tracking to Location Management (#7230) * Location Uptime tracking * Add facilityId prop to Location component * Fix card alignment --- src/Components/Assets/AssetManage.tsx | 4 +++ src/Components/Common/Uptime.tsx | 29 ++++++++++--------- .../Facility/LocationManagement.tsx | 19 +++++++++++- src/Redux/api.tsx | 2 +- 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/Components/Assets/AssetManage.tsx b/src/Components/Assets/AssetManage.tsx index b7197dd0562..661043ba697 100644 --- a/src/Components/Assets/AssetManage.tsx +++ b/src/Components/Assets/AssetManage.tsx @@ -503,6 +503,10 @@ const AssetManage = (props: AssetManageProps) => { Availability History
+ } + parentClassNames="mt-8 flex w-full flex-col bg-white p-4 shadow-sm sm:rounded-lg" /> )}
Service History
diff --git a/src/Components/Common/Uptime.tsx b/src/Components/Common/Uptime.tsx index e7272e2e1f4..4b12a13bd17 100644 --- a/src/Components/Common/Uptime.tsx +++ b/src/Components/Common/Uptime.tsx @@ -169,6 +169,9 @@ export default function Uptime( props: Readonly<{ route: QueryRoute>; params?: Record; + header?: React.ReactNode; + parentClassNames?: string; + centerInfoPanel?: boolean; }> ) { const [summary, setSummary] = useState<{ @@ -191,6 +194,8 @@ export default function Uptime( setNumDays(Math.min(newNumDays, 100)); }; + const centerInfoPanel = props.centerInfoPanel ?? false; + const setUptimeRecord = (records: AvailabilityRecord[]): void => { const recordsByDayBefore: { [key: number]: AvailabilityRecord[] } = {}; @@ -361,10 +366,10 @@ export default function Uptime( ); } else if (summary) { return ( -
-
+
+
-
Availability History
+ {props.header}
@@ -407,15 +412,13 @@ export default function Uptime( }`} >
- {hoveredDay === index && ( - <> - - + {hoveredDay === index && !centerInfoPanel && ( + )} ); @@ -432,7 +435,7 @@ export default function Uptime(
{hoveredDay !== -1 && ( -
+
import("../Common/Loading")); @@ -19,6 +20,7 @@ interface Props { } interface LocationProps extends LocationModel { + facilityId: string; setShowDeletePopup: (e: { open: boolean; name: string; id: string }) => void; } @@ -109,7 +111,11 @@ export default function LocationManagement({ facilityId }: Props) { className="my-8 grid gap-3 @4xl:grid-cols-2 @6xl:grid-cols-3 @[100rem]:grid-cols-4 lg:mx-8"> {(item) => ( - + )}
@@ -208,6 +214,7 @@ const Location = ({ modified_date, id, setShowDeletePopup, + facilityId, }: LocationProps) => (
@@ -241,6 +248,16 @@ const Location = ({ > {middleware_address || "-"}

+ + Middleware Uptime +

+ } + centerInfoPanel + />
>(), }, - getFacilityAssetLocationAvailability: { + listFacilityAssetLocationAvailability: { path: "/api/v1/facility/{facility_external_id}/asset_location/{external_id}/availability/", method: "GET", TRes: Type>(), From ab678269f76b18791edb84f9383eaecee88caa8d Mon Sep 17 00:00:00 2001 From: Devdeep Ghosh <63492939+thedevildude@users.noreply.github.com> Date: Wed, 28 Feb 2024 09:46:00 +0530 Subject: [PATCH 5/6] Introduce (i) Button Popover Component in HL7Monitor and VentilatorPatientVitalsMonitor (#7228) * created a VitalsMonitorAssetPopover component * replaced asset name with (i) button popover * replaced DialogModal with headlessUI popover * minor mobile ui fix HL7Monitor * removed redundant code * minor css fix and dynamic icon feature added * spacing fix * local fix to improper gender type * reusable header for VitalsMonitor * minor css fix * minor popover css fix * added hideHeader optional prop to VitalsMonitor * hide header from VitalsMonitor in ConsultationUpdatesTab * created and implemented VitalsMonitorFooter component * hide header and footer from VitalsMonitor asset configure --------- Co-authored-by: Rithvik Nishad --- .../Assets/AssetType/HL7Monitor.tsx | 9 ++- .../Facility/CentralNursingStation.tsx | 3 +- .../ConsultationUpdatesTab.tsx | 4 + .../VitalsMonitor/HL7PatientVitalsMonitor.tsx | 59 ++------------ .../VentilatorPatientVitalsMonitor.tsx | 66 ++-------------- .../VitalsMonitorAssetPopover.tsx | 77 +++++++++++++++++++ .../VitalsMonitor/VitalsMonitorFooter.tsx | 17 ++++ .../VitalsMonitor/VitalsMonitorHeader.tsx | 56 ++++++++++++++ src/Components/VitalsMonitor/types.ts | 2 + 9 files changed, 179 insertions(+), 114 deletions(-) create mode 100644 src/Components/VitalsMonitor/VitalsMonitorAssetPopover.tsx create mode 100644 src/Components/VitalsMonitor/VitalsMonitorFooter.tsx create mode 100644 src/Components/VitalsMonitor/VitalsMonitorHeader.tsx diff --git a/src/Components/Assets/AssetType/HL7Monitor.tsx b/src/Components/Assets/AssetType/HL7Monitor.tsx index a7be23baad8..cca0a7571b8 100644 --- a/src/Components/Assets/AssetType/HL7Monitor.tsx +++ b/src/Components/Assets/AssetType/HL7Monitor.tsx @@ -131,12 +131,19 @@ const HL7Monitor = (props: HL7MonitorProps) => { )} {assetType === "HL7MONITOR" && ( - + )} {assetType === "VENTILATOR" && ( )}
diff --git a/src/Components/Facility/CentralNursingStation.tsx b/src/Components/Facility/CentralNursingStation.tsx index 186dbbd48e9..e063292cf2f 100644 --- a/src/Components/Facility/CentralNursingStation.tsx +++ b/src/Components/Facility/CentralNursingStation.tsx @@ -207,7 +207,8 @@ export default function CentralNursingStation({ facilityId }: Props) { ?.start_date } key={`${props.patientAssetBed?.bed.id}-${hash}`} - {...props} + patientAssetBed={props.patientAssetBed} + socketUrl={props.socketUrl || ""} config={config} />
diff --git a/src/Components/Facility/ConsultationDetails/ConsultationUpdatesTab.tsx b/src/Components/Facility/ConsultationDetails/ConsultationUpdatesTab.tsx index 1ccd6e0626d..fdbf4846329 100644 --- a/src/Components/Facility/ConsultationDetails/ConsultationUpdatesTab.tsx +++ b/src/Components/Facility/ConsultationDetails/ConsultationUpdatesTab.tsx @@ -111,6 +111,7 @@ export const ConsultationUpdatesTab = (props: ConsultationTabProps) => { meta: monitorBedData?.asset_object?.meta, }} socketUrl={hl7SocketUrl} + hideHeader={true} />
@@ -122,6 +123,7 @@ export const ConsultationUpdatesTab = (props: ConsultationTabProps) => { meta: ventilatorBedData?.asset_object?.meta, }} socketUrl={ventilatorSocketUrl} + hideHeader={true} />
@@ -157,6 +159,7 @@ export const ConsultationUpdatesTab = (props: ConsultationTabProps) => { }} socketUrl={hl7SocketUrl} config={vitals.config} + hideHeader={true} />
)} @@ -173,6 +176,7 @@ export const ConsultationUpdatesTab = (props: ConsultationTabProps) => { }} socketUrl={ventilatorSocketUrl} config={vitals.config} + hideHeader={true} />
)} diff --git a/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx b/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx index d91b0c56b2f..268e6c91ffa 100644 --- a/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx +++ b/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx @@ -1,7 +1,5 @@ import { useEffect } from "react"; import useHL7VitalsMonitor from "./useHL7VitalsMonitor"; -import { Link } from "raviger"; -import { GENDER_TYPES } from "../../Common/constants"; import CareIcon from "../../CAREUI/icons/CareIcon"; import WaveformLabels from "./WaveformLabels"; import { classNames } from "../../Utils/utils"; @@ -9,6 +7,8 @@ import { IVitalsComponentProps, VitalsValueBase } from "./types"; import { triggerGoal } from "../../Integrations/Plausible"; import useAuthUser from "../../Common/hooks/useAuthUser"; import dayjs from "dayjs"; +import VitalsMonitorHeader from "./VitalsMonitorHeader"; +import VitalsMonitorFooter from "./VitalsMonitorFooter"; const minutesAgo = (timestamp: string) => { return `${dayjs().diff(dayjs(timestamp), "minute")}m ago`; @@ -18,7 +18,7 @@ export default function HL7PatientVitalsMonitor(props: IVitalsComponentProps) { const { connect, waveformCanvas, data, isOnline } = useHL7VitalsMonitor( props.config ); - const { patient, bed, asset } = props.patientAssetBed ?? {}; + const { bed, asset } = props.patientAssetBed ?? {}; const authUser = useAuthUser(); useEffect(() => { @@ -41,56 +41,8 @@ export default function HL7PatientVitalsMonitor(props: IVitalsComponentProps) { return (
- {props.patientAssetBed && ( -
-
- {patient ? ( - - {patient?.name} - - ) : ( - - - No Patient - - )} - {patient && ( - - {patient.age}y;{" "} - {GENDER_TYPES.find((g) => g.id === patient.gender)?.icon} - - )} -
-
- {asset && ( - - - {asset.name} - - )} - {bed && ( - - - - {bed.name} - - - - {bed.location_object?.name} - - - )} -
-
+ {props.hideHeader ? null : ( + )}
@@ -227,6 +179,7 @@ export default function HL7PatientVitalsMonitor(props: IVitalsComponentProps) {
+ {props.hideFooter ? null : }
); } diff --git a/src/Components/VitalsMonitor/VentilatorPatientVitalsMonitor.tsx b/src/Components/VitalsMonitor/VentilatorPatientVitalsMonitor.tsx index b03fe0645c6..ee3f471b22c 100644 --- a/src/Components/VitalsMonitor/VentilatorPatientVitalsMonitor.tsx +++ b/src/Components/VitalsMonitor/VentilatorPatientVitalsMonitor.tsx @@ -1,19 +1,18 @@ import { useEffect } from "react"; -import { Link } from "raviger"; -import { GENDER_TYPES } from "../../Common/constants"; import CareIcon from "../../CAREUI/icons/CareIcon"; import useVentilatorVitalsMonitor from "./useVentilatorVitalsMonitor"; import { IVitalsComponentProps, VitalsValueBase } from "./types"; import { classNames } from "../../Utils/utils"; import WaveformLabels from "./WaveformLabels"; import { VitalsNonWaveformContent } from "./HL7PatientVitalsMonitor"; +import VitalsMonitorHeader from "./VitalsMonitorHeader"; +import VitalsMonitorFooter from "./VitalsMonitorFooter"; export default function VentilatorPatientVitalsMonitor( props: IVitalsComponentProps ) { const { connect, waveformCanvas, data, isOnline } = useVentilatorVitalsMonitor(props.config); - const { patient, bed, asset } = props.patientAssetBed ?? {}; useEffect(() => { connect(props.socketUrl); @@ -21,62 +20,8 @@ export default function VentilatorPatientVitalsMonitor( return (
- {props.patientAssetBed && ( -
-
- {patient ? ( - - {patient?.name} - - ) : ( - - - No Patient - - )} - {patient && ( - - {patient.age}y;{" "} - {GENDER_TYPES.find((g) => g.id === patient.gender)?.icon} - - )} -
-
- {asset && ( -
- - - - {asset.name} - - -
- )} - {bed && ( -
- - - - {bed.name} - - - - {bed.location_object?.name} - - -
- )} -
-
+ {props.hideHeader ? null : ( + )}
@@ -138,6 +83,9 @@ export default function VentilatorPatientVitalsMonitor( />
+ {props.hideFooter ? null : ( + + )}
); } diff --git a/src/Components/VitalsMonitor/VitalsMonitorAssetPopover.tsx b/src/Components/VitalsMonitor/VitalsMonitorAssetPopover.tsx new file mode 100644 index 00000000000..cf56c3c5e50 --- /dev/null +++ b/src/Components/VitalsMonitor/VitalsMonitorAssetPopover.tsx @@ -0,0 +1,77 @@ +import CareIcon from "../../CAREUI/icons/CareIcon"; +import { AssetData, assetClassProps } from "../Assets/AssetTypes"; +import ButtonV2 from "../Common/components/ButtonV2"; +import { navigate } from "raviger"; +import { useTranslation } from "react-i18next"; +import { Popover, Transition } from "@headlessui/react"; +import { Fragment } from "react"; + +interface VitalsMonitorAssetPopoverProps { + asset?: AssetData; +} + +const VitalsMonitorAssetPopover = ({ + asset, +}: VitalsMonitorAssetPopoverProps) => { + const { t } = useTranslation(); + + return ( + + + + + + +
+
+ +

{asset?.name}

+
+
+

Middleware Hostname:

+

+ {asset?.resolved_middleware?.hostname} +

+
+
+

Local IP Address:

+

+ {asset?.meta?.local_ip_address} +

+
+ + navigate( + `/facility/${asset?.location_object.facility?.id}/assets/${asset?.id}/configure` + ) + } + id="configure-asset" + data-testid="asset-configure-button" + > + + {t("configure")} + +
+
+
+
+ ); +}; + +export default VitalsMonitorAssetPopover; diff --git a/src/Components/VitalsMonitor/VitalsMonitorFooter.tsx b/src/Components/VitalsMonitor/VitalsMonitorFooter.tsx new file mode 100644 index 00000000000..a9598f16965 --- /dev/null +++ b/src/Components/VitalsMonitor/VitalsMonitorFooter.tsx @@ -0,0 +1,17 @@ +import { AssetData } from "../Assets/AssetTypes"; +import VitalsMonitorAssetPopover from "./VitalsMonitorAssetPopover"; + +interface IVitalsMonitorFooterProps { + asset?: AssetData; +} + +const VitalsMonitorFooter = ({ asset }: IVitalsMonitorFooterProps) => { + return ( +
+

{asset?.name}

+ +
+ ); +}; + +export default VitalsMonitorFooter; diff --git a/src/Components/VitalsMonitor/VitalsMonitorHeader.tsx b/src/Components/VitalsMonitor/VitalsMonitorHeader.tsx new file mode 100644 index 00000000000..2f9df8607b0 --- /dev/null +++ b/src/Components/VitalsMonitor/VitalsMonitorHeader.tsx @@ -0,0 +1,56 @@ +import { PatientAssetBed } from "../Assets/AssetTypes"; +import { Link } from "raviger"; +import CareIcon from "../../CAREUI/icons/CareIcon"; +import { GENDER_TYPES } from "../../Common/constants"; + +interface VitalsMonitorHeaderProps { + patientAssetBed?: PatientAssetBed; +} + +const VitalsMonitorHeader = ({ patientAssetBed }: VitalsMonitorHeaderProps) => { + const { patient, bed } = patientAssetBed ?? {}; + return ( +
+
+ {patient ? ( + + {patient?.name} + + ) : ( + + + No Patient + + )} + {patient && ( + + {patient.age}y;{" "} + {GENDER_TYPES.find((g) => g.id === patient.gender)?.icon} + + )} +
+
+ {bed && ( + + + + {bed.name} + + + + {bed.location_object?.name} + + + )} +
+
+ ); +}; + +export default VitalsMonitorHeader; diff --git a/src/Components/VitalsMonitor/types.ts b/src/Components/VitalsMonitor/types.ts index c73d7399b59..d6812d273d6 100644 --- a/src/Components/VitalsMonitor/types.ts +++ b/src/Components/VitalsMonitor/types.ts @@ -50,4 +50,6 @@ export interface IVitalsComponentProps { patientAssetBed?: PatientAssetBed; socketUrl: string; config?: ReturnType; + hideHeader?: boolean; + hideFooter?: boolean; } From 9a53d70cf039728b75d156ce7d54b33a58876a0a Mon Sep 17 00:00:00 2001 From: Gampa Sri Harsh <114745442+sriharsh05@users.noreply.github.com> Date: Wed, 28 Feb 2024 09:46:35 +0530 Subject: [PATCH 6/6] Replace useDispatch with useQuery and request in PatientRegistration form. (#7216) * replace useDispatch with useQuery and request in PatientRegister.tsx * remove promise.all for states * replace useQuery for fetchData with request * replace complex useQuery with request --- src/Components/ExternalResult/models.ts | 3 + src/Components/Patient/PatientRegister.tsx | 473 ++++++++++----------- src/Redux/actions.tsx | 29 -- src/Redux/api.tsx | 8 + 4 files changed, 231 insertions(+), 282 deletions(-) diff --git a/src/Components/ExternalResult/models.ts b/src/Components/ExternalResult/models.ts index 7b136c76cef..bc143593019 100644 --- a/src/Components/ExternalResult/models.ts +++ b/src/Components/ExternalResult/models.ts @@ -20,6 +20,9 @@ export interface IExternalResult { sample_collection_date: string; patient_category: string; srf_id: string; + permanent_address: string; + test_id: string; + village: string; district_object: { id: number; name: string; diff --git a/src/Components/Patient/PatientRegister.tsx b/src/Components/Patient/PatientRegister.tsx index c6b260efe87..efc269fa00c 100644 --- a/src/Components/Patient/PatientRegister.tsx +++ b/src/Components/Patient/PatientRegister.tsx @@ -8,19 +8,6 @@ import { TEST_TYPE, VACCINES, } from "../../Common/constants"; -import { - HCXActions, - createPatient, - externalResult, - getAnyFacility, - getDistrictByState, - getLocalbodyByDistrict, - getPatient, - getStates, - getWardByLocalBody, - searchPatient, - updatePatient, -} from "../../Redux/actions"; import { dateQueryString, getPincodeDetails, @@ -67,10 +54,12 @@ import { debounce } from "lodash-es"; import useAppHistory from "../../Common/hooks/useAppHistory"; import useConfig from "../../Common/hooks/useConfig"; -import { useDispatch } from "react-redux"; import { validatePincode } from "../../Common/validation"; import { FormContextValue } from "../Form/FormContext.js"; import useAuthUser from "../../Common/hooks/useAuthUser.js"; +import useQuery from "../../Utils/request/useQuery.js"; +import routes from "../../Redux/api.js"; +import request from "../../Utils/request/request.js"; const Loading = lazy(() => import("../Common/Loading")); const PageTitle = lazy(() => import("../Common/PageTitle")); @@ -184,7 +173,6 @@ export const PatientRegister = (props: PatientRegisterProps) => { const authUser = useAuthUser(); const { goBack } = useAppHistory(); const { gov_data_api_key, enable_hcx, enable_abdm } = useConfig(); - const dispatchAction: any = useDispatch(); const { facilityId, id } = props; const [state, dispatch] = useReducer(patientFormReducer, initialState); const [showAlertMessage, setAlertMessage] = useState({ @@ -202,11 +190,9 @@ export const PatientRegister = (props: PatientRegisterProps) => { }); const [careExtId, setCareExtId] = useState(""); const [formField, setFormField] = useState(); - const [isStateLoading, setIsStateLoading] = useState(false); const [isDistrictLoading, setIsDistrictLoading] = useState(false); const [isLocalbodyLoading, setIsLocalbodyLoading] = useState(false); const [isWardLoading, setIsWardLoading] = useState(false); - const [states, setStates] = useState([]); const [districts, setDistricts] = useState([]); const [localBody, setLocalBody] = useState([]); const [ward, setWard] = useState([]); @@ -215,7 +201,6 @@ export const PatientRegister = (props: PatientRegisterProps) => { transfer?: boolean; patientList: Array; }>({ patientList: [] }); - const [facilityName, setFacilityName] = useState(""); const [patientName, setPatientName] = useState(""); const [{ extId }, setQuery] = useQueryParams(); const [showLinkAbhaNumberModal, setShowLinkAbhaNumberModal] = useState(false); @@ -236,50 +221,47 @@ export const PatientRegister = (props: PatientRegisterProps) => { const headerText = !id ? "Add Details of Patient" : "Update Patient Details"; const buttonText = !id ? "Add Patient" : "Save Details"; - const fetchDistricts = useCallback( - async (id: number) => { - if (id > 0) { - setIsDistrictLoading(true); - const districtList = await dispatchAction(getDistrictByState({ id })); - if (districtList) { - setDistricts(districtList.data); - } - setIsDistrictLoading(false); - return districtList ? [...districtList.data] : []; + const fetchDistricts = useCallback(async (id: number) => { + if (id > 0) { + setIsDistrictLoading(true); + const { res, data } = await request(routes.getDistrictByState, { + pathParams: { id }, + }); + if (res?.ok && data) { + setDistricts(data); } - }, - [dispatchAction] - ); + setIsDistrictLoading(false); + return data ? [...data] : []; + } + }, []); - const fetchLocalBody = useCallback( - async (id: string) => { - if (Number(id) > 0) { - setIsLocalbodyLoading(true); - const localBodyList = await dispatchAction( - getLocalbodyByDistrict({ id }) - ); - setIsLocalbodyLoading(false); - setLocalBody(localBodyList.data); - } else { - setLocalBody([]); - } - }, - [dispatchAction] - ); + const fetchLocalBody = useCallback(async (id: string) => { + if (Number(id) > 0) { + setIsLocalbodyLoading(true); + const { data } = await request(routes.getLocalbodyByDistrict, { + pathParams: { id }, + }); + setIsLocalbodyLoading(false); + setLocalBody(data || []); + } else { + setLocalBody([]); + } + }, []); - const fetchWards = useCallback( - async (id: string) => { - if (Number(id) > 0) { - setIsWardLoading(true); - const wardList = await dispatchAction(getWardByLocalBody({ id })); - setIsWardLoading(false); - setWard(wardList.data.results); - } else { - setWard([]); + const fetchWards = useCallback(async (id: string) => { + if (Number(id) > 0) { + setIsWardLoading(true); + const { data } = await request(routes.getWardByLocalBody, { + pathParams: { id }, + }); + setIsWardLoading(false); + if (data) { + setWard(data.results); } - }, - [dispatchAction] - ); + } else { + setWard([]); + } + }, []); const parseGenderFromExt = (gender: any, defaultValue: any) => { switch (gender.toLowerCase()) { @@ -297,97 +279,95 @@ export const PatientRegister = (props: PatientRegisterProps) => { const fetchExtResultData = async (e: any, field: any) => { if (e) e.preventDefault(); if (!careExtId) return; - const res = await dispatchAction(externalResult({ id: careExtId })); + const { res, data } = await request(routes.externalResult, { + pathParams: { id: careExtId }, + }); - if (res?.data) { + if (res?.ok && data) { field.onChange({ name: "name", - value: res.data.name ? res.data.name : state.form.name, + value: data.name ? data.name : state.form.name, }); field.onChange({ name: "address", - value: res.data.address ? res.data.address : state.form.address, + value: data.address ? data.address : state.form.address, }); field.onChange({ name: "permanent_address", - value: res.data.permanent_address - ? res.data.permanent_address + value: data.permanent_address + ? data.permanent_address : state.form.permanent_address, }); field.onChange({ name: "gender", - value: res.data.gender - ? parseGenderFromExt(res.data.gender, state.form.gender) + value: data.gender + ? parseGenderFromExt(data.gender, state.form.gender) : state.form.gender, }); field.onChange({ name: "test_id", - value: res.data.test_id ? res.data.test_id : state.form.test_id, + value: data.test_id ? data.test_id : state.form.test_id, }); field.onChange({ name: "srf_id", - value: res.data.srf_id ? res.data.srf_id : state.form.srf_id, + value: data.srf_id ? data.srf_id : state.form.srf_id, }); field.onChange({ name: "state", - value: res.data.district_object - ? res.data.district_object.state + value: data.district_object + ? data.district_object.state : state.form.state, }); field.onChange({ name: "district", - value: res.data.district ? res.data.district : state.form.district, + value: data.district ? data.district : state.form.district, }); field.onChange({ name: "local_body", - value: res.data.local_body - ? res.data.local_body - : state.form.local_body, + value: data.local_body ? data.local_body : state.form.local_body, }); field.onChange({ name: "ward", - value: res.data.ward ? res.data.ward : state.form.ward, + value: data.ward ? data.ward : state.form.ward, }); field.onChange({ name: "village", - value: res.data.village ? res.data.village : state.form.village, + value: data.village ? data.village : state.form.village, }); field.onChange({ name: "disease_status", - value: res.data.result - ? res.data.result.toUpperCase() + value: data.result + ? data.result.toUpperCase() : state.form.disease_status, }); field.onChange({ name: "test_type", - value: res.data.test_type - ? res.data.test_type.toUpperCase() + value: data.test_type + ? data.test_type.toUpperCase() : state.form.test_type, }); field.onChange({ name: "date_of_test", - value: res.data.sample_collection_date - ? res.data.sample_collection_date + value: data.sample_collection_date + ? data.sample_collection_date : state.form.date_of_test, }); field.onChange({ name: "date_of_result", - value: res.data.result_date - ? res.data.result_date - : state.form.date_of_result, + value: data.result_date ? data.result_date : state.form.date_of_result, }); field.onChange({ name: "phone_number", - value: res.data.mobile_number - ? "+91" + res.data.mobile_number + value: data.mobile_number + ? "+91" + data.mobile_number : state.form.phone_number, }); Promise.all([ - fetchDistricts(res.data.district_object.state), - fetchLocalBody(res.data.district), - fetchWards(res.data.local_body), - duplicateCheck(res.data.mobile_number), + fetchDistricts(data.district_object.state), + fetchLocalBody(String(data.district)), + fetchWards(String(data.local_body)), // Convert data.local_body to a string + duplicateCheck(data.mobile_number), ]); setShowImport({ show: false, @@ -399,93 +379,93 @@ export const PatientRegister = (props: PatientRegisterProps) => { const fetchData = useCallback( async (status: statusType) => { setIsLoading(true); - const res = await dispatchAction(getPatient({ id })); + const { res, data } = await request(routes.getPatient, { + pathParams: { id: id ? id : 0 }, + }); if (!status.aborted) { - if (res?.data) { - setFacilityName(res.data.facility_object.name); - setPatientName(res.data.name); - console.log(res.data); + if (res?.ok && data) { + setPatientName(data.name || ""); const formData = { - ...res.data, - health_id_number: res.data.abha_number_object?.abha_number || "", - health_id: res.data.abha_number_object?.health_id || "", - nationality: res.data.nationality ? res.data.nationality : "India", - gender: res.data.gender ? res.data.gender : "", - cluster_name: res.data.cluster_name ? res.data.cluster_name : "", - state: res.data.state ? res.data.state : "", - district: res.data.district ? res.data.district : "", - blood_group: res.data.blood_group - ? res.data.blood_group === "UNKNOWN" + ...data, + health_id_number: data.abha_number_object?.abha_number || "", + health_id: data.abha_number_object?.health_id || "", + nationality: data.nationality ? data.nationality : "India", + gender: data.gender ? data.gender : undefined, + cluster_name: data.cluster_name ? data.cluster_name : "", + state: data.state ? data.state : "", + district: data.district ? data.district : "", + blood_group: data.blood_group + ? data.blood_group === "UNKNOWN" ? "UNK" - : res.data.blood_group + : data.blood_group : "", - local_body: res.data.local_body ? res.data.local_body : "", - ward: res.data.ward_object ? res.data.ward_object.id : undefined, - village: res.data.village ? res.data.village : "", + local_body: data.local_body ? data.local_body : "", + ward: data.ward_object ? data.ward_object.id : undefined, + village: data.village ? data.village : "", medical_history: [], - is_antenatal: String(!!res.data.is_antenatal), - allergies: res.data.allergies ? res.data.allergies : "", - pincode: res.data.pincode ? res.data.pincode : "", - ongoing_medication: res.data.ongoing_medication - ? res.data.ongoing_medication + is_antenatal: String(!!data.is_antenatal), + allergies: data.allergies ? data.allergies : "", + pincode: data.pincode ? data.pincode : "", + ongoing_medication: data.ongoing_medication + ? data.ongoing_medication : "", - is_declared_positive: res.data.is_declared_positive - ? String(res.data.is_declared_positive) + is_declared_positive: data.is_declared_positive + ? String(data.is_declared_positive) : "false", - designation_of_health_care_worker: res.data - .designation_of_health_care_worker - ? res.data.designation_of_health_care_worker + designation_of_health_care_worker: + data.designation_of_health_care_worker + ? data.designation_of_health_care_worker + : "", + instituion_of_health_care_worker: + data.instituion_of_health_care_worker + ? data.instituion_of_health_care_worker + : "", + + number_of_primary_contacts: data.number_of_primary_contacts + ? data.number_of_primary_contacts : "", - instituion_of_health_care_worker: res.data - .instituion_of_health_care_worker - ? res.data.instituion_of_health_care_worker + number_of_secondary_contacts: data.number_of_secondary_contacts + ? data.number_of_secondary_contacts : "", - - number_of_primary_contacts: res.data.number_of_primary_contacts - ? res.data.number_of_primary_contacts - : "", - number_of_secondary_contacts: res.data.number_of_secondary_contacts - ? res.data.number_of_secondary_contacts - : "", - contact_with_confirmed_carrier: res.data - .contact_with_confirmed_carrier - ? String(res.data.contact_with_confirmed_carrier) + contact_with_confirmed_carrier: data.contact_with_confirmed_carrier + ? String(data.contact_with_confirmed_carrier) : "false", - contact_with_suspected_carrier: res.data - .contact_with_suspected_carrier - ? String(res.data.contact_with_suspected_carrier) + contact_with_suspected_carrier: data.contact_with_suspected_carrier + ? String(data.contact_with_suspected_carrier) : "false", - is_vaccinated: String(res.data.is_vaccinated), - number_of_doses: res.data.number_of_doses - ? String(res.data.number_of_doses) + is_vaccinated: String(data.is_vaccinated), + number_of_doses: data.number_of_doses + ? String(data.number_of_doses) : "0", - vaccine_name: res.data.vaccine_name ? res.data.vaccine_name : null, - last_vaccinated_date: res.data.last_vaccinated_date - ? res.data.last_vaccinated_date + vaccine_name: data.vaccine_name ? data.vaccine_name : null, + last_vaccinated_date: data.last_vaccinated_date + ? data.last_vaccinated_date : null, }; - - formData.sameAddress = - res.data.address === res.data.permanent_address; - res.data.medical_history.forEach((i: any) => { - const medicalHistory = MEDICAL_HISTORY_CHOICES.find( - (j: any) => - String(j.text).toLowerCase() === String(i.disease).toLowerCase() - ); - if (medicalHistory) { - formData.medical_history.push(medicalHistory.id); - formData[`medical_history_${medicalHistory.id}`] = i.details; + formData.sameAddress = data.address === data.permanent_address; + (data.medical_history ? data.medical_history : []).forEach( + (i: any) => { + const medicalHistory = MEDICAL_HISTORY_CHOICES.find( + (j) => + String(j.text).toLowerCase() === + String(i.disease).toLowerCase() + ); + if (medicalHistory) { + formData.medical_history.push(Number(medicalHistory.id)); + formData[`medical_history_${String(medicalHistory.id)}`] = + i.details; + } } - }); + ); dispatch({ type: "set_form", form: formData, }); Promise.all([ - fetchDistricts(res.data.state), - fetchLocalBody(res.data.district), - fetchWards(res.data.local_body), + fetchDistricts(data.state ?? 0), + fetchLocalBody(data.district ? String(data.district) : ""), + fetchWards(data.local_body ? String(data.local_body) : ""), // Convert data.local_body to string ]); } else { goBack(); @@ -493,37 +473,25 @@ export const PatientRegister = (props: PatientRegisterProps) => { setIsLoading(false); } }, - [dispatchAction, fetchDistricts, fetchLocalBody, fetchWards, id] + [id] ); - useEffect(() => { - const fetchPatientInsuranceDetails = async () => { - if (!id) { + useQuery(routes.listHCXPolicies, { + query: { + patient: id, + }, + prefetch: !!id, + onResponse: ({ data }) => { + if (data) { + setInsuranceDetails(data.results); + } else { setInsuranceDetails([]); - return; } - - const res = await dispatchAction( - HCXActions.policies.list({ patient: id }) - ); - if (res?.data) { - setInsuranceDetails(res.data.results); - } - }; - - fetchPatientInsuranceDetails(); - }, [dispatchAction, id]); - - const fetchStates = useCallback( - async (status: statusType) => { - setIsStateLoading(true); - const statesRes = await dispatchAction(getStates()); - if (!status.aborted && statesRes.data.results) { - setStates(statesRes.data.results); - } - setIsStateLoading(false); }, - [dispatchAction] + }); + + const { data: stateData, loading: isStateLoading } = useQuery( + routes.statesList ); useAbortableEffect( @@ -531,24 +499,14 @@ export const PatientRegister = (props: PatientRegisterProps) => { if (id) { fetchData(status); } - fetchStates(status); }, [dispatch, fetchData] ); - useEffect(() => { - async function fetchFacilityName() { - if (facilityId && !id) { - const res = await dispatchAction(getAnyFacility(facilityId)); - - setFacilityName(res?.data?.name || ""); - } else { - setFacilityName(""); - } - } - - fetchFacilityName(); - }, [dispatchAction, facilityId]); + const { data: facilityObject } = useQuery(routes.getAnyFacility, { + pathParams: { id: facilityId }, + prefetch: !!facilityId, + }); const validateForm = (form: any) => { const errors: Partial> = {}; @@ -701,7 +659,7 @@ export const PatientRegister = (props: PatientRegisterProps) => { const pincodeDetails = await getPincodeDetails(e.value, gov_data_api_key); if (!pincodeDetails) return; - const matchedState = states?.find((state) => { + const matchedState = stateData?.results?.find((state) => { return includesIgnoreCase(state.name, pincodeDetails.statename); }); if (!matchedState) return; @@ -715,9 +673,9 @@ export const PatientRegister = (props: PatientRegisterProps) => { if (!matchedDistrict) return; setField({ name: "state", value: matchedState.id }); - setField({ name: "district", value: matchedDistrict.id }); + setField({ name: "district", value: matchedDistrict.id.toString() }); // Convert matchedDistrict.id to string - fetchLocalBody(matchedDistrict.id); + fetchLocalBody(matchedDistrict.id.toString()); // Convert matchedDistrict.id to string setShowAutoFilledPincode(true); setTimeout(() => { setShowAutoFilledPincode(false); @@ -834,37 +792,45 @@ export const PatientRegister = (props: PatientRegisterProps) => { medical_history, is_active: true, }; - const res = await dispatchAction( - id - ? updatePatient(data, { id }) - : createPatient({ ...data, facility: facilityId }) - ); - if (res && res.data && res.status != 400) { + const { res, data: requestData } = id + ? await request(routes.updatePatient, { + pathParams: { id }, + body: data, + }) + : await request(routes.addPatient, { + body: { ...data, facility: facilityId }, + }); + if (res?.ok && requestData) { await Promise.all( insuranceDetails.map(async (obj) => { const policy = { ...obj, - patient: res.data.id, + patient: requestData.id, insurer_id: obj.insurer_id || undefined, insurer_name: obj.insurer_name || undefined, }; - const policyRes = await (policy.id - ? dispatchAction( - HCXActions.policies.update(policy.id, policy as HCXPolicyModel) - ) - : dispatchAction( - HCXActions.policies.create(policy as HCXPolicyModel) - )); - - if (enable_hcx) { - const eligibilityCheckRes = await dispatchAction( - HCXActions.checkEligibility(policyRes.data.id) - ); - if (eligibilityCheckRes.status === 200) { - Notification.Success({ msg: "Checking Policy Eligibility..." }); - } else { - Notification.Error({ msg: "Something Went Wrong..." }); - } + const { data: policyData } = policy.id + ? await request(routes.updateHCXPolicy, { + pathParams: { external_id: policy.id }, + body: policy, + }) + : await request(routes.createHCXPolicy, { + body: policy, + }); + + if (enable_hcx && policyData?.id) { + await request(routes.hcxCheckEligibility, { + body: { policy: policyData?.id }, + onResponse: ({ res }) => { + if (res?.ok) { + Notification.Success({ + msg: "Checking Policy Eligibility...", + }); + } else { + Notification.Error({ msg: "Something Went Wrong..." }); + } + }, + }); } }) ); @@ -873,10 +839,12 @@ export const PatientRegister = (props: PatientRegisterProps) => { if (!id) { setAlertMessage({ show: true, - message: `Please note down patient name: ${formData.name} and patient ID: ${res.data.id}`, + message: `Please note down patient name: ${formData.name} and patient ID: ${requestData.id}`, title: "Patient Added Successfully", }); - navigate(`/facility/${facilityId}/patient/${res.data.id}/consultation`); + navigate( + `/facility/${facilityId}/patient/${requestData.id}/consultation` + ); } else { Notification.Success({ msg: "Patient updated successfully", @@ -970,33 +938,32 @@ export const PatientRegister = (props: PatientRegisterProps) => { }); }; - const duplicateCheck = useCallback( - debounce(async (phoneNo: string) => { - if ( - phoneNo && - PhoneNumberValidator()(parsePhoneNumber(phoneNo) ?? "") === undefined - ) { - const query = { - phone_number: parsePhoneNumber(phoneNo), - }; - const res = await dispatchAction(searchPatient(query)); - if (res?.data?.results) { - const duplicateList = !id - ? res.data.results - : res.data.results.filter( - (item: DupPatientModel) => item.patient_id !== id - ); - if (duplicateList.length) { - setStatusDialog({ - show: true, - patientList: duplicateList, - }); - } + const duplicateCheck = debounce(async (phoneNo: string) => { + if ( + phoneNo && + PhoneNumberValidator()(parsePhoneNumber(phoneNo) ?? "") === undefined + ) { + const query = { + phone_number: parsePhoneNumber(phoneNo), + }; + const { res, data } = await request(routes.searchPatient, { + query, + }); + if (res?.ok && data?.results) { + const duplicateList = !id + ? data.results + : data.results.filter( + (item: DupPatientModel) => item.patient_id !== id + ); + if (duplicateList.length) { + setStatusDialog({ + show: true, + patientList: duplicateList, + }); } } - }, 300), - [] - ); + } + }, 300); const handleDialogClose = (action: string) => { if (action === "transfer") { @@ -1080,7 +1047,7 @@ export const PatientRegister = (props: PatientRegisterProps) => { } }} crumbsReplacements={{ - [facilityId]: { name: facilityName }, + [facilityId]: { name: facilityObject?.name }, [id ?? "????"]: { name: patientName }, }} /> @@ -1424,7 +1391,7 @@ export const PatientRegister = (props: PatientRegisterProps) => { label="State" required placeholder="Choose State" - options={states} + options={stateData ? stateData.results : []} optionLabel={(o: any) => o.name} optionValue={(o: any) => o.id} onChange={(e: any) => { diff --git a/src/Redux/actions.tsx b/src/Redux/actions.tsx index c11a5f9de59..73e1a839519 100644 --- a/src/Redux/actions.tsx +++ b/src/Redux/actions.tsx @@ -62,50 +62,21 @@ export const downloadFacilityTriage = () => { }; //Patient -export const searchPatient = (params: object) => { - return fireRequest("searchPatient", [], params); -}; export const getAllPatient = (params: object, altKey: string) => { return fireRequest("patientList", [], params, null, altKey); }; -export const createPatient = (params: object) => { - return fireRequest("addPatient", [], params); -}; export const getPatient = (pathParam: object) => { return fireRequest("getPatient", [], {}, pathParam); }; -export const updatePatient = (params: object, pathParam: object) => { - return fireRequest("updatePatient", [], params, pathParam); -}; - -export const transferPatient = (params: object, pathParam: object) => { - return fireRequest("transferPatient", [], params, pathParam); -}; - export const patchPatient = (params: object, pathParam: object) => { return fireRequest("patchPatient", [], params, pathParam); }; -export const getStates = () => { - return fireRequest("statesList", []); -}; - // District/State/Local body/ward -export const getDistrictByState = (pathParam: object) => { - return fireRequest("getDistrictByState", [], {}, pathParam); -}; export const getDistrictByName = (params: object) => { return fireRequest("getDistrictByName", [], params, null); }; -export const getLocalbodyByDistrict = (pathParam: object) => { - return fireRequest("getLocalbodyByDistrict", [], {}, pathParam); -}; - -export const getWardByLocalBody = (pathParam: object) => { - return fireRequest("getWardByLocalBody", [], {}, pathParam); -}; - // Sample Test export const downloadSampleTests = (params: object) => { return fireRequest("getTestSampleList", [], { ...params, csv: 1 }); diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index 3bed047a4fe..d566fb91c86 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -57,6 +57,7 @@ import { InventoryLogResponse, InventoryItemsModel, PatientTransferResponse, + DupPatientModel, } from "../Components/Facility/models"; import { IDeleteBedCapacity, @@ -665,6 +666,7 @@ const routes = { searchPatient: { path: "/api/v1/patient/search", + TRes: Type>(), }, patientList: { path: "/api/v1/patient/", @@ -674,15 +676,18 @@ const routes = { addPatient: { path: "/api/v1/patient/", method: "POST", + TRes: Type(), }, getPatient: { path: "/api/v1/patient/{id}/", method: "GET", + TBody: Type(), TRes: Type(), }, updatePatient: { path: "/api/v1/patient/{id}/", method: "PUT", + TRes: Type(), }, patchPatient: { path: "/api/v1/patient/{id}/", @@ -1417,6 +1422,7 @@ const routes = { hcxCheckEligibility: { path: "/api/v1/hcx/check_eligibility/", method: "POST", + TRes: Type(), }, listHCXPolicies: { @@ -1428,6 +1434,7 @@ const routes = { createHCXPolicy: { path: "/api/v1/hcx/policy/", method: "POST", + TRes: Type(), }, getHCXPolicy: { @@ -1438,6 +1445,7 @@ const routes = { updateHCXPolicy: { path: "/api/v1/hcx/policy/{external_id}/", method: "PUT", + TRes: Type(), }, partialUpdateHCXPolicy: {