diff --git a/cypress/e2e/patient_spec/PatientRegistration.cy.ts b/cypress/e2e/patient_spec/PatientRegistration.cy.ts index 2143ff7a651..4e493a23bff 100644 --- a/cypress/e2e/patient_spec/PatientRegistration.cy.ts +++ b/cypress/e2e/patient_spec/PatientRegistration.cy.ts @@ -242,14 +242,6 @@ describe("Patient Creation with consultation", () => { .contains("member id") .scrollIntoView(); cy.wait(2000); - patientInsurance.verifyPatientPolicyDetails( - patientOneFirstSubscriberId, - patientOneFirstPolicyId, - patientOneFirstInsurerId, - patientOneFirstInsurerName, - isHCXEnabled, - ); - patientInsurance.clickPatientInsuranceViewDetail(); cy.wait(3000); patientInsurance.verifyPatientPolicyDetails( diff --git a/cypress/e2e/users_spec/UsersCreation.cy.ts b/cypress/e2e/users_spec/UsersCreation.cy.ts index 2c5797fefa7..392c9ff987d 100644 --- a/cypress/e2e/users_spec/UsersCreation.cy.ts +++ b/cypress/e2e/users_spec/UsersCreation.cy.ts @@ -79,13 +79,10 @@ describe("User Creation", () => { ); userCreationPage.typeIntoElementByIdPostClear("lastName", "Cypress"); userCreationPage.selectDropdownOption("gender", "Male"); - userCreationPage.typeIntoElementByIdPostClear( - "phoneNumber", - "+91" + phone_number, - ); + userCreationPage.typeIntoElementByIdPostClear("phoneNumber", phone_number); userCreationPage.typeIntoElementByIdPostClear( "altPhoneNumber", - "+91" + emergency_phone_number, + emergency_phone_number, ); userCreationPage.typeIntoElementByIdPostClear("email", "test@test.com"); userCreationPage.typeIntoElementByIdPostClear("weekly_working_hours", "14"); diff --git a/cypress/e2e/users_spec/UsersProfile.cy.ts b/cypress/e2e/users_spec/UsersProfile.cy.ts index 8dc1ad7ef0a..3073cebe7ce 100644 --- a/cypress/e2e/users_spec/UsersProfile.cy.ts +++ b/cypress/e2e/users_spec/UsersProfile.cy.ts @@ -10,7 +10,7 @@ describe("Manage User Profile", () => { const date_of_birth = "01011999"; const gender = "Male"; const email = "test@example.com"; - const phone = "+918899887788"; + const phone = "8899887788"; const workinghours = "8"; const qualification = "MBBS"; const doctorYoE = "10"; diff --git a/cypress/pageobject/Facility/FacilityLocation.ts b/cypress/pageobject/Facility/FacilityLocation.ts index be14e9a8c81..31bc30290f7 100644 --- a/cypress/pageobject/Facility/FacilityLocation.ts +++ b/cypress/pageobject/Facility/FacilityLocation.ts @@ -84,7 +84,7 @@ class FacilityLocation { } clickNotification() { - cy.get(".pnotify").click(); + cy.get(".pnotify-container").click(); } enterBedName(name: string) { diff --git a/src/Locale/en.json b/src/Locale/en.json index 9826b7532fa..fa5bdeb6aff 100644 --- a/src/Locale/en.json +++ b/src/Locale/en.json @@ -235,6 +235,7 @@ "abha_address_validation_length_error": "Should be atleast 4 character long", "abha_address_validation_start_error": "Shouldn't start with a number or dot (.)", "abha_details": "ABHA Details", + "abha_disabled_due_to_no_health_facility": "ABHA Number generation and linking is disabled for this facility, Please link a health facility to enable this feature.", "abha_link_options__create_with_aadhaar__description": "Create New ABHA Number Using Aadhaar Number", "abha_link_options__create_with_aadhaar__title": "Create with Aadhaar", "abha_link_options__create_with_driving_license__description": "Create New ABHA Number Using Driving License", @@ -379,6 +380,7 @@ "checking_eligibility": "Checking Eligibility", "checking_for_update": "Checking for update", "checking_policy_eligibility": "Checking Policy Eligibility", + "choose_date_time": "Choose Date and Time", "choose_file": "Upload From Device", "choose_location": "Choose Location", "claim__add_item": "Add Item", @@ -668,6 +670,7 @@ "full_name": "Full Name", "full_screen": "Full Screen", "gender": "Gender", + "generate_link_abha": "Generate/Link ABHA Number", "generate_report": "Generate Report", "generated_summary_caution": "This is a computer generated summary using the information captured in the CARE system.", "generating": "Generating", @@ -871,6 +874,7 @@ "no_tests_taken": "No tests taken", "no_treating_physicians_available": "This facility does not have any home facility doctors. Please contact your admin.", "no_users_found": "No Users Found", + "no_vitals_present": "No Vitals Monitor present in this location or facility", "none": "None", "normal": "Normal", "not_eligible": "Not Eligible", @@ -1242,6 +1246,7 @@ "virtual_nursing_assistant": "Virtual Nursing Assistant", "vitals": "Vitals", "vitals_monitor": "Vitals Monitor", + "vitals_present": "Vitals Monitor present", "ward": "Ward", "warranty_amc_expiry": "Warranty / AMC Expiry", "what_facility_assign_the_patient_to": "What facility would you like to assign the patient to", diff --git a/src/Utils/request/useMutation.ts b/src/Utils/request/useMutation.ts new file mode 100644 index 00000000000..737b32a2237 --- /dev/null +++ b/src/Utils/request/useMutation.ts @@ -0,0 +1,41 @@ +import request from "@/Utils/request/request"; +import { + MutationRoute, + RequestOptions, + RequestResult, +} from "@/Utils/request/types"; +import { mergeRequestOptions } from "@/Utils/request/utils"; +import React from "react"; + +export default function useMutation( + route: MutationRoute, + options: RequestOptions, +) { + const [response, setResponse] = React.useState>(); + const [isProcessing, setIsProcessing] = React.useState(false); + + const controllerRef = React.useRef(); + + const runQuery = React.useCallback( + async (overrides?: RequestOptions) => { + controllerRef.current?.abort(); + + const controller = new AbortController(); + controllerRef.current = controller; + + const resolvedOptions = + options && overrides + ? mergeRequestOptions(options, overrides) + : (overrides ?? options); + + setIsProcessing(true); + const response = await request(route, { ...resolvedOptions, controller }); + setResponse(response); + setIsProcessing(false); + return response; + }, + [route, JSON.stringify(options)], + ); + + return { ...response, isProcessing, mutate: runQuery }; +} diff --git a/src/components/Common/LocationSelect.tsx b/src/components/Common/LocationSelect.tsx index cf8a4e2d6b8..cb1b7514ac0 100644 --- a/src/components/Common/LocationSelect.tsx +++ b/src/components/Common/LocationSelect.tsx @@ -15,6 +15,8 @@ interface LocationSelectProps { selected: string | string[] | null; setSelected: (selected: string | string[] | null) => void; errorClassName?: string; + bedIsOccupied?: boolean; + disableOnOneOrFewer?: boolean; } export const LocationSelect = (props: LocationSelectProps) => { @@ -23,6 +25,8 @@ export const LocationSelect = (props: LocationSelectProps) => { { query: { limit: 14, + bed_is_occupied: + props.bedIsOccupied === undefined ? undefined : !props.bedIsOccupied, }, pathParams: { facility_external_id: props.facilityId, @@ -31,6 +35,10 @@ export const LocationSelect = (props: LocationSelectProps) => { }, ); + if (props.disableOnOneOrFewer && data && data.count <= 1) { + props = { ...props, disabled: true }; + } + return props.multiple ? ( + updatePage(page)} + />
- {totalCount} Vitals - Monitor present + {totalCount}{" "} + {t("vitals_present")}
@@ -134,6 +141,10 @@ export default function CentralNursingStation({ facilityId }: Props) { facilityId={facilityId} errors="" errorClassName="hidden" + bedIsOccupied={JSON.parse( + qParams.monitors_without_patient ?? "false", + )} + disableOnOneOrFewer /> @@ -164,7 +175,9 @@ export default function CentralNursingStation({ facilityId }: Props) { value={JSON.parse( qParams.monitors_without_patient ?? "false", )} - onChange={(e) => updateQuery({ [e.name]: `${e.value}` })} + onChange={(e) => + updateQuery({ [e.name]: `${e.value}`, location: "" }) + } labelClassName="text-sm" errorClassName="hidden" /> @@ -189,14 +202,6 @@ export default function CentralNursingStation({ facilityId }: Props) {
- - updatePage(page)} - /> } > @@ -204,7 +209,7 @@ export default function CentralNursingStation({ facilityId }: Props) { ) : data.length === 0 ? (
- No Vitals Monitor present in this location or facility. + {t("no_vitals_present")}
) : (
diff --git a/src/components/Facility/ConsultationDetails/index.tsx b/src/components/Facility/ConsultationDetails/index.tsx index 6a4dba966c4..148411a6e06 100644 --- a/src/components/Facility/ConsultationDetails/index.tsx +++ b/src/components/Facility/ConsultationDetails/index.tsx @@ -76,7 +76,7 @@ export const ConsultationDetails = (props: any) => { } const [showDoctors, setShowDoctors] = useState(false); const [qParams, _] = useQueryParams(); - const [patientData, setPatientData] = useState({}); + const [patientData, setPatientData] = useState(); const [abhaNumberData, setAbhaNumberData] = useState(); const [activeShiftingData, setActiveShiftingData] = useState>([]); @@ -135,7 +135,7 @@ export const ConsultationDetails = (props: any) => { address: getPatientAddress(data), comorbidities: getPatientComorbidities(data), is_declared_positive: data.is_declared_positive ? "Yes" : "No", - is_vaccinated: patientData.is_vaccinated ? "Yes" : "No", + is_vaccinated: patientData?.is_vaccinated ? "Yes" : "No", } as any); }, }); @@ -160,7 +160,7 @@ export const ConsultationDetails = (props: any) => { setActiveShiftingData(shiftRequestsQuery.data.results); } }, - [consultationId, patientData.is_vaccinated], + [consultationId, patientData?.is_vaccinated], ); useEffect(() => { @@ -176,7 +176,7 @@ export const ConsultationDetails = (props: any) => { }); }, [patientDataQuery.data?.id]); - if (!consultationData || patientDataQuery.loading) { + if (!patientData || !consultationData || patientDataQuery.loading) { return ; } diff --git a/src/components/Facility/Consultations/PainDiagrams.tsx b/src/components/Facility/Consultations/PainDiagrams.tsx index 2b73fe978ad..c5c6d06864f 100644 --- a/src/components/Facility/Consultations/PainDiagrams.tsx +++ b/src/components/Facility/Consultations/PainDiagrams.tsx @@ -1,57 +1,41 @@ import { useEffect, useState } from "react"; -import routes from "../../../Redux/api"; -import request from "../../../Utils/request/request"; import { formatDateTime } from "../../../Utils/utils"; import PainChart from "../../LogUpdate/components/PainChart"; -import { PainDiagramsFields } from "../models"; +import { useTranslation } from "react-i18next"; export const PainDiagrams = (props: any) => { - const { consultationId } = props; - const [isLoading, setIsLoading] = useState(false); - const [results, setResults] = useState({}); - const [selectedData, setData] = useState({ + const { dailyRound } = props; + const [results, setResults] = useState({}); + const [selectedData, setData] = useState({ data: [], id: "", }); + const { t } = useTranslation(); useEffect(() => { - const fetchDailyRounds = async (consultationId: string) => { - setIsLoading(true); - const { res, data: dailyRound } = await request( - routes.dailyRoundsAnalyse, - { - body: { fields: PainDiagramsFields }, - pathParams: { - consultationId, - }, - }, - ); - if (res && res.ok && dailyRound?.results) { - const keys = Object.keys(dailyRound.results || {}).filter( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - (key) => dailyRound.results[key].pain_scale_enhanced.length, + const filterDailyRounds = () => { + if (dailyRound) { + const keys = Object.keys(dailyRound || {}).filter( + (key) => dailyRound[key].pain_scale_enhanced.length, ); const data: any = {}; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - keys.forEach((key) => (data[key] = dailyRound.results[key])); + keys.forEach( + (key) => + (data[key] = Object.assign( + {}, + { pain_scale_enhanced: dailyRound[key].pain_scale_enhanced }, + )), + ); setResults(data); if (keys.length > 0) { setSelectedDateData(data, keys[0]); } } - setIsLoading(false); }; - fetchDailyRounds(consultationId); - }, [consultationId]); - - useEffect(() => { - if (Object.keys(results).length > 0) - setSelectedDateData(results, Object.keys(results)[0]); - }, [results]); + filterDailyRounds(); + }, [dailyRound]); useEffect(() => { if (Object.keys(results).length > 0) @@ -73,7 +57,7 @@ export const PainDiagrams = (props: any) => { const dropdown = (dates: Array) => { return dates && dates.length > 0 ? (
-
Choose Date and Time
+
{t("choose_date_time")}
); @@ -106,7 +90,7 @@ export const PainDiagrams = (props: any) => { return (
{dates && dropdown(dates)} - {!isLoading && selectedData.data ? ( + {selectedData.data ? ( ) : (
diff --git a/src/components/Facility/Consultations/PrimaryParametersPlot.tsx b/src/components/Facility/Consultations/PrimaryParametersPlot.tsx index eb831127773..067e197e374 100644 --- a/src/components/Facility/Consultations/PrimaryParametersPlot.tsx +++ b/src/components/Facility/Consultations/PrimaryParametersPlot.tsx @@ -255,7 +255,7 @@ export const PrimaryParametersPlot = ({
- +
{totalCount > PAGINATION_LIMIT && (
diff --git a/src/components/Facility/models.tsx b/src/components/Facility/models.tsx index 73473c57c1e..e64bbfda99f 100644 --- a/src/components/Facility/models.tsx +++ b/src/components/Facility/models.tsx @@ -449,6 +449,7 @@ export const PrimaryParametersPlotFields = [ "ventilator_fio2", "rhythm", "rhythm_detail", + "pain_scale_enhanced", ] as const satisfies (keyof DailyRoundsModel)[]; export type PrimaryParametersPlotRes = { diff --git a/src/components/Form/FormFields/PhoneNumberFormField.tsx b/src/components/Form/FormFields/PhoneNumberFormField.tsx index 4d1bda64399..92bca8126ea 100644 --- a/src/components/Form/FormFields/PhoneNumberFormField.tsx +++ b/src/components/Form/FormFields/PhoneNumberFormField.tsx @@ -92,10 +92,6 @@ export default function PhoneNumberFormField(props: Props) { } }, [setValue]); - useEffect(() => { - setValue(field.value || "+91"); - }, []); - return ( { - if (value == null) { + if (!value) { return "+91 "; } diff --git a/src/components/LogUpdate/Sections/RespiratorySupport/OxygenSupport.tsx b/src/components/LogUpdate/Sections/RespiratorySupport/OxygenSupport.tsx index 4c343f71f74..45d339bae04 100644 --- a/src/components/LogUpdate/Sections/RespiratorySupport/OxygenSupport.tsx +++ b/src/components/LogUpdate/Sections/RespiratorySupport/OxygenSupport.tsx @@ -8,6 +8,25 @@ import { OXYGEN_MODALITY_OPTIONS } from "@/common/constants"; const OxygenRespiratorySupport = ({ log, onChange }: LogUpdateSectionProps) => { const { t } = useTranslation(); + const handleChange = (c: any) => { + let resetData = {}; + switch (c.value) { + case "HIGH_FLOW_NASAL_CANNULA": + resetData = { ventilator_oxygen_modality_oxygen_rate: null }; + break; + default: + resetData = { + ventilator_fio2: null, + ventilator_oxygen_modality_flow_rate: null, + }; + } + onChange({ + ventilator_oxygen_modality: + c.value as typeof log.ventilator_oxygen_modality, + ...resetData, + }); + }; + return ( <> { optionValue={(c) => c.value} name="ventilator_oxygen_modality" value={log.ventilator_oxygen_modality} - onChange={(c) => - onChange({ - ventilator_oxygen_modality: - c.value as typeof log.ventilator_oxygen_modality, - }) - } + onChange={handleChange} layout="vertical" />
diff --git a/src/components/LogUpdate/Sections/RespiratorySupport/index.tsx b/src/components/LogUpdate/Sections/RespiratorySupport/index.tsx index 74164ab6de1..c53d5f61108 100644 --- a/src/components/LogUpdate/Sections/RespiratorySupport/index.tsx +++ b/src/components/LogUpdate/Sections/RespiratorySupport/index.tsx @@ -51,6 +51,38 @@ const RespiratorySupport = ({ log, onChange }: LogUpdateSectionProps) => { } }, [warnForNoLinkedVentilator]); + const handleChange = (c: any) => { + let resetData = {}; + if (["OXYGEN_SUPPORT", "UNKNOWN"].includes(c.value)) { + resetData = { + ...resetData, + ventilator_spo2: undefined, + ventilator_fio2: undefined, + ventilator_peep: undefined, + ventilator_pip: undefined, + ventilator_mean_airway_pressure: undefined, + ventilator_resp_rate: undefined, + ventilator_pressure_support: undefined, + ventilator_tidal_volume: undefined, + ventilator_mode: undefined, + }; + } + if (["INVASIVE", "NON_INVASIVE", "UNKNOWN"].includes(c.value)) { + resetData = { + ...resetData, + ventilator_spo2: undefined, + ventilator_oxygen_modality_flow_rate: undefined, + ventilator_oxygen_modality_oxygen_rate: undefined, + ventilator_oxygen_modality: undefined, + }; + } + onChange({ + ventilator_interface: (c.value || + "UNKNOWN") as typeof log.ventilator_interface, + ...resetData, + }); + }; + return (
{ optionValue={(c) => c.value} name="respiratory_support" value={log.ventilator_interface} - onChange={(c) => - onChange({ - ventilator_interface: (c.value || - "UNKNOWN") as typeof log.ventilator_interface, - }) - } + onChange={handleChange} /> - disabled={isCreating} + disabled={mutation.isProcessing} defaults={props.prescription} onCancel={props.onDone} onSubmit={async (body) => { body["medicine"] = body.medicine_object?.id; delete body.medicine_object; - setIsCreating(true); - const { res, error } = await request( - MedicineRoutes.createPrescription, - { - pathParams: { consultation }, - body, - }, - ); - setIsCreating(false); - + const { res, error } = await mutation.mutate({ body }); if (!res?.ok) { return error; } diff --git a/src/components/Patient/PatientInfoCard.tsx b/src/components/Patient/PatientInfoCard.tsx index 4566cfbfb4f..bdc8b0e672d 100644 --- a/src/components/Patient/PatientInfoCard.tsx +++ b/src/components/Patient/PatientInfoCard.tsx @@ -1,5 +1,10 @@ import * as Notification from "../../Utils/Notifications"; - +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { CONSULTATION_SUGGESTION, DISCHARGE_REASONS, @@ -43,6 +48,7 @@ import { SkillModel } from "../Users/models"; import { AuthorizedForConsultationRelatedActions } from "../../CAREUI/misc/AuthorizedChild"; import LinkAbhaNumber from "../ABDM/LinkAbhaNumber/index"; import careConfig from "@careConfig"; +import { cn } from "@/lib/utils.js"; const formatSkills = (arr: SkillModel[]) => { const skills = arr.map((skill) => skill.skill_object.name); @@ -133,6 +139,11 @@ export default function PatientInfoCard(props: { prefetch: !!consultation?.treating_physician_object?.username, }); + const { data: healthFacility } = useQuery(routes.abdm.healthFacility.get, { + pathParams: { facility_id: patient.facility ?? "" }, + silent: true, + }); + return ( <> ) : ( - - {({ close }) => ( -
{ - close(); - setShowLinkABHANumber(true); - }} - > - - -

{t("link_abha_profile")}

-
-
- )} -
+ + + + + {({ close, disabled }) => ( +
{ + close(); + setShowLinkABHANumber(true); + }} + > + + +

{t("generate_link_abha")}

+
+
+ )} +
+
+ + {!healthFacility && ( + + {t("abha_disabled_due_to_no_health_facility")} + + )} +
+
))}
diff --git a/src/components/Patient/PatientRegister.tsx b/src/components/Patient/PatientRegister.tsx index a39330dd0ee..77f43c04251 100644 --- a/src/components/Patient/PatientRegister.tsx +++ b/src/components/Patient/PatientRegister.tsx @@ -28,7 +28,12 @@ import { import { useCallback, useReducer, useRef, useState } from "react"; import { navigate } from "raviger"; import { statusType, useAbortableEffect } from "@/common/utils"; - +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; import AccordionV2 from "@/components/Common/components/AccordionV2"; import AutocompleteFormField from "../Form/FormFields/Autocomplete"; import ButtonV2 from "@/components/Common/components/ButtonV2"; @@ -372,6 +377,11 @@ export const PatientRegister = (props: PatientRegisterProps) => { [id], ); + const { data: healthFacility } = useQuery(routes.abdm.healthFacility.get, { + pathParams: { facility_id: facilityId }, + silent: true, + }); + useQuery(routes.hcx.policies.list, { query: { patient: id, @@ -1015,16 +1025,28 @@ export const PatientRegister = (props: PatientRegisterProps) => {
{!state.form.abha_number && (
- + + + + + + {!healthFacility && ( + + {t("abha_disabled_due_to_no_health_facility")} + + )} + +
)} {showAlertMessage.show && ( diff --git a/src/components/Resource/ResourceDetails.tsx b/src/components/Resource/ResourceDetails.tsx index 667762e5d22..4cfe959b7b9 100644 --- a/src/components/Resource/ResourceDetails.tsx +++ b/src/components/Resource/ResourceDetails.tsx @@ -322,7 +322,7 @@ export default function ResourceDetails(props: { id: string }) {
Reason:
-
{data.reason || "--"}
+
{data.reason || "--"}
diff --git a/src/components/Users/UserProfile.tsx b/src/components/Users/UserProfile.tsx index 92d7f34aaa6..7aa3c9eff34 100644 --- a/src/components/Users/UserProfile.tsx +++ b/src/components/Users/UserProfile.tsx @@ -126,6 +126,7 @@ export default function UserProfile() { isChecking: false, isUpdateAvailable: false, }); + const [dirty, setDirty] = useState(false); const authUser = useAuthUser(); @@ -181,6 +182,7 @@ export default function UserProfile() { type: "set_form", form: formData, }); + setDirty(false); }, }); @@ -333,6 +335,7 @@ export default function UserProfile() { type: "set_form", form: { ...states.form, [event.name]: event.value }, }); + setDirty(true); }; const getDate = (value: any) => @@ -857,7 +860,11 @@ export default function UserProfile() {
- +