From f712fa33e44f4b1017bc53b632d0a38a5e279dfb Mon Sep 17 00:00:00 2001 From: Mohammed Nihal <57055998+nihal467@users.noreply.github.com> Date: Mon, 20 May 2024 07:23:39 +0530 Subject: [PATCH 01/11] New Cypress Test | Titrated dosage and Individual administration | Patient Prescription Module (#7803) * Titrated dosage * fix flaky test --- .../patient_spec/patient_prescription.cy.ts | 56 +++++++++++++++++-- .../pageobject/Patient/PatientPrescription.ts | 34 +++++++++-- .../Medicine/CreatePrescriptionForm.tsx | 1 + .../Medicine/ManagePrescriptions.tsx | 5 +- .../AdministrationEventCell.tsx | 1 + .../MedicineAdministrationSheet/index.tsx | 1 + .../Medicine/PrescriptionBuilder.tsx | 2 +- .../Medicine/PrescriptionDetailCard.tsx | 1 + 8 files changed, 89 insertions(+), 12 deletions(-) diff --git a/cypress/e2e/patient_spec/patient_prescription.cy.ts b/cypress/e2e/patient_spec/patient_prescription.cy.ts index 3cf5a1ba5aa..d9a7bf7a080 100644 --- a/cypress/e2e/patient_spec/patient_prescription.cy.ts +++ b/cypress/e2e/patient_spec/patient_prescription.cy.ts @@ -5,6 +5,11 @@ import { PatientPage } from "../../pageobject/Patient/PatientCreation"; const patientPrescription = new PatientPrescription(); const loginPage = new LoginPage(); const patientPage = new PatientPage(); +const medicineName = "DOLO"; +const medicineBaseDosage = "4"; +const medicineTargetDosage = "9"; +const medicineFrequency = "Twice daily"; +const medicineAdministerNote = "Medicine Administration Note"; describe("Patient Medicine Administration", () => { before(() => { @@ -18,15 +23,54 @@ describe("Patient Medicine Administration", () => { cy.awaitUrl("/patients"); }); + it("Add a new titrated medicine for a patient | Individual Administeration |", () => { + patientPage.visitPatient("Dummy Patient 5"); + patientPrescription.visitMedicineTab(); + patientPrescription.visitEditPrescription(); + patientPrescription.clickAddPrescription(); + patientPrescription.interceptMedibase(); + patientPrescription.selectMedicinebox(); + patientPrescription.selectMedicine(medicineName); + patientPrescription.clickTitratedDosage(); + patientPrescription.enterDosage(medicineBaseDosage); + patientPrescription.enterTargetDosage(medicineTargetDosage); + patientPrescription.selectDosageFrequency(medicineFrequency); + cy.submitButton("Submit"); + cy.verifyNotification("Medicine prescribed"); + cy.closeNotification(); + // Administer the medicine in edit form + patientPrescription.clickAdministerButton(); + patientPrescription.enterAdministerDosage(medicineBaseDosage); + patientPrescription.enterAdministerNotes(medicineAdministerNote); + cy.submitButton("Administer Medicine"); + cy.verifyNotification("Medicine(s) administered"); + cy.closeNotification(); + // Verify the Reflection on the Medicine + cy.verifyContentPresence("#medicine-preview", [ + medicineName, + medicineBaseDosage, + medicineTargetDosage, + ]); + patientPrescription.clickReturnToDashboard(); + // Go to medicine tab and administer it again + patientPrescription.visitMedicineTab(); + cy.verifyAndClickElement("#0", medicineName); + cy.submitButton("Administer"); + patientPrescription.enterAdministerDosage(medicineBaseDosage); + cy.submitButton("Administer Medicine"); + cy.verifyNotification("Medicine(s) administered"); + }); + it("Add a new medicine for a patient and verify the duplicate medicine validation", () => { patientPage.visitPatient("Dummy Patient 4"); patientPrescription.visitMedicineTab(); + patientPrescription.visitEditPrescription(); patientPrescription.clickAddPrescription(); patientPrescription.interceptMedibase(); patientPrescription.selectMedicinebox(); - patientPrescription.selectMedicine("DOLO"); - patientPrescription.enterDosage("4"); - patientPrescription.selectDosageFrequency("Twice daily"); + patientPrescription.selectMedicine(medicineName); + patientPrescription.enterDosage(medicineBaseDosage); + patientPrescription.selectDosageFrequency(medicineFrequency); cy.submitButton("Submit"); cy.verifyNotification("Medicine prescribed"); cy.closeNotification(); @@ -34,9 +78,9 @@ describe("Patient Medicine Administration", () => { patientPrescription.clickAddPrescription(); patientPrescription.interceptMedibase(); patientPrescription.selectMedicinebox(); - patientPrescription.selectMedicine("DOLO"); - patientPrescription.enterDosage("4"); - patientPrescription.selectDosageFrequency("Twice daily"); + patientPrescription.selectMedicine(medicineName); + patientPrescription.enterDosage(medicineBaseDosage); + patientPrescription.selectDosageFrequency(medicineFrequency); cy.submitButton("Submit"); cy.verifyNotification( "Medicine - This medicine is already prescribed to this patient. Please discontinue the existing prescription to prescribe again.", diff --git a/cypress/pageobject/Patient/PatientPrescription.ts b/cypress/pageobject/Patient/PatientPrescription.ts index dc4163e4823..a4b92b0a5fa 100644 --- a/cypress/pageobject/Patient/PatientPrescription.ts +++ b/cypress/pageobject/Patient/PatientPrescription.ts @@ -1,8 +1,10 @@ export class PatientPrescription { clickAddPrescription() { - cy.contains("button", "Add Prescription Medication") - .should("be.visible") - .click(); + cy.get("#add-prescription").scrollIntoView(); + cy.verifyAndClickElement( + "#add-prescription", + "Add Prescription Medication", + ); } interceptMedibase() { @@ -16,6 +18,15 @@ export class PatientPrescription { ); } + clickTitratedDosage() { + cy.get("#titrated-dosage").click(); + } + + clickAdministerButton() { + cy.get("#administer-medicine").should("be.visible"); + cy.verifyAndClickElement("#administer-medicine", "Administer"); + } + selectMedicinebox() { cy.get( "div#medicine_object input[placeholder='Select'][role='combobox']", @@ -30,6 +41,18 @@ export class PatientPrescription { cy.get("#base_dosage").type(doseAmount, { force: true }); } + enterAdministerDosage(dosage: string) { + cy.get("#dosage").type(dosage); + } + + enterAdministerNotes(notes: string) { + cy.get("#administration_notes").type(notes); + } + + enterTargetDosage(targetDosage: string) { + cy.get("#target_dosage").type(targetDosage, { force: true }); + } + selectDosageFrequency(frequency: string) { cy.clickAndSelectOption("#frequency", frequency); } @@ -54,7 +77,10 @@ export class PatientPrescription { visitMedicineTab() { cy.get("#consultation_tab_nav").scrollIntoView(); cy.get("#consultation_tab_nav").contains("Medicines").click(); - cy.get("a[href='prescriptions']").first().click(); + } + + visitEditPrescription() { + cy.get("#edit-prescription").click(); } } export default PatientPrescription; diff --git a/src/Components/Medicine/CreatePrescriptionForm.tsx b/src/Components/Medicine/CreatePrescriptionForm.tsx index b918d5781fe..173f5163427 100644 --- a/src/Components/Medicine/CreatePrescriptionForm.tsx +++ b/src/Components/Medicine/CreatePrescriptionForm.tsx @@ -64,6 +64,7 @@ export default function CreatePrescriptionForm(props: { {props.prescription.dosage_type !== "PRN" && props.prescription.prescription_type !== "DISCHARGE" && ( -
+

diff --git a/src/Components/Medicine/MedicineAdministrationSheet/AdministrationEventCell.tsx b/src/Components/Medicine/MedicineAdministrationSheet/AdministrationEventCell.tsx index b13e05b5b58..0949189d96d 100644 --- a/src/Components/Medicine/MedicineAdministrationSheet/AdministrationEventCell.tsx +++ b/src/Components/Medicine/MedicineAdministrationSheet/AdministrationEventCell.tsx @@ -62,6 +62,7 @@ export default function AdministrationEventCell({ />

- {patientData.is_vaccinated ? ( + {patientData.is_vaccinated && ( - ) : ( - )} {patientData.allow_transfer ? ( Date: Tue, 21 May 2024 18:58:33 +0530 Subject: [PATCH 05/11] Remove unwanted covid fields (#7870) --- cypress/e2e/shifting_spec/filter.cy.ts | 7 +- cypress/pageobject/Shift/ShiftFilters.ts | 18 +- src/Common/constants.tsx | 7 - src/Components/Patient/ManagePatients.tsx | 24 -- src/Components/Patient/PatientFilter.tsx | 51 ---- src/Components/Patient/PatientHome.tsx | 23 +- src/Components/Patient/PatientRegister.tsx | 267 +-------------------- src/Components/Patient/models.tsx | 12 +- src/Components/Shifting/BadgesList.tsx | 1 - src/Components/Shifting/Commons.tsx | 2 - src/Components/Shifting/ListFilter.tsx | 17 -- src/Components/Shifting/ListView.tsx | 9 +- src/Components/Shifting/ShiftDetails.tsx | 31 --- src/Components/Shifting/ShiftingBoard.tsx | 8 +- 14 files changed, 13 insertions(+), 464 deletions(-) diff --git a/cypress/e2e/shifting_spec/filter.cy.ts b/cypress/e2e/shifting_spec/filter.cy.ts index a142a657013..82fad9d99e4 100644 --- a/cypress/e2e/shifting_spec/filter.cy.ts +++ b/cypress/e2e/shifting_spec/filter.cy.ts @@ -20,7 +20,7 @@ describe("Shifting section filter", () => { shiftingPage.filterByFacility( "Dummy Shifting", "Dummy Shifting", - "District" + "District", ); shiftingPage.facilityAssignedBadge().should("exist"); @@ -32,13 +32,10 @@ describe("Shifting section filter", () => { "ASC Created Date", "yes", "yes", - "POSITIVE", "no", "MODERATE", - "9999999999" + "9999999999", ); - - shiftingPage.diseaseStatusBadge().should("exist"); shiftingPage.orderingBadge().should("exist"); shiftingPage.breathlessnessLevelBadge().should("exist"); shiftingPage.phoneNumberBadge().should("exist"); diff --git a/cypress/pageobject/Shift/ShiftFilters.ts b/cypress/pageobject/Shift/ShiftFilters.ts index 87d3f33c37e..1f824cebbb3 100644 --- a/cypress/pageobject/Shift/ShiftFilters.ts +++ b/cypress/pageobject/Shift/ShiftFilters.ts @@ -27,10 +27,6 @@ class ShiftingPage { return cy.get("#is-up-shift"); } - diseaseStatusInput() { - return cy.get("#disease-status"); - } - isAntenatalInput() { return cy.get("#is-antenatal"); } @@ -63,10 +59,6 @@ class ShiftingPage { return cy.get("[data-testid='Current facility']"); } - diseaseStatusBadge() { - return cy.get("[data-testid='Disease status']"); - } - orderingBadge() { return cy.get("[data-testid='Ordering']"); } @@ -98,7 +90,7 @@ class ShiftingPage { filterByFacility( origin_facility: string, assigned_facility: string, - assigned_to: string + assigned_to: string, ) { this.originFacilityInput().click().type(origin_facility); cy.get("[role='option']").contains(origin_facility).click(); @@ -116,10 +108,9 @@ class ShiftingPage { ordering: string, emergency: string, is_up_shift: string, - disease_status: string, is_antenatal: string, breathlessness_level: string, - patient_phone_number: string + patient_phone_number: string, ) { this.orderingInput().click(); cy.get("[role='option']").contains(ordering).click(); @@ -130,9 +121,6 @@ class ShiftingPage { this.isUpShiftInput().click(); cy.get("[role='option']").contains(is_up_shift).click(); - this.diseaseStatusInput().click(); - cy.get("[role='option']").contains(disease_status).click(); - this.isAntenatalInput().click(); cy.get("[role='option']").contains(is_antenatal).click(); @@ -148,7 +136,7 @@ class ShiftingPage { created_date_start: string, created_date_end: string, modified_date_start: string, - modified_date_end: string + modified_date_end: string, ) { this.createdDateStartInput().click(); cy.get("[id^='headlessui-popover-panel-'] .care-l-angle-left-b") diff --git a/src/Common/constants.tsx b/src/Common/constants.tsx index 3d6352b3260..10cdbdbcc7f 100644 --- a/src/Common/constants.tsx +++ b/src/Common/constants.tsx @@ -470,13 +470,6 @@ export const SAMPLE_FLOW_RULES = { RECEIVED_AT_LAB: ["COMPLETED"], }; -export const DISEASE_STATUS = [ - "POSITIVE", - "SUSPECTED", - "NEGATIVE", - "RECOVERED", -]; - export const TEST_TYPE = [ "UNK", "ANTIGEN", diff --git a/src/Components/Patient/ManagePatients.tsx b/src/Components/Patient/ManagePatients.tsx index b9a5cc6f34c..e0a3b2d9ee5 100644 --- a/src/Components/Patient/ManagePatients.tsx +++ b/src/Components/Patient/ManagePatients.tsx @@ -164,7 +164,6 @@ export const PatientManager = () => { is_active: !qParams.last_consultation__new_discharge_reason && (qParams.is_active || "True"), - disease_status: qParams.disease_status || undefined, phone_number: qParams.phone_number ? parsePhoneNumber(qParams.phone_number) : undefined, @@ -189,8 +188,6 @@ export const PatientManager = () => { qParams.date_declared_positive_before || undefined, date_declared_positive_after: qParams.date_declared_positive_after || undefined, - date_of_result_before: qParams.date_of_result_before || undefined, - date_of_result_after: qParams.date_of_result_after || undefined, last_consultation_medico_legal_case: qParams.last_consultation_medico_legal_case || undefined, last_consultation_encounter_date_before: @@ -207,7 +204,6 @@ export const PatientManager = () => { qParams.last_consultation__new_discharge_reason || undefined, last_consultation_current_bed__location: qParams.last_consultation_current_bed__location || undefined, - srf_id: qParams.srf_id || undefined, number_of_doses: qParams.number_of_doses || undefined, covin_id: qParams.covin_id || undefined, is_kasp: qParams.is_kasp || undefined, @@ -259,7 +255,6 @@ export const PatientManager = () => { [params.created_date_before, params.created_date_after], [params.modified_date_before, params.modified_date_after], [params.date_declared_positive_before, params.date_declared_positive_after], - [params.date_of_result_before, params.date_of_result_after], [params.last_vaccinated_date_before, params.last_vaccinated_date_after], [ params.last_consultation_encounter_date_before, @@ -595,14 +590,6 @@ export const PatientManager = () => { text={`IP Days: ${dayjs().diff(patient.last_consultation.encounter_date, "day")}`} /> )} - {patient.disease_status === "POSITIVE" && ( - - )} {patient.gender === 2 && patient.is_antenatal && isAntenatal(patient.last_menstruation_start_date) && @@ -624,14 +611,6 @@ export const PatientManager = () => { text="Medical Worker" /> )} - {patient.disease_status === "EXPIRED" && ( - - )} {(!patient.last_consultation || patient.last_consultation?.facility !== patient.facility || (patient.last_consultation?.discharge_date && @@ -1009,7 +988,6 @@ export const PatientManager = () => { ), ordering(), value("Category", "category", getTheCategoryFromId()), - badge("Disease Status", "disease_status"), value( "Respiratory Support", "ventilator_interface", @@ -1027,7 +1005,6 @@ export const PatientManager = () => { paramKey: "last_consultation_admitted_to", }, ...range("Age", "age"), - badge("SRF ID", "srf_id"), { name: "LSG Body", value: qParams.lsgBody ? LocalBodyData?.name || "" : "", @@ -1041,7 +1018,6 @@ export const PatientManager = () => { ), ), badge("Declared Status", "is_declared_positive"), - ...dateRange("Result", "date_of_result"), ...dateRange("Declared positive", "date_declared_positive"), ...dateRange( "Symptoms onset", diff --git a/src/Components/Patient/PatientFilter.tsx b/src/Components/Patient/PatientFilter.tsx index 7c68dce8fbc..fe7a9f4ee06 100644 --- a/src/Components/Patient/PatientFilter.tsx +++ b/src/Components/Patient/PatientFilter.tsx @@ -4,7 +4,6 @@ import FiltersSlideover from "../../CAREUI/interactive/FiltersSlideover"; import { ADMITTED_TO, DISCHARGE_REASONS, - DISEASE_STATUS, FACILITY_TYPES, GENDER_TYPES, PATIENT_FILTER_CATEGORIES, @@ -51,18 +50,14 @@ export default function PatientFilter(props: any) { district_ref: null, date_declared_positive_before: filter.date_declared_positive_before || null, date_declared_positive_after: filter.date_declared_positive_after || null, - date_of_result_before: filter.date_of_result_before || null, - date_of_result_after: filter.date_of_result_after || null, created_date_before: filter.created_date_before || null, created_date_after: filter.created_date_after || null, modified_date_before: filter.modified_date_before || null, modified_date_after: filter.modified_date_after || null, category: filter.category || null, gender: filter.gender || null, - disease_status: filter.disease_status || null, age_min: filter.age_min || null, age_max: filter.age_max || null, - date_of_result: filter.date_of_result || null, date_declared_positive: filter.date_declared_positive || null, last_consultation_medico_legal_case: filter.last_consultation_medico_legal_case || null, @@ -82,7 +77,6 @@ export default function PatientFilter(props: any) { filter.last_consultation_current_bed__location || "", last_consultation__new_discharge_reason: filter.last_consultation__new_discharge_reason || null, - srf_id: filter.srf_id || null, number_of_doses: filter.number_of_doses || null, covin_id: filter.covin_id || null, is_kasp: filter.is_kasp || null, @@ -169,18 +163,14 @@ export default function PatientFilter(props: any) { lsgBody, date_declared_positive_before, date_declared_positive_after, - date_of_result_before, - date_of_result_after, created_date_before, created_date_after, modified_date_before, modified_date_after, category, gender, - disease_status, age_min, age_max, - date_of_result, last_consultation_medico_legal_case, last_consultation_encounter_date_before, last_consultation_encounter_date_after, @@ -191,7 +181,6 @@ export default function PatientFilter(props: any) { last_consultation_current_bed__location, number_of_doses, covin_id, - srf_id, is_kasp, is_declared_positive, last_consultation_symptoms_onset_date_before, @@ -221,13 +210,10 @@ export default function PatientFilter(props: any) { date_declared_positive_after: dateQueryString( date_declared_positive_after, ), - date_of_result_before: dateQueryString(date_of_result_before), - date_of_result_after: dateQueryString(date_of_result_after), created_date_before: dateQueryString(created_date_before), created_date_after: dateQueryString(created_date_after), modified_date_before: dateQueryString(modified_date_before), modified_date_after: dateQueryString(modified_date_after), - date_of_result: dateQueryString(date_of_result), last_consultation_medico_legal_case: last_consultation_medico_legal_case || "", last_consultation_encounter_date_before: dateQueryString( @@ -244,15 +230,12 @@ export default function PatientFilter(props: any) { ), category: category || "", gender: gender || "", - disease_status: - (disease_status == "Show All" ? "" : disease_status) || "", age_min: age_min || "", age_max: age_max || "", last_consultation_admitted_bed_type_list: last_consultation_admitted_bed_type_list || [], last_consultation__new_discharge_reason: last_consultation__new_discharge_reason || "", - srf_id: srf_id || "", number_of_doses: number_of_doses || "", covin_id: covin_id || "", is_kasp: is_kasp || "", @@ -680,18 +663,6 @@ export default function PatientFilter(props: any) {
)} -
- COVID Disease status - o} - value={filterState.disease_status} - onChange={(v) => - setFilterState({ ...filterState, disease_status: v }) - } - /> -
COVID Vaccinated
-
- SRF ID} - value={filterState.srf_id} - onChange={handleFormFieldChange} - errorClassName="hidden" - /> -
- { )} )} - {patientData.contact_with_confirmed_carrier && ( - - )} - {patientData.contact_with_suspected_carrier && ( - - )} {patientData.past_travel && ( { activeShiftingData.results.map((shift: any) => (
-
+
diff --git a/src/Components/Patient/PatientRegister.tsx b/src/Components/Patient/PatientRegister.tsx index c62ad2a8a0d..07e682c137f 100644 --- a/src/Components/Patient/PatientRegister.tsx +++ b/src/Components/Patient/PatientRegister.tsx @@ -2,11 +2,9 @@ import * as Notification from "../../Utils/Notifications.js"; import { BLOOD_GROUPS, - DISEASE_STATUS, GENDER_TYPES, MEDICAL_HISTORY_CHOICES, OCCUPATION_TYPES, - TEST_TYPE, VACCINES, } from "../../Common/constants"; import { @@ -89,11 +87,9 @@ const medicalHistoryChoices = MEDICAL_HISTORY_CHOICES.reduce( [], ); const genderTypes = GENDER_TYPES; -const diseaseStatus = [...DISEASE_STATUS]; const bloodGroups = [...BLOOD_GROUPS]; const occupationTypes = OCCUPATION_TYPES; -const testType = [...TEST_TYPE]; -const vaccines = ["Select", ...VACCINES]; +const vaccines = [...VACCINES]; const initForm: any = { name: "", @@ -103,7 +99,6 @@ const initForm: any = { phone_number: "+91", emergency_phone_number: "+91", blood_group: "", - disease_status: diseaseStatus[2], is_declared_positive: "false", date_declared_positive: new Date(), date_of_birth: null, @@ -121,25 +116,13 @@ const initForm: any = { allergies: "", pincode: "", present_health: "", - contact_with_confirmed_carrier: "false", - contact_with_suspected_carrier: "false", - - estimated_contact_date: null, date_of_return: null, - - number_of_primary_contacts: "", - number_of_secondary_contacts: "", is_antenatal: "false", date_of_test: null, - date_of_result: null, - test_id: "", - srf_id: "", - test_type: testType[0], treatment_plan: false, ongoing_medication: "", designation_of_health_care_worker: "", instituion_of_health_care_worker: "", - cluster_name: "", covin_id: "", is_vaccinated: "false", number_of_doses: "0", @@ -323,14 +306,6 @@ export const PatientRegister = (props: PatientRegisterProps) => { ? parseGenderFromExt(data.gender, state.form.gender) : state.form.gender, }); - field.onChange({ - name: "test_id", - value: data.test_id ? data.test_id : state.form.test_id, - }); - field.onChange({ - name: "srf_id", - value: data.srf_id ? data.srf_id : state.form.srf_id, - }); field.onChange({ name: "state", value: data.district_object @@ -353,28 +328,12 @@ export const PatientRegister = (props: PatientRegisterProps) => { name: "village", value: data.village ? data.village : state.form.village, }); - field.onChange({ - name: "disease_status", - value: data.result - ? data.result.toUpperCase() - : state.form.disease_status, - }); - field.onChange({ - name: "test_type", - value: data.test_type - ? data.test_type.toUpperCase() - : state.form.test_type, - }); field.onChange({ name: "date_of_test", value: data.sample_collection_date ? data.sample_collection_date : state.form.date_of_test, }); - field.onChange({ - name: "date_of_result", - value: data.result_date ? data.result_date : state.form.date_of_result, - }); field.onChange({ name: "phone_number", value: data.mobile_number @@ -416,7 +375,6 @@ export const PatientRegister = (props: PatientRegisterProps) => { 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 @@ -453,19 +411,6 @@ export const PatientRegister = (props: PatientRegisterProps) => { occupation: data.meta_info?.occupation ? parseOccupationFromExt(data.meta_info.occupation) : null, - - number_of_primary_contacts: data.number_of_primary_contacts - ? data.number_of_primary_contacts - : "", - number_of_secondary_contacts: data.number_of_secondary_contacts - ? data.number_of_secondary_contacts - : "", - contact_with_confirmed_carrier: data.contact_with_confirmed_carrier - ? String(data.contact_with_confirmed_carrier) - : "false", - contact_with_suspected_carrier: data.contact_with_suspected_carrier - ? String(data.contact_with_suspected_carrier) - : "false", is_vaccinated: String(data.is_vaccinated), number_of_doses: data.number_of_doses ? String(data.number_of_doses) @@ -645,39 +590,11 @@ export const PatientRegister = (props: PatientRegisterProps) => { errors[field] = "Please enter valid phone number"; } return; - - case "estimated_contact_date": - if ( - JSON.parse(form.contact_with_confirmed_carrier) || - JSON.parse(form.contact_with_suspected_carrier) - ) { - if (!form[field]) { - errors[field] = "Please enter the estimated date of contact"; - } - } - return; - case "cluster_name": - if ( - JSON.parse(form.contact_with_confirmed_carrier) || - JSON.parse(form.contact_with_suspected_carrier) - ) { - if (!form[field]) { - errors[field] = "Please enter the name / cluster of the contact"; - } - } - return; case "blood_group": if (!form[field]) { errors[field] = "Please select a blood group"; } return; - case "number_of_primary_contacts": - case "number_of_secondary_contacts": - if (form[field] && form[field] < 0) { - errors[field] = "Value cannot be negative"; - } - return; - case "is_vaccinated": if (form.is_vaccinated === "true") { if (form.number_of_doses === "0") { @@ -694,23 +611,6 @@ export const PatientRegister = (props: PatientRegisterProps) => { } } return; - - case "date_of_result": - if (form[field] < form.date_of_test) { - errors[field] = - "Date should not be before the date of sample collection"; - } - return; - case "disease_status": - if (form[field] === "POSITIVE") { - if (!form.date_of_test) { - errors["date_of_test"] = "Please fill the date of sample testing"; - } - if (!form.date_of_result) { - errors["date_of_result"] = "Please fill the date of result"; - } - } - return; case "medical_history": if (!form[field].length) { errors[field] = "Please fill the medical history"; @@ -780,18 +680,12 @@ export const PatientRegister = (props: PatientRegisterProps) => { ? dateQueryString(formData.date_of_birth) : null, year_of_birth: ageInputType === "age" ? formData.year_of_birth : null, - disease_status: formData.disease_status, date_of_test: formData.date_of_test ? formData.date_of_test : undefined, - date_of_result: formData.date_of_result - ? formData.date_of_result - : undefined, date_declared_positive: JSON.parse(formData.is_declared_positive) && formData.date_declared_positive ? formData.date_declared_positive : null, - test_id: formData.test_id, - srf_id: formData.srf_id, covin_id: formData.is_vaccinated === "true" ? formData.covin_id : undefined, is_vaccinated: formData.is_vaccinated, @@ -811,7 +705,6 @@ export const PatientRegister = (props: PatientRegisterProps) => { ? formData.last_vaccinated_date : null : null, - test_type: formData.test_type, name: _.startCase(_.toLower(formData.name)), pincode: formData.pincode ? formData.pincode : undefined, gender: Number(formData.gender), @@ -847,33 +740,7 @@ export const PatientRegister = (props: PatientRegisterProps) => { present_health: formData.present_health ? formData.present_health : undefined, - contact_with_confirmed_carrier: JSON.parse( - formData.contact_with_confirmed_carrier, - ), - contact_with_suspected_carrier: JSON.parse( - formData.contact_with_suspected_carrier, - ), - estimated_contact_date: - (JSON.parse(formData.contact_with_confirmed_carrier) || - JSON.parse(formData.contact_with_suspected_carrier)) && - formData.estimated_contact_date - ? formData.estimated_contact_date - : null, - cluster_name: - (JSON.parse(formData.contact_with_confirmed_carrier) || - JSON.parse(formData.contact_with_suspected_carrier)) && - formData.cluster_name - ? formData.cluster_name - : null, allergies: formData.allergies, - number_of_primary_contacts: Number(formData.number_of_primary_contacts) - ? Number(formData.number_of_primary_contacts) - : undefined, - number_of_secondary_contacts: Number( - formData.number_of_secondary_contacts, - ) - ? Number(formData.number_of_secondary_contacts) - : undefined, ongoing_medication: formData.ongoing_medication, is_declared_positive: JSON.parse(formData.is_declared_positive), designation_of_health_care_worker: @@ -1864,7 +1731,7 @@ export const PatientRegister = (props: PatientRegisterProps) => { >
-
+
{ optionValue={(option) => option.value} />
-
- option.label} - optionValue={(option) => option.value} - /> -
-
- option.label} - optionValue={(option) => option.value} - /> -
{
} - -
-
- -
- -
- -
-
-
-
- o} - optionValue={(o) => o} - required - /> -
-
- o} - optionValue={(o) => o} - required - /> -
-
- -
+
+
{
-
- -
-
{ position="LEFT" />
-
- -
- -
- -
-
- -
diff --git a/src/Components/Patient/models.tsx b/src/Components/Patient/models.tsx index 81a06ff659d..b6f6fae7ea2 100644 --- a/src/Components/Patient/models.tsx +++ b/src/Components/Patient/models.tsx @@ -49,7 +49,6 @@ export interface AbhaObject { } export interface PatientModel { - test_id?: string; id?: string; action?: number; name?: string; @@ -87,19 +86,14 @@ export interface PatientModel { sameAddress?: boolean; village?: string; pincode?: number; - contact_with_confirmed_carrier?: boolean; - contact_with_suspected_carrier?: boolean; is_medical_worker?: boolean; designation_of_health_care_worker?: string; instituion_of_health_care_worker?: string; frontline_worker?: string; - estimated_contact_date?: string; past_travel?: boolean; ongoing_medication?: string; countries_travelled?: Array; transit_details?: string; - number_of_primary_contacts?: number; - number_of_secondary_contacts?: number; present_health?: string; has_SARI?: boolean; local_body?: number; @@ -107,11 +101,8 @@ export interface PatientModel { state?: number; nationality?: string; passport_no?: string; - disease_status?: string; - test_type?: string; date_of_test?: string; - date_of_result?: string; - srf_id?: string; + date_of_result?: string; // keeping this to avoid errors in Death report covin_id?: string; is_vaccinated?: boolean; vaccine_name?: string; @@ -124,7 +115,6 @@ export interface PatientModel { review_interval?: number; review_time?: string; date_of_return?: string; - cluster_name?: string; number_of_aged_dependents?: number; number_of_chronic_diseased_dependents?: number; will_donate_blood?: boolean; diff --git a/src/Components/Shifting/BadgesList.tsx b/src/Components/Shifting/BadgesList.tsx index 4490d948cbd..b16d831a96b 100644 --- a/src/Components/Shifting/BadgesList.tsx +++ b/src/Components/Shifting/BadgesList.tsx @@ -48,7 +48,6 @@ export default function BadgesList(props: any) { badge(t("patient_name"), "patient_name"), ...dateRange(t("created"), "created_date"), ...dateRange(t("modified"), "modified_date"), - badge(t("disease_status"), "disease_status"), badge(t("breathlessness_level"), "breathlessness_level"), value( t("assigned_to"), diff --git a/src/Components/Shifting/Commons.tsx b/src/Components/Shifting/Commons.tsx index 57f0b1f8209..284b6e4ce5a 100644 --- a/src/Components/Shifting/Commons.tsx +++ b/src/Components/Shifting/Commons.tsx @@ -19,7 +19,6 @@ export const initialFilterData = { ordering: null, is_kasp: "", assigned_to: "", - disease_status: "", is_antenatal: "", breathlessness_level: "", }; @@ -55,7 +54,6 @@ export const formatFilter = (params: any) => { patient_phone_number: filter.patient_phone_number || undefined, ordering: filter.ordering || undefined, assigned_to: filter.assigned_to || undefined, - disease_status: filter.disease_status || undefined, breathlessness_level: filter.breathlessness_level || undefined, is_kasp: (filter.is_kasp && filter.is_kasp) === "" diff --git a/src/Components/Shifting/ListFilter.tsx b/src/Components/Shifting/ListFilter.tsx index 09393dfdb5c..af98f524ed2 100644 --- a/src/Components/Shifting/ListFilter.tsx +++ b/src/Components/Shifting/ListFilter.tsx @@ -1,6 +1,5 @@ import { BREATHLESSNESS_LEVEL, - DISEASE_STATUS, SHIFTING_FILTER_ORDER, } from "../../Common/constants"; import { DateRange } from "../Common/DateRangeInputV2"; @@ -60,7 +59,6 @@ export default function ListFilter(props: any) { status: filter.status || null, assigned_user_ref: null, assigned_to: filter.assigned_to || "", - disease_status: filter.disease_status || "", is_antenatal: filter.is_antenatal || "", breathlessness_level: filter.breathlessness_level || "", @@ -155,7 +153,6 @@ export default function ListFilter(props: any) { is_kasp, status, assigned_to, - disease_status, is_antenatal, breathlessness_level, } = filterState; @@ -177,7 +174,6 @@ export default function ListFilter(props: any) { is_kasp: is_kasp || "", status: status || "", assigned_to: assigned_to || "", - disease_status: disease_status || "", is_antenatal: is_antenatal || "", breathlessness_level: breathlessness_level || "", }; @@ -340,19 +336,6 @@ export default function ListFilter(props: any) { errorClassName="hidden" /> - option} - optionValue={(option) => option} - onChange={(option) => handleFormFieldChange(option)} - errorClassName="hidden" - /> - (
-
+
diff --git a/src/Components/Shifting/ShiftDetails.tsx b/src/Components/Shifting/ShiftDetails.tsx index 5d29e0c890a..457f110c271 100644 --- a/src/Components/Shifting/ShiftDetails.tsx +++ b/src/Components/Shifting/ShiftDetails.tsx @@ -4,7 +4,6 @@ import { GENDER_TYPES, SHIFTING_CHOICES_PEACETIME, SHIFTING_CHOICES_WARTIME, - TEST_TYPE_CHOICES, } from "../../Common/constants"; import { Link, navigate } from "raviger"; import { lazy, useState } from "react"; @@ -85,10 +84,6 @@ export default function ShiftDetails(props: { id: string }) { const copyContent = (data: any) => { let formattedText = - t("disease_status") + - ": *" + - data?.patient_object?.disease_status + - "* \n" + t("name") + ":" + data?.patient_object?.name + @@ -129,9 +124,6 @@ export default function ShiftDetails(props: { id: string }) { const patientGender = GENDER_TYPES.find( (i) => i.id === patientData?.gender, )?.text; - const testType = TEST_TYPE_CHOICES.find( - (i) => i.id === patientData?.test_type, - )?.text; return (
@@ -150,20 +142,6 @@ export default function ShiftDetails(props: { id: string }) { {t("yes")}
)} -
- - {t("disease_status")}{" "} - - - {patientData?.disease_status} - -
-
- - {t("test_type")}:{" "} - - {(patientData?.test_type && testType) || "-"} -
{t("facility")}:{" "} @@ -319,9 +297,6 @@ export default function ShiftDetails(props: { id: string }) { const patientGender = GENDER_TYPES.find( (i) => i.id === patientData?.gender, )?.text; - const testType = TEST_TYPE_CHOICES.find( - (i) => i.id === patientData?.test_type, - )?.text; return (
@@ -427,12 +402,6 @@ export default function ShiftDetails(props: { id: string }) { formatDateTime(patientData?.date_of_test)) || "-"}
-
- - {t("test_type")}:{" "} - - {(patientData?.test_type && testType) || "-"} -
{/*
diff --git a/src/Components/Shifting/ShiftingBoard.tsx b/src/Components/Shifting/ShiftingBoard.tsx index 088f3d66276..3203b5027f5 100644 --- a/src/Components/Shifting/ShiftingBoard.tsx +++ b/src/Components/Shifting/ShiftingBoard.tsx @@ -82,12 +82,7 @@ const ShiftCard = ({ shift, filter }: any) => { cursor: isDragging ? "grabbing" : "grab", }} > -
+
@@ -316,7 +311,6 @@ export default function ShiftingBoard({ filterProp.ordering, filterProp.is_kasp, filterProp.assigned_to, - filterProp.disease_status, filterProp.is_antenatal, filterProp.breathlessness_level, ]); From a0d29b197fa65c38dfcbd7fc54a2727c9196db36 Mon Sep 17 00:00:00 2001 From: Shivank Kacker Date: Wed, 22 May 2024 10:05:34 +0530 Subject: [PATCH 06/11] Updated discharged patients page (#7853) * updated discharged patients page * fixed filter badges * updated filters * fixed responsiveness and removed geo filters * changed per page limit * switched to 12 * fixes * fixed filters * fix phone number field * changes to filters * removed admitted to --------- Co-authored-by: Mohammed Nihal <57055998+nihal467@users.noreply.github.com> --- src/CAREUI/misc/PaginatedList.tsx | 12 +- .../Facility/DischargedPatientsList.tsx | 358 +++++++++++++++++- src/Components/Patient/PatientFilter.tsx | 134 ++++--- 3 files changed, 428 insertions(+), 76 deletions(-) diff --git a/src/CAREUI/misc/PaginatedList.tsx b/src/CAREUI/misc/PaginatedList.tsx index db68c6f042c..ec270bf8134 100644 --- a/src/CAREUI/misc/PaginatedList.tsx +++ b/src/CAREUI/misc/PaginatedList.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext, useState } from "react"; +import { createContext, useContext, useEffect, useState } from "react"; import { PaginatedResponse, QueryRoute } from "../../Utils/request/types"; import useQuery, { QueryOptions } from "../../Utils/request/useQuery"; import ButtonV2, { @@ -33,6 +33,9 @@ function useContextualized() { interface Props extends QueryOptions> { route: QueryRoute>; perPage?: number; + queryCB?: ( + query: ReturnType>>, + ) => void; children: ( ctx: PaginatedListContext, query: ReturnType>>, @@ -43,6 +46,7 @@ export default function PaginatedList({ children, route, perPage = DEFAULT_PER_PAGE_LIMIT, + queryCB, ...queryOptions }: Props) { const [currentPage, setPage] = useState(1); @@ -57,6 +61,12 @@ export default function PaginatedList({ const items = query.data?.results ?? []; + useEffect(() => { + if (queryCB) { + queryCB(query); + } + }, [query]); + return ( { + if (!qParams.phone_number && phone_number.length >= 13) { + setPhoneNumber("+91"); + } + if ( + !qParams.emergency_phone_number && + emergency_phone_number.length >= 13 + ) { + setEmergencyPhoneNumber("+91"); + } + }, [qParams]); + + const { data: districtData } = useQuery(routes.getDistrict, { + pathParams: { + id: qParams.district, + }, + prefetch: !!Number(qParams.district), + }); + + const { data: LocalBodyData } = useQuery(routes.getLocalBody, { + pathParams: { + id: qParams.lsgBody, + }, + prefetch: !!Number(qParams.lsgBody), + }); + + const { data: facilityAssetLocationData } = useQuery( + routes.getFacilityAssetLocation, + { + pathParams: { + facility_external_id: qParams.facility, + external_id: qParams.last_consultation_current_bed__location, + }, + prefetch: !!qParams.last_consultation_current_bed__location, + }, + ); + + const getTheCategoryFromId = () => { + let category_name; + if (qParams.category) { + category_name = PATIENT_CATEGORIES.find( + (item: any) => qParams.category === item.id, + )?.text; + + return String(category_name); + } else { + return ""; + } + }; + + const getDiagnosisFilterValue = (key: DiagnosesFilterKey) => { + const ids: string[] = (qParams[key] ?? "").split(","); + return ids.map((id) => diagnoses.find((obj) => obj.id == id)?.label ?? id); + }; + + useEffect(() => { + const ids: string[] = []; + FILTER_BY_DIAGNOSES_KEYS.forEach((key) => { + ids.push(...(qParams[key] ?? "").split(",").filter(Boolean)); + }); + const existing = diagnoses.filter(({ id }) => ids.includes(id)); + const objIds = existing.map((o) => o.id); + const diagnosesToBeFetched = ids.filter((id) => !objIds.includes(id)); + getDiagnosesByIds(diagnosesToBeFetched).then((data) => { + const retrieved = data.filter(Boolean) as ICD11DiagnosisModel[]; + setDiagnoses([...existing, ...retrieved]); + }); + }, [ + qParams.diagnoses, + qParams.diagnoses_confirmed, + qParams.diagnoses_provisional, + qParams.diagnoses_unconfirmed, + qParams.diagnoses_differential, + ]); + + const LastAdmittedToTypeBadges = () => { + const badge = (key: string, value: any, id: string) => { + return ( + value && ( + { + const lcat = qParams.last_consultation_admitted_bed_type_list + .split(",") + .filter((x: string) => x != id) + .join(","); + updateQuery({ + ...qParams, + last_consultation_admitted_bed_type_list: lcat, + }); + }} + /> + ) + ); + }; + return qParams.last_consultation_admitted_bed_type_list + .split(",") + .map((id: string) => { + const text = ADMITTED_TO.find((obj) => obj.id == id)?.text; + return badge("Bed Type", text, id); + }); + }; + + const queryField = (name: string, defaultValue?: T) => { + return { + name, + value: qParams[name] || defaultValue, + onChange: (e: FieldChangeEvent) => updateQuery({ [e.name]: e.value }), + className: "grow w-full mb-2", + }; + }; + const [diagnoses, setDiagnoses] = useState([]); + const [phone_number, setPhoneNumber] = useState(""); + const [phoneNumberError, setPhoneNumberError] = useState(""); + const [emergency_phone_number, setEmergencyPhoneNumber] = useState(""); + const [emergencyPhoneNumberError, setEmergencyPhoneNumberError] = + useState(""); + const [count, setCount] = useState(0); + + const setPhoneNum = (phone_number: string) => { + setPhoneNumber(phone_number); + if (phone_number.length >= 13) { + setPhoneNumberError(""); + updateQuery({ phone_number }); + return; + } + + if (phone_number === "+91" || phone_number === "") { + setPhoneNumberError(""); + qParams.phone_number && updateQuery({ phone_number: null }); + return; + } + + setPhoneNumberError("Enter a valid number"); + }; + + const setEmergencyPhoneNum = (emergency_phone_number: string) => { + setEmergencyPhoneNumber(emergency_phone_number); + if (emergency_phone_number.length >= 13) { + setEmergencyPhoneNumberError(""); + updateQuery({ emergency_phone_number }); + return; + } + + if (emergency_phone_number === "+91" || emergency_phone_number === "") { + setEmergencyPhoneNumberError(""); + qParams.emergency_phone_number && + updateQuery({ emergency_phone_number: null }); + return; + } + + setEmergencyPhoneNumberError("Enter a valid number"); + }; return ( - updateQuery({ name: e.value }))} - /> -
+
navigate("/patients")} isTab2Active /> + advancedFilter.setShow(true)} + /> } > +
+
+
+ +
+
+
+
+
+ + +
+
+ setPhoneNum(e.value)} + error={phoneNumberError} + types={["mobile", "landline"]} + /> + setEmergencyPhoneNum(e.value)} + error={emergencyPhoneNumberError} + types={["mobile", "landline"]} + /> +
+
+
+
- [ordering()]} /> + [ + phoneNumber("Primary number", "phone_number"), + phoneNumber("Emergency number", "emergency_phone_number"), + badge("Patient name", "name"), + badge("IP/OP number", "patient_no"), + ...dateRange("Modified", "modified_date"), + ...dateRange("Created", "created_date"), + ...dateRange("Admitted", "last_consultation_encounter_date"), + ...dateRange("Discharged", "last_consultation_discharge_date"), + // Admitted to type badges + badge("No. of vaccination doses", "number_of_doses"), + kasp(), + badge("COWIN ID", "covin_id"), + badge("Is Antenatal", "is_antenatal"), + badge("Review Missed", "review_missed"), + badge( + "Is Medico-Legal Case", + "last_consultation_medico_legal_case", + ), + value( + "Location", + "last_consultation_current_bed__location", + qParams.last_consultation_current_bed__location + ? facilityAssetLocationData?.name || + qParams.last_consultation_current_bed__locations + : "", + ), + badge("Facility Type", "facility_type"), + value( + "District", + "district", + qParams.district ? districtData?.name || "" : "", + ), + ordering(), + value("Category", "category", getTheCategoryFromId()), + badge("Disease Status", "disease_status"), + value( + "Respiratory Support", + "ventilator_interface", + qParams.ventilator_interface && + t(`RESPIRATORY_SUPPORT_${qParams.ventilator_interface}`), + ), + value( + "Gender", + "gender", + parseOptionId(GENDER_TYPES, qParams.gender) || "", + ), + { + name: "Admitted to", + value: ADMITTED_TO[qParams.last_consultation_admitted_to], + paramKey: "last_consultation_admitted_to", + }, + ...range("Age", "age"), + badge("SRF ID", "srf_id"), + { + name: "LSG Body", + value: qParams.lsgBody ? LocalBodyData?.name || "" : "", + paramKey: "lsgBody", + }, + ...FILTER_BY_DIAGNOSES_KEYS.map((key) => + value( + DIAGNOSES_FILTER_LABELS[key], + key, + getDiagnosisFilterValue(key).join(", "), + ), + ), + badge("Declared Status", "is_declared_positive"), + ...dateRange("Result", "date_of_result"), + ...dateRange("Declared positive", "date_declared_positive"), + ...dateRange( + "Symptoms onset", + "last_consultation_symptoms_onset_date", + ), + ...dateRange("Last vaccinated", "last_vaccinated_date"), + { + name: "Telemedicine", + paramKey: "last_consultation_is_telemedicine", + }, + value( + "Discharge Reason", + "last_consultation__new_discharge_reason", + parseOptionId( + DISCHARGE_REASONS, + qParams.last_consultation__new_discharge_reason, + ) || "", + ), + ]} + children={ + qParams.last_consultation_admitted_bed_type_list && + LastAdmittedToTypeBadges() + } + />
{ + setCount(query.data?.count || 0); + console.log(query.data?.count); + }} > {() => ( -
+
{t("discharged_patients_empty")} @@ -99,6 +428,11 @@ const DischargedPatientsList = ({
)} + ); }; diff --git a/src/Components/Patient/PatientFilter.tsx b/src/Components/Patient/PatientFilter.tsx index fe7a9f4ee06..0d8ebaae2b0 100644 --- a/src/Components/Patient/PatientFilter.tsx +++ b/src/Components/Patient/PatientFilter.tsx @@ -345,26 +345,31 @@ export default function PatientFilter(props: any) { />
-
- Admitted to (Bed Types) - o.id} - optionLabel={(o) => o.text} - onChange={(o) => - setFilterState({ - ...filterState, - last_consultation_admitted_bed_type_list: o, - }) - } - /> -
- {["StateAdmin", "StateReadOnlyAdmin"].includes( - authUser.user_type, - ) && ( + {props.dischargePage || ( +
+ + {props.dischargePage && "Last "}Admitted to (Bed Types) + + o.id} + optionLabel={(o) => o.text} + onChange={(o) => + setFilterState({ + ...filterState, + last_consultation_admitted_bed_type_list: o, + }) + } + /> +
+ )} + {(props.dischargePage || + ["StateAdmin", "StateReadOnlyAdmin"].includes( + authUser.user_type, + )) && (
Discharge Reason
-
+ {/*
Is Antenatal o === "true" ? "Antenatal" : "Non-antenatal" } - optionDescription={(o) => - o === "true" - ? "i.e., last menstruation start date is within the last 9 months" - : undefined - } value={filterState.is_antenatal} onChange={(v) => setFilterState({ ...filterState, is_antenatal: v }) } /> -
+
*/}
- Review Missed - (o === "true" ? "Yes" : "No")} - value={filterState.review_missed} - onChange={(v) => - setFilterState({ ...filterState, review_missed: v }) - } - /> + {props.dischargePage || ( + <> + Review Missed + (o === "true" ? "Yes" : "No")} + value={filterState.review_missed} + onChange={(v) => + setFilterState({ ...filterState, review_missed: v }) + } + /> + + )}
Is Medico-Legal Case @@ -568,16 +572,18 @@ export default function PatientFilter(props: any) { className="rounded-md" >
-
- Facility - setFilterWithRef("facility", obj)} - /> -
+ {!props.dischargePage && ( +
+ Facility + setFilterWithRef("facility", obj)} + /> +
+ )} {filterState.facility && (
Location @@ -596,22 +602,24 @@ export default function PatientFilter(props: any) { />
)} -
- Facility type - o.text} - optionValue={(o) => o.text} - value={filterState.facility_type} - onChange={(v) => - setFilterState({ ...filterState, facility_type: v }) - } - optionIcon={() => ( - - )} - /> -
+ {!props.dischargePage && ( +
+ Facility type + o.text} + optionValue={(o) => o.text} + value={filterState.facility_type} + onChange={(v) => + setFilterState({ ...filterState, facility_type: v }) + } + optionIcon={() => ( + + )} + /> +
+ )}
LSG Body
From 25f51d4ad98b8e01fbf6c7c948e9eebe28430e3b Mon Sep 17 00:00:00 2001 From: Shivank Kacker Date: Wed, 22 May 2024 10:06:11 +0530 Subject: [PATCH 07/11] Update Security Policy to redirect to issue page (#7292) * Update Security Policy to redirect to issue page * change url --- SECURITY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index 0b3730ed9ad..03d8dec4837 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -23,4 +23,4 @@ ## Reporting a Vulnerability -Please create a ticket at https://support.coronasafe.network +Please create an issue at https://github.com/coronasafe/care_fe/issues/new From 1fe6eb33177f1bf6cac576276a36ee3be462eb99 Mon Sep 17 00:00:00 2001 From: Ankur Prabhu <85862184+AnkurPrabhu@users.noreply.github.com> Date: Wed, 22 May 2024 10:06:35 +0530 Subject: [PATCH 08/11] Disable the Bed List of Already occupied Beds (front-end change) (#7699) * front-end change * adding suggested changes --- src/Components/Assets/configure/MonitorConfigure.tsx | 3 ++- src/Components/Common/BedSelect.tsx | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Components/Assets/configure/MonitorConfigure.tsx b/src/Components/Assets/configure/MonitorConfigure.tsx index 5053b5b7d02..785b82873de 100644 --- a/src/Components/Assets/configure/MonitorConfigure.tsx +++ b/src/Components/Assets/configure/MonitorConfigure.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { BedSelect } from "../../Common/BedSelect"; import { BedModel } from "../../Facility/models"; -import { AssetData } from "../AssetTypes"; +import { AssetClass, AssetData } from "../AssetTypes"; import * as Notification from "../../../Utils/Notifications.js"; import { Submit } from "../../Common/components/ButtonV2"; import { FieldLabel } from "../../Form/FormFields/FormField"; @@ -73,6 +73,7 @@ export default function MonitorConfigure({ asset }: { asset: AssetData }) { multiple={false} location={asset?.location_object?.id} facility={asset?.location_object?.facility?.id} + not_occupied_by_asset_type={AssetClass.HL7MONITOR} className="w-full" />
diff --git a/src/Components/Common/BedSelect.tsx b/src/Components/Common/BedSelect.tsx index 2e7bf09072e..5c31055a3a4 100644 --- a/src/Components/Common/BedSelect.tsx +++ b/src/Components/Common/BedSelect.tsx @@ -4,6 +4,7 @@ import AutoCompleteAsync from "../Form/AutoCompleteAsync"; import { useTranslation } from "react-i18next"; import request from "../../Utils/request/request"; import routes from "../../Redux/api"; +import { AssetClass } from "../Assets/AssetTypes"; interface BedSelectProps { name: string; @@ -17,6 +18,7 @@ interface BedSelectProps { showAll?: boolean; showNOptions?: number; selected: BedModel | BedModel[] | null; + not_occupied_by_asset_type?: AssetClass; setSelected: (selected: BedModel | BedModel[] | null) => void; } @@ -33,6 +35,7 @@ export const BedSelect = (props: BedSelectProps) => { facility, location, showNOptions = 20, + not_occupied_by_asset_type, } = props; const { t } = useTranslation(); @@ -45,8 +48,8 @@ export const BedSelect = (props: BedSelectProps) => { all: searchAll, facility, location, + not_occupied_by_asset_type, }; - const { data } = await request(routes.listFacilityBeds, { query }); if (unoccupiedOnly) { From 599359e30296efa457596595627253da3898161d Mon Sep 17 00:00:00 2001 From: Ankur Prabhu <85862184+AnkurPrabhu@users.noreply.github.com> Date: Wed, 22 May 2024 10:07:56 +0530 Subject: [PATCH 09/11] Allow only admins to delete a location or a bed (#7671) * allow only admins to delete * adding size change for tooltip * add suggested changes --- src/Components/Facility/BedManagement.tsx | 22 ++++++++++++++----- .../Facility/LocationManagement.tsx | 15 +++++++++++-- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/Components/Facility/BedManagement.tsx b/src/Components/Facility/BedManagement.tsx index 27100bf992b..10624675b5e 100644 --- a/src/Components/Facility/BedManagement.tsx +++ b/src/Components/Facility/BedManagement.tsx @@ -5,13 +5,14 @@ import { ReactElement } from "react"; import * as Notification from "../../Utils/Notifications.js"; import { LOCATION_BED_TYPES } from "../../Common/constants"; import BedDeleteDialog from "./BedDeleteDialog"; -import { NonReadOnlyUsers } from "../../Utils/AuthorizeFor"; +import AuthorizeFor, { NonReadOnlyUsers } from "../../Utils/AuthorizeFor"; import CareIcon from "../../CAREUI/icons/CareIcon"; import Page from "../Common/components/Page"; import request from "../../Utils/request/request"; import routes from "../../Redux/api"; import useQuery from "../../Utils/request/useQuery"; import useFilters from "../../Common/hooks/useFilters"; +import useAuthUser from "../../Common/hooks/useAuthUser"; const Loading = lazy(() => import("../Common/Loading")); interface BedManagementProps { @@ -45,7 +46,7 @@ const BedRow = (props: BedRowProps) => { show: boolean; name: string; }>({ show: false, name: "" }); - + const authUser = useAuthUser(); const handleDelete = (name: string, _id: string) => { setBedData({ show: true, @@ -53,6 +54,10 @@ const BedRow = (props: BedRowProps) => { }); }; + const allowedUser = ["DistrictAdmin", "StateAdmin"].includes( + authUser.user_type, + ); + const handleDeleteConfirm = async () => { const { res } = await request(routes.deleteFacilityBed, { pathParams: { external_id: id }, @@ -126,14 +131,19 @@ const BedRow = (props: BedRowProps) => { handleDelete(name, id)} - authorizeFor={NonReadOnlyUsers} + authorizeFor={AuthorizeFor(["DistrictAdmin", "StateAdmin"])} variant="danger" border ghost className="w-full lg:w-auto" - disabled={isOccupied} - tooltip={isOccupied ? "Bed is occupied" : undefined} - tooltipClassName="w-full lg:w-auto" + tooltip={ + !allowedUser + ? "Contact your admin to delete the bed" + : isOccupied + ? "Bed is occupied" + : undefined + } + tooltipClassName=" text-xs w-full lg:w-auto" > Delete diff --git a/src/Components/Facility/LocationManagement.tsx b/src/Components/Facility/LocationManagement.tsx index 06e0de28d62..18f3af60eb5 100644 --- a/src/Components/Facility/LocationManagement.tsx +++ b/src/Components/Facility/LocationManagement.tsx @@ -1,6 +1,6 @@ import { lazy, useState } from "react"; import ButtonV2, { Cancel } from "../Common/components/ButtonV2"; -import { NonReadOnlyUsers } from "../../Utils/AuthorizeFor"; +import AuthorizeFor, { NonReadOnlyUsers } from "../../Utils/AuthorizeFor"; import CareIcon from "../../CAREUI/icons/CareIcon"; import Page from "../Common/components/Page"; import routes from "../../Redux/api"; @@ -12,6 +12,7 @@ import * as Notification from "../../Utils/Notifications.js"; import ConfirmDialog from "../Common/ConfirmDialog"; import DialogModal from "../Common/Dialog"; import Uptime from "../Common/Uptime"; +import useAuthUser from "../../Common/hooks/useAuthUser"; const Loading = lazy(() => import("../Common/Loading")); @@ -21,10 +22,12 @@ interface Props { interface LocationProps extends LocationModel { facilityId: string; + disabled: boolean; setShowDeletePopup: (e: { open: boolean; name: string; id: string }) => void; } export default function LocationManagement({ facilityId }: Props) { + const authUser = useAuthUser(); const [showDeleteFailModal, setShowDeleteFailModal] = useState({ open: false, id: "", @@ -115,6 +118,11 @@ export default function LocationManagement({ facilityId }: Props) { setShowDeletePopup={setShowDeletePopup} facilityId={facilityId} {...item} + disabled={ + ["DistrictAdmin", "StateAdmin"].includes(authUser.user_type) + ? false + : true + } /> )} @@ -213,6 +221,7 @@ const Location = ({ created_date, modified_date, id, + disabled, setShowDeletePopup, facilityId, }: LocationProps) => ( @@ -286,14 +295,16 @@ const Location = ({
setShowDeletePopup({ open: true, name: name ?? "", id: id ?? "" }) } - authorizeFor={NonReadOnlyUsers} > Delete From 1554ef2fc6af55333199140659468e894b220dda Mon Sep 17 00:00:00 2001 From: Khavin Shankar Date: Wed, 22 May 2024 14:02:17 +0530 Subject: [PATCH 10/11] Show standardized labels for patient categorization (#7875) --- cypress/e2e/patient_spec/patient_consultation.cy.ts | 6 +++--- cypress/e2e/patient_spec/patient_logupdate.cy.ts | 2 +- src/Common/constants.tsx | 4 ++-- src/Components/Facility/models.tsx | 6 +----- src/Components/Patient/ManagePatients.tsx | 9 +-------- 5 files changed, 8 insertions(+), 19 deletions(-) diff --git a/cypress/e2e/patient_spec/patient_consultation.cy.ts b/cypress/e2e/patient_spec/patient_consultation.cy.ts index 8caea111ca1..d5732a6619d 100644 --- a/cypress/e2e/patient_spec/patient_consultation.cy.ts +++ b/cypress/e2e/patient_spec/patient_consultation.cy.ts @@ -66,7 +66,7 @@ describe("Patient Consultation in multiple combination", () => { ); patientConsultationPage.typePatientWeight(patientWeight); patientConsultationPage.typePatientHeight(patientHeight); - patientConsultationPage.selectPatientCategory("Stable"); + patientConsultationPage.selectPatientCategory("Mild"); // icd 11 - 4 diagnosis with one principal patientConsultationPage.selectPatientDiagnosis( diagnosis1, @@ -236,7 +236,7 @@ describe("Patient Consultation in multiple combination", () => { // Asymptomatic cy.searchAndSelectOption("#symptoms", "ASYMPTOMATIC"); // Abnormal category - patientConsultationPage.selectPatientCategory("Abnormal"); + patientConsultationPage.selectPatientCategory("Moderate"); patientConsultationPage.selectPatientSuggestion("Domiciliary Care"); // one ICD-11 diagnosis patientConsultationPage.selectPatientDiagnosis( @@ -299,7 +299,7 @@ describe("Patient Consultation in multiple combination", () => { "SORE THROAT", ]); // Stable category - patientConsultationPage.selectPatientCategory("Stable"); + patientConsultationPage.selectPatientCategory("Mild"); // Date of symptoms patientConsultationPage.selectSymptomsDate( "#symptoms_onset_date", diff --git a/cypress/e2e/patient_spec/patient_logupdate.cy.ts b/cypress/e2e/patient_spec/patient_logupdate.cy.ts index 8cf83b1c5a8..a55b86e464b 100644 --- a/cypress/e2e/patient_spec/patient_logupdate.cy.ts +++ b/cypress/e2e/patient_spec/patient_logupdate.cy.ts @@ -10,7 +10,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { const patientPage = new PatientPage(); const patientLogupdate = new PatientLogupdate(); const domicilaryPatient = "Dummy Patient 11"; - const patientCategory = "Abnormal"; + const patientCategory = "Moderate"; const additionalSymptoms = "ASYMPTOMATIC"; const physicalExamination = "physical examination details"; const otherExamination = "Other"; diff --git a/src/Common/constants.tsx b/src/Common/constants.tsx index 10cdbdbcc7f..de0ab305f48 100644 --- a/src/Common/constants.tsx +++ b/src/Common/constants.tsx @@ -431,8 +431,8 @@ export const PATIENT_CATEGORIES: { twClass: string; }[] = [ { id: "Comfort", text: "Comfort Care", twClass: "patient-comfort" }, - { id: "Stable", text: "Stable", twClass: "patient-stable" }, - { id: "Moderate", text: "Abnormal", twClass: "patient-abnormal" }, + { id: "Stable", text: "Mild", twClass: "patient-stable" }, + { id: "Moderate", text: "Moderate", twClass: "patient-abnormal" }, { id: "Critical", text: "Critical", twClass: "patient-critical" }, ]; diff --git a/src/Components/Facility/models.tsx b/src/Components/Facility/models.tsx index d61d5a9f129..49a2f1346af 100644 --- a/src/Components/Facility/models.tsx +++ b/src/Components/Facility/models.tsx @@ -95,11 +95,7 @@ export interface OptionsType { disabled?: boolean; } -export type PatientCategory = - | "Comfort Care" - | "Stable" - | "Abnormal" - | "Critical"; +export type PatientCategory = "Comfort Care" | "Mild" | "Moderate" | "Critical"; export interface ConsultationModel { encounter_date: string; diff --git a/src/Components/Patient/ManagePatients.tsx b/src/Components/Patient/ManagePatients.tsx index e0a3b2d9ee5..ac716f7bf45 100644 --- a/src/Components/Patient/ManagePatients.tsx +++ b/src/Components/Patient/ManagePatients.tsx @@ -77,13 +77,6 @@ function TabPanel(props: TabPanelProps) { ); } -const PatientCategoryDisplayText: Record = { - "Comfort Care": "COMFORT CARE", - Stable: "STABLE", - Abnormal: "ABNORMAL", - Critical: "CRITICAL", -}; - export const PatientManager = () => { const { t } = useTranslation(); const { @@ -473,7 +466,7 @@ export const PatientManager = () => { className={`absolute inset-y-0 left-0 flex h-full w-1 items-center rounded-l-lg transition-all duration-200 ease-in-out group-hover:w-5 ${categoryClass}`} > - {category ? PatientCategoryDisplayText[category] : "UNKNOWN"} + {category || "UNKNOWN"}
From b39b28f3026feced05535bee2e9f1caa337591f9 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Wed, 22 May 2024 14:13:19 +0530 Subject: [PATCH 11/11] Fixes procedures not working in Edit Consultation form (#7879) fixes #7878 --- src/Components/Facility/ConsultationForm.tsx | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Components/Facility/ConsultationForm.tsx b/src/Components/Facility/ConsultationForm.tsx index ba248b8db6f..7e6fe345f7c 100644 --- a/src/Components/Facility/ConsultationForm.tsx +++ b/src/Components/Facility/ConsultationForm.tsx @@ -125,7 +125,6 @@ type FormDetails = { death_datetime: string; death_confirmed_doctor: string; InvestigationAdvice: InvestigationType[]; - procedures: ProcedureType[]; consent_records: ConsentRecord[]; }; @@ -176,7 +175,6 @@ const initForm: FormDetails = { death_datetime: "", death_confirmed_doctor: "", InvestigationAdvice: [], - procedures: [], consent_records: [], }; @@ -375,7 +373,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { (Array.isArray(data.investigation) && data.investigation) || [], }); handleFormFieldChange({ - name: "procedures", + name: "procedure", value: (Array.isArray(data.procedure) && data.procedure) || [], }); if (data.suggestion === "R") { @@ -593,7 +591,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { } return; case "procedure": { - for (const p of state.form.procedures) { + for (const p of state.form.procedure) { if (!p.procedure?.replace(/\s/g, "").length) { errors[field] = "Procedure field can not be empty"; invalidForm = true; @@ -725,7 +723,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { create_diagnoses: isUpdate ? undefined : state.form.create_diagnoses, treating_physician: state.form.treating_physician, investigation: state.form.InvestigationAdvice, - procedure: state.form.procedures, + procedure: state.form.procedure, patient: patientId, facility: facilityId, referred_to: @@ -1433,11 +1431,11 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { > Procedures { + procedures={state.form.procedure} + setProcedures={(procedure) => { handleFormFieldChange({ - name: "procedures", - value: procedures, + name: "procedure", + value: procedure, }); }} />