From 1cc1ed6bd7b81c23b1cbf88e24e04dc274e3e9db Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Tue, 2 Apr 2024 22:10:12 +0530 Subject: [PATCH 1/4] Migrate ICD11 and Medibase Medicine search to use `useQuery` (#7381) * Migrate ICD11 search to useQuery * Migrate Medicine search to useQuery * remove unused redux actions * remove unused redux actions * fix medibase tests * fix-cypress --- .../patient_spec/patient_consultation.cy.ts | 3 +- cypress/e2e/patient_spec/patient_manage.cy.ts | 3 +- .../pageobject/Patient/PatientPrescription.ts | 8 +- .../AddICD11Diagnosis.tsx | 19 +++-- .../MedibaseAutocompleteFormField.tsx | 23 +++--- src/Redux/actions.tsx | 82 ------------------- src/Redux/api.tsx | 3 +- 7 files changed, 32 insertions(+), 109 deletions(-) diff --git a/cypress/e2e/patient_spec/patient_consultation.cy.ts b/cypress/e2e/patient_spec/patient_consultation.cy.ts index d851e08ed14..d4ed0f1da04 100644 --- a/cypress/e2e/patient_spec/patient_consultation.cy.ts +++ b/cypress/e2e/patient_spec/patient_consultation.cy.ts @@ -99,9 +99,8 @@ describe("Patient Consultation in multiple combination", () => { cy.verifyNotification("Consultation created successfully"); // Below code for the prescription module only present while creating a new consultation patientPrescription.clickAddPrescription(); - patientPrescription.interceptMediaBase(); + patientPrescription.interceptMedibase(); patientPrescription.selectMedicinebox(); - patientPrescription.waitForMediabaseStatusCode(); patientPrescription.selectMedicine(medicineOne); patientPrescription.enterDosage("3"); patientPrescription.selectDosageFrequency("Twice daily"); diff --git a/cypress/e2e/patient_spec/patient_manage.cy.ts b/cypress/e2e/patient_spec/patient_manage.cy.ts index 313b62ba43d..32e6faf880e 100644 --- a/cypress/e2e/patient_spec/patient_manage.cy.ts +++ b/cypress/e2e/patient_spec/patient_manage.cy.ts @@ -49,9 +49,8 @@ describe("Patient", () => { patientPage.visitPatient("Dummy Patient 4"); patientPrescription.visitEditPrescriptionPage(); patientPrescription.clickAddPrescription(); - patientPrescription.interceptMediaBase(); + patientPrescription.interceptMedibase(); patientPrescription.selectMedicinebox(); - patientPrescription.waitForMediabaseStatusCode(); patientPrescription.selectMedicine("DOLO"); patientPrescription.enterDosage("4"); patientPrescription.selectDosageFrequency("Twice daily"); diff --git a/cypress/pageobject/Patient/PatientPrescription.ts b/cypress/pageobject/Patient/PatientPrescription.ts index e5934fcb95a..5c5c64483e4 100644 --- a/cypress/pageobject/Patient/PatientPrescription.ts +++ b/cypress/pageobject/Patient/PatientPrescription.ts @@ -5,8 +5,8 @@ export class PatientPrescription { .click(); } - interceptMediaBase() { - cy.intercept("GET", "**/api/v1/medibase/**").as("getMediaBase"); + interceptMedibase() { + cy.intercept("GET", "**/api/v1/medibase/**").as("getMedibase"); } selectMedicine(medicine: string) { @@ -22,8 +22,8 @@ export class PatientPrescription { ).click(); } - waitForMediabaseStatusCode() { - cy.wait("@getMediaBase").its("response.statusCode").should("eq", 200); + waitForMedibaseStatusCode() { + cy.wait("@getMedibase").its("response.statusCode").should("eq", 200); } enterDosage(doseAmount: string) { diff --git a/src/Components/Diagnosis/ConsultationDiagnosisBuilder/AddICD11Diagnosis.tsx b/src/Components/Diagnosis/ConsultationDiagnosisBuilder/AddICD11Diagnosis.tsx index d405a0611d8..76c32d23a83 100644 --- a/src/Components/Diagnosis/ConsultationDiagnosisBuilder/AddICD11Diagnosis.tsx +++ b/src/Components/Diagnosis/ConsultationDiagnosisBuilder/AddICD11Diagnosis.tsx @@ -6,10 +6,10 @@ import { CreateDiagnosis, ICD11DiagnosisModel, } from "../types"; -import { useAsyncOptions } from "../../../Common/hooks/useAsyncOptions"; -import { listICD11Diagnosis } from "../../../Redux/actions"; import ConditionVerificationStatusMenu from "../ConditionVerificationStatusMenu"; -import { classNames } from "../../../Utils/utils"; +import { classNames, mergeQueryOptions } from "../../../Utils/utils"; +import useQuery from "../../../Utils/request/useQuery"; +import routes from "../../../Redux/api"; interface AddICD11DiagnosisProps { className?: string; @@ -24,8 +24,7 @@ export default function AddICD11Diagnosis(props: AddICD11DiagnosisProps) { const [adding, setAdding] = useState(false); const hasError = !!props.disallowed.find((d) => d?.id === selected?.id); - const { fetchOptions, isLoading, options } = - useAsyncOptions("id"); + const { data, loading, refetch } = useQuery(routes.listICD11Diagnosis); const handleAdd = async (status: CreateDiagnosis["verification_status"]) => { if (!selected) return; @@ -56,11 +55,15 @@ export default function AddICD11Diagnosis(props: AddICD11DiagnosisProps) { placeholder={t("search_icd11_placeholder")} value={selected} onChange={(e) => setSelected(e.value)} - options={options(selected ? [selected] : undefined)} + options={mergeQueryOptions( + selected ? [selected] : [], + data ?? [], + (obj) => obj.id + )} optionLabel={(option) => option.label} optionValue={(option) => option} - onQuery={(query) => fetchOptions(listICD11Diagnosis({ query }))} - isLoading={isLoading} + onQuery={(query) => refetch({ query: { query } })} + isLoading={loading} error={hasError ? t("diagnosis_already_added") : undefined} /> ) { const field = useFormFieldPropsResolver(props); - const { isLoading, options, fetchOptions } = - useAsyncOptions("id"); const [query, setQuery] = useState(""); const [type, setType] = useState(); - useEffect(() => { - fetchOptions(listMedibaseMedicines(query, type)); - }, [query, type]); + const { data, loading } = useQuery(routes.listMedibaseMedicines, { + query: { query, type }, + }); return ( obj.id + )} optionLabel={(option) => option.name.toUpperCase()} optionDescription={(option) => } optionValue={(option) => option} @@ -61,7 +64,7 @@ export default function MedibaseAutocompleteFormField( ) } onQuery={setQuery} - isLoading={isLoading} + isLoading={loading} /> ); diff --git a/src/Redux/actions.tsx b/src/Redux/actions.tsx index edecb7a8c77..01be9a94e05 100644 --- a/src/Redux/actions.tsx +++ b/src/Redux/actions.tsx @@ -1,5 +1,4 @@ import { HCXClaimModel, HCXPolicyModel } from "../Components/HCX/models"; -import { MedibaseMedicine } from "../Components/Medicine/models"; import { fireRequest } from "./fireRequest"; // Facility @@ -7,10 +6,6 @@ export const getUserList = (params: object, key?: string) => { return fireRequest("userList", [], params, null, key); }; -export const getAnyFacility = (id: number | string, key?: string) => { - return fireRequest("getAnyFacility", [], {}, { id: id }, key); -}; - export const getFacilityUsers = (id: string, params?: object) => { return fireRequest( "getFacilityUsers", @@ -68,9 +63,6 @@ export const getAllPatient = (params: object, altKey: string) => { export const getPatient = (pathParam: object) => { return fireRequest("getPatient", [], {}, pathParam); }; -export const patchPatient = (params: object, pathParam: object) => { - return fireRequest("patchPatient", [], params, pathParam); -}; // District/State/Local body/ward export const getDistrictByName = (params: object) => { @@ -145,80 +137,6 @@ export const externalResultList = (params: object, altKey: string) => { return fireRequest("externalResultList", [], params, null, altKey); }; -export const externalResult = (pathParam: object) => { - return fireRequest("externalResult", [], {}, pathParam); -}; - -// Investigation - -export const listInvestigations = ( - params: object, - altKey = "listInvestigations" -) => { - return fireRequest("listInvestigations", [], params, null, altKey); -}; - -export const listInvestigationGroups = (params: object) => { - return fireRequest("listInvestigationGroups", [], params); -}; - -export const createInvestigation = ( - params: object, - consultation_external_id: string -) => { - return fireRequest("createInvestigation", [], params, { - consultation_external_id: consultation_external_id, - }); -}; - -export const getInvestigationSessions = ( - params: object, - consultation_external_id: string -) => { - return fireRequest("getInvestigationSessions", [], params, { - consultation_external_id: consultation_external_id, - }); -}; - -export const getInvestigation = ( - params: object, - consultation_external_id: string -) => { - return fireRequest("getInvestigation", [], params, { - consultation_external_id: consultation_external_id, - }); -}; - -export const getPatientInvestigation = ( - params: object, - patient_external_id: string -) => { - return fireRequest("getPatientInvestigation", [], params, { - patient_external_id: patient_external_id, - }); -}; - -export const editInvestigation = ( - params: object, - consultation_external_id: string -) => { - return fireRequest("editInvestigation", [], params, { - consultation_external_id: consultation_external_id, - }); -}; - -// ICD11 -export const listICD11Diagnosis = (params: object) => { - return fireRequest("listICD11Diagnosis", [], params, null); -}; -// Medibase -export const listMedibaseMedicines = ( - query: string, - type?: MedibaseMedicine["type"] -) => { - return fireRequest("listMedibaseMedicines", [], { query, type }); -}; - // Resource export const downloadResourceRequests = (params: object) => { return fireRequest("downloadResourceRequests", [], params); diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index 08673318b19..e1ed6161cc3 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -68,7 +68,7 @@ import { StateModel, WardModel, } from "../Components/Facility/models"; -import { Prescription } from "../Components/Medicine/models"; +import { MedibaseMedicine, Prescription } from "../Components/Medicine/models"; import { NotificationData, PNconfigData, @@ -1120,6 +1120,7 @@ const routes = { // Medibase listMedibaseMedicines: { path: "/api/v1/medibase/", + TRes: Type(), }, // Resource From e305049c68a9910910d6df8666d53a8674750993 Mon Sep 17 00:00:00 2001 From: Soumya Maheshwari <104725768+soumya-maheshwari@users.noreply.github.com> Date: Tue, 2 Apr 2024 22:24:20 +0530 Subject: [PATCH 2/4] Implemented responsive design for approval letter in resource (#7471) * Implemented responsive design for approval letter in resource * fix cypress --------- Co-authored-by: Mohammed Nihal <57055998+nihal467@users.noreply.github.com> --- cypress/e2e/patient_spec/patient_consultation.cy.ts | 3 ++- cypress/e2e/patient_spec/patient_logupdate.cy.ts | 1 + src/Components/Resource/ResourceDetails.tsx | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cypress/e2e/patient_spec/patient_consultation.cy.ts b/cypress/e2e/patient_spec/patient_consultation.cy.ts index d4ed0f1da04..530ff08b8eb 100644 --- a/cypress/e2e/patient_spec/patient_consultation.cy.ts +++ b/cypress/e2e/patient_spec/patient_consultation.cy.ts @@ -35,7 +35,7 @@ describe("Patient Consultation in multiple combination", () => { const procedureName = "Procedure No 1"; const patientWeight = "70"; const patientHeight = "170"; - const medicineOne = "DOLO"; + const medicineOne = "DOLOLUP"; const patientIpNumber = Math.random().toString(36).substring(7); before(() => { @@ -105,6 +105,7 @@ describe("Patient Consultation in multiple combination", () => { patientPrescription.enterDosage("3"); patientPrescription.selectDosageFrequency("Twice daily"); cy.submitButton("Submit"); + cy.wait(2000); cy.verifyNotification("Medicine prescribed"); patientPrescription.clickReturnToDashboard(); // Verify the data's across the dashboard diff --git a/cypress/e2e/patient_spec/patient_logupdate.cy.ts b/cypress/e2e/patient_spec/patient_logupdate.cy.ts index 143be363efc..859cf623f30 100644 --- a/cypress/e2e/patient_spec/patient_logupdate.cy.ts +++ b/cypress/e2e/patient_spec/patient_logupdate.cy.ts @@ -147,6 +147,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientLogupdate.typeRhythm(patientRhythm); cy.get("#consciousness_level-2").click(); cy.submitButton("Save"); + cy.wait(2000); cy.verifyNotification("Consultation Updates details created successfully"); // Verify the card content cy.get("#basic-information").scrollIntoView(); diff --git a/src/Components/Resource/ResourceDetails.tsx b/src/Components/Resource/ResourceDetails.tsx index 952554c61ef..b50f4c082c3 100644 --- a/src/Components/Resource/ResourceDetails.tsx +++ b/src/Components/Resource/ResourceDetails.tsx @@ -77,7 +77,7 @@ export default function ResourceDetails(props: { id: string }) { const ApprovalLetter = (data: any) => { return (
-
+
APPROVAL LETTER
From da31e66301bf57e0d49e4bc259ae4e17bcc278b1 Mon Sep 17 00:00:00 2001 From: Rashmik <146672184+rash-27@users.noreply.github.com> Date: Wed, 3 Apr 2024 07:43:00 +0530 Subject: [PATCH 3/4] Add Age field in patient registration (#7411) * Add age field in patient registration form * Add test for age input in user registration * fixes based on code review * use updated patient age formatting * calculate age from FE * fix year_of_birth to be non readonly * update cypress so that it works every year * changes according to review * modify cypress tests * update cypress tests * modify trailing text * update cypress tests * update age format in Patientinfocard * changes according to review * update cypress tests * fix cypress issues * fix error in the shift details page * fix type errors in shift details * fix * fix type errors * fix cypress --------- Co-authored-by: rithviknishad Co-authored-by: Mohammed Nihal <57055998+nihal467@users.noreply.github.com> --- .../patient_spec/patient_registration.cy.ts | 3 +- cypress/pageobject/Patient/PatientCreation.ts | 7 + .../ConsultationUpdatesTab.tsx | 13 +- .../Facility/DischargedPatientsList.tsx | 4 +- .../Investigations/Reports/ReportTable.tsx | 14 +- .../Facility/Investigations/Reports/index.tsx | 4 +- src/Components/Facility/TreatmentSummary.tsx | 12 +- src/Components/Patient/ManagePatients.tsx | 4 +- src/Components/Patient/PatientHome.tsx | 17 +- src/Components/Patient/PatientInfoCard.tsx | 11 +- src/Components/Patient/PatientRegister.tsx | 171 ++++++++++++++++-- src/Components/Patient/SampleDetails.tsx | 4 +- src/Components/Patient/models.tsx | 3 +- src/Components/Shifting/ListView.tsx | 8 +- src/Components/Shifting/ShiftDetails.tsx | 21 +-- src/Components/Shifting/ShiftingBoard.tsx | 12 +- .../VitalsMonitor/VitalsMonitorHeader.tsx | 3 +- src/Utils/utils.ts | 64 ++++--- 18 files changed, 263 insertions(+), 112 deletions(-) diff --git a/cypress/e2e/patient_spec/patient_registration.cy.ts b/cypress/e2e/patient_spec/patient_registration.cy.ts index d0ec3d75486..76c3e2b7199 100644 --- a/cypress/e2e/patient_spec/patient_registration.cy.ts +++ b/cypress/e2e/patient_spec/patient_registration.cy.ts @@ -80,7 +80,7 @@ describe("Patient Creation with consultation", () => { // Patient Details page patientPage.typePatientPhoneNumber(phone_number); patientPage.typePatientEmergencyNumber(emergency_phone_number); - patientPage.typePatientDateOfBirth(patientDateOfBirth); + patientPage.typePatientAge(age.toString()); patientPage.typePatientName(patientOneName); patientPage.selectPatientGender(patientOneGender); patientPage.typePatientAddress(patientOneAddress); @@ -146,6 +146,7 @@ describe("Patient Creation with consultation", () => { // change the gender to female and input data to related changed field cy.wait(3000); patientPage.selectPatientGender(patientOneUpdatedGender); + patientPage.typePatientDateOfBirth(patientDateOfBirth); patientPage.clickPatientAntenatalStatusYes(); patientPage.selectPatientBloodGroup(patientOneUpdatedBloodGroup); // Edit the patient consultation , select none medical history and multiple health ID diff --git a/cypress/pageobject/Patient/PatientCreation.ts b/cypress/pageobject/Patient/PatientCreation.ts index 833cd95a3fd..919b16c7c20 100644 --- a/cypress/pageobject/Patient/PatientCreation.ts +++ b/cypress/pageobject/Patient/PatientCreation.ts @@ -46,11 +46,18 @@ export class PatientPage { } typePatientDateOfBirth(dateOfBirth: string) { + cy.clickAndSelectOption("#patientAge", "D.O.B"); cy.get("#date_of_birth").scrollIntoView(); cy.get("#date_of_birth").should("be.visible").click(); cy.get("#date-input").click().type(dateOfBirth); } + typePatientAge(age: string) { + cy.clickAndSelectOption("#patientAge", "Age"); + cy.submitButton("Confirm"); + cy.get("#age").clear().type(age); + } + typePatientName(patientName: string) { cy.get("[data-testid=name] input").click().type(patientName); } diff --git a/src/Components/Facility/ConsultationDetails/ConsultationUpdatesTab.tsx b/src/Components/Facility/ConsultationDetails/ConsultationUpdatesTab.tsx index ecbe157a8aa..2d673a37f74 100644 --- a/src/Components/Facility/ConsultationDetails/ConsultationUpdatesTab.tsx +++ b/src/Components/Facility/ConsultationDetails/ConsultationUpdatesTab.tsx @@ -15,7 +15,11 @@ import { } from "../../../Common/constants"; import PrescriptionsTable from "../../Medicine/PrescriptionsTable"; import Chip from "../../../CAREUI/display/Chip"; -import { formatAge, formatDate, formatDateTime } from "../../../Utils/utils"; +import { + formatDate, + formatDateTime, + formatPatientAge, +} from "../../../Utils/utils"; import ReadMore from "../../Common/components/Readmore"; import DailyRoundsList from "../Consultations/DailyRoundsList"; import EventsList from "./Events/EventsList"; @@ -635,12 +639,7 @@ export const ConsultationUpdatesTab = (props: ConsultationTabProps) => {
Age {" - "} - {props.patientData.age !== undefined // 0 is a valid age, so we need to check for undefined - ? formatAge( - props.patientData.age, - props.patientData.date_of_birth - ) - : "-"} + {formatPatientAge(props.patientData)}
diff --git a/src/Components/Facility/DischargedPatientsList.tsx b/src/Components/Facility/DischargedPatientsList.tsx index e313717c2ae..af5f79cf4c6 100644 --- a/src/Components/Facility/DischargedPatientsList.tsx +++ b/src/Components/Facility/DischargedPatientsList.tsx @@ -7,10 +7,10 @@ import { PatientModel } from "../Patient/models"; import useQuery from "../../Utils/request/useQuery"; import { debounce } from "lodash-es"; import SearchInput from "../Form/SearchInput"; -import { formatAge } from "../../Utils/utils"; import { GENDER_TYPES } from "../../Common/constants"; import CareIcon from "../../CAREUI/icons/CareIcon"; import RecordMeta from "../../CAREUI/display/RecordMeta"; +import { formatPatientAge } from "../../Utils/utils"; import { useTranslation } from "react-i18next"; import SwitchTabs from "../Common/components/SwitchTabs"; @@ -100,7 +100,7 @@ const PatientListItem = ({ patient }: { patient: PatientModel }) => {

{patient.name}

{GENDER_TYPES.find((g) => g.id === patient.gender)?.text} -{" "} - {formatAge(patient.age, patient.date_of_birth)} + {formatPatientAge(patient)}
{ @@ -52,8 +52,7 @@ interface ReportTableProps { title?: string; patientDetails?: { name: string; - age: number; - date_of_birth: string; + age: string; hospitalName: string; }; investigationData: InvestigationResponse; @@ -84,14 +83,7 @@ const ReportTable: FC = ({ {patientDetails && (

Name: {patientDetails.name}

-

- Age:{" "} - {formatAge( - patientDetails.age, - patientDetails.date_of_birth, - true - )} -

+

Age: {patientDetails.age}

Hospital: {patientDetails.hospitalName}

)} diff --git a/src/Components/Facility/Investigations/Reports/index.tsx b/src/Components/Facility/Investigations/Reports/index.tsx index 36a553f9f52..68b3f533b67 100644 --- a/src/Components/Facility/Investigations/Reports/index.tsx +++ b/src/Components/Facility/Investigations/Reports/index.tsx @@ -16,6 +16,7 @@ import AutocompleteMultiSelectFormField from "../../../Form/FormFields/Autocompl import { FieldChangeEvent } from "../../../Form/FormFields/Utils"; import ReportTable from "./ReportTable"; import { Investigation, InvestigationResponse } from "./types"; +import { formatPatientAge } from "../../../../Utils/utils"; const RESULT_PER_PAGE = 14; interface InitialState { @@ -386,8 +387,7 @@ const InvestigationReports = ({ id }: any) => { title={t("report")} patientDetails={{ name: patientData?.name || "", - age: patientData?.age || -1, - date_of_birth: patientData?.date_of_birth || "", + age: patientData ? formatPatientAge(patientData, true) : "", hospitalName: patientData?.facility_object?.name || "", }} /> diff --git a/src/Components/Facility/TreatmentSummary.tsx b/src/Components/Facility/TreatmentSummary.tsx index f3c59791d63..e33a5e3c4f7 100644 --- a/src/Components/Facility/TreatmentSummary.tsx +++ b/src/Components/Facility/TreatmentSummary.tsx @@ -1,5 +1,9 @@ import { GENDER_TYPES } from "../../Common/constants"; -import { formatAge, formatDate, formatDateTime } from "../../Utils/utils"; +import { + formatDate, + formatDateTime, + formatPatientAge, +} from "../../Utils/utils"; import useSlug from "../../Common/hooks/useSlug"; import useAppHistory from "../../Common/hooks/useAppHistory"; import routes from "../../Redux/api"; @@ -66,11 +70,7 @@ const TreatmentSummary = (props: any) => {
Age :{" "} - {formatAge( - patientData?.age ?? 0, - patientData?.date_of_birth ?? "", - true - )} + {patientData ? formatPatientAge(patientData, true) : ""}
OP : {consultationData?.patient_no ?? ""} diff --git a/src/Components/Patient/ManagePatients.tsx b/src/Components/Patient/ManagePatients.tsx index aacad50dc19..ed9c358b9b3 100644 --- a/src/Components/Patient/ManagePatients.tsx +++ b/src/Components/Patient/ManagePatients.tsx @@ -31,7 +31,7 @@ import RecordMeta from "../../CAREUI/display/RecordMeta"; import SearchInput from "../Form/SearchInput"; import SortDropdownMenu from "../Common/SortDropdown"; import SwitchTabs from "../Common/components/SwitchTabs"; -import { formatAge, parsePhoneNumber } from "../../Utils/utils.js"; +import { formatPatientAge, parsePhoneNumber } from "../../Utils/utils.js"; import useFilters from "../../Common/hooks/useFilters"; import { useTranslation } from "react-i18next"; import Page from "../Common/components/Page.js"; @@ -531,7 +531,7 @@ export const PatientManager = () => { > {patient.name} - {formatAge(patient.age, patient.date_of_birth, true)} + {formatPatientAge(patient, true)}
diff --git a/src/Components/Patient/PatientHome.tsx b/src/Components/Patient/PatientHome.tsx index 5c151553379..919a0048e22 100644 --- a/src/Components/Patient/PatientHome.tsx +++ b/src/Components/Patient/PatientHome.tsx @@ -16,9 +16,9 @@ import { SampleTestCard } from "./SampleTestCard"; import Chip from "../../CAREUI/display/Chip"; import { classNames, - formatAge, formatDate, formatDateTime, + formatPatientAge, } from "../../Utils/utils"; import ButtonV2 from "../Common/components/ButtonV2"; import { NonReadOnlyUsers } from "../../Utils/AuthorizeFor"; @@ -342,12 +342,7 @@ export const PatientHome = (props: any) => {

- {patientData.name} -{" "} - {formatAge( - patientData.age, - patientData.date_of_birth, - true - )} + {patientData.name} - {formatPatientAge(patientData, true)}

{patientData.is_vaccinated ? ( @@ -427,10 +422,14 @@ export const PatientHome = (props: any) => {
- Date of Birth + {patientData.date_of_birth + ? "Date of Birth" + : "Year of Birth"}
- {formatDate(patientData?.date_of_birth)} + {patientData.date_of_birth + ? formatDate(patientData.date_of_birth) + : patientData.year_of_birth}
diff --git a/src/Components/Patient/PatientInfoCard.tsx b/src/Components/Patient/PatientInfoCard.tsx index 284341b746c..4a934d32835 100644 --- a/src/Components/Patient/PatientInfoCard.tsx +++ b/src/Components/Patient/PatientInfoCard.tsx @@ -15,7 +15,12 @@ import { useState } from "react"; import CareIcon from "../../CAREUI/icons/CareIcon.js"; import useConfig from "../../Common/hooks/useConfig.js"; import dayjs from "../../Utils/dayjs.js"; -import { classNames, formatDate, formatDateTime } from "../../Utils/utils.js"; +import { + classNames, + formatDate, + formatDateTime, + formatPatientAge, +} from "../../Utils/utils.js"; import ABHAProfileModal from "../ABDM/ABHAProfileModal.js"; import LinkABHANumberModal from "../ABDM/LinkABHANumberModal.js"; import LinkCareContextModal from "../ABDM/LinkCareContextModal.js"; @@ -217,7 +222,7 @@ export default function PatientInfoCard(props: { > {patient.name}
- {patient.age} years • {patient.gender} + {formatPatientAge(patient, true)} • {patient.gender}
{patient.name}
- {patient.age} years • {patient.gender} + {formatPatientAge(patient, true)} • {patient.gender}
diff --git a/src/Components/Patient/PatientRegister.tsx b/src/Components/Patient/PatientRegister.tsx index 4d022b85af2..2a7a42279bb 100644 --- a/src/Components/Patient/PatientRegister.tsx +++ b/src/Components/Patient/PatientRegister.tsx @@ -61,6 +61,7 @@ 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"; +import SelectMenuV2 from "../Form/SelectMenuV2.js"; const Loading = lazy(() => import("../Common/Loading")); const PageTitle = lazy(() => import("../Common/PageTitle")); @@ -92,6 +93,7 @@ const vaccines = ["Select", ...VACCINES]; const initForm: any = { name: "", age: "", + year_of_birth: "", gender: "", phone_number: "+91", emergency_phone_number: "+91", @@ -204,6 +206,9 @@ export const PatientRegister = (props: PatientRegisterProps) => { const [districts, setDistricts] = useState([]); const [localBody, setLocalBody] = useState([]); const [ward, setWard] = useState([]); + const [ageInputType, setAgeInputType] = useState< + "date_of_birth" | "age" | "alert_for_age" + >("date_of_birth"); const [statusDialog, setStatusDialog] = useState<{ show?: boolean; transfer?: boolean; @@ -392,8 +397,14 @@ export const PatientRegister = (props: PatientRegisterProps) => { if (!status.aborted) { if (res?.ok && data) { setPatientName(data.name || ""); + if (!data.date_of_birth) { + setAgeInputType("age"); + } const formData = { ...data, + age: data.year_of_birth + ? new Date().getFullYear() - data.year_of_birth + : "", health_id_number: data.abha_number_object?.abha_number || "", health_id: data.abha_number_object?.health_id || "", nationality: data.nationality ? data.nationality : "India", @@ -464,9 +475,8 @@ export const PatientRegister = (props: PatientRegisterProps) => { ); if (medicalHistory) { formData.medical_history.push(Number(medicalHistory.id)); - (formData as any)[ - `medical_history_${String(medicalHistory.id)}` - ] = i.details; + (formData as any)[`medical_history_${medicalHistory.id}`] = + i.details; } } ); @@ -534,9 +544,34 @@ export const PatientRegister = (props: PatientRegisterProps) => { case "address": case "name": case "gender": - case "date_of_birth": errors[field] = RequiredFieldValidator()(form[field]); return; + case "age": + case "date_of_birth": { + const field = ageInputType === "age" ? "age" : "date_of_birth"; + + errors[field] = RequiredFieldValidator()(form[field]); + if (errors[field]) { + return; + } + + if (field === "age") { + if (form.age < 0) { + errors.age = "Age cannot be less than 0"; + return; + } + + form.date_of_birth = null; + form.year_of_birth = new Date().getFullYear() - form.age; + } + + if (field === "date_of_birth") { + form.age = null; + form.year_of_birth = null; + } + + return; + } case "permanent_address": if (!form.sameAddress) { errors[field] = RequiredFieldValidator()(form[field]); @@ -711,7 +746,11 @@ export const PatientRegister = (props: PatientRegisterProps) => { abha_number: state.form.abha_number, phone_number: parsePhoneNumber(formData.phone_number), emergency_phone_number: parsePhoneNumber(formData.emergency_phone_number), - date_of_birth: dateQueryString(formData.date_of_birth), + date_of_birth: + ageInputType === "date_of_birth" + ? 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 @@ -1138,7 +1177,7 @@ export const PatientRegister = (props: PatientRegisterProps) => { )} <>
- + defaults={id ? state.form : initForm} validate={validateForm} onSubmit={handleSubmit} @@ -1284,18 +1323,116 @@ export const PatientRegister = (props: PatientRegisterProps) => { label={"Name"} />
-
- + + {ageInputType === "age" ? "Age" : "Date of Birth"} + +
+ o.text} + optionValue={(o) => + o.value === "date_of_birth" + ? "date_of_birth" + : "age" + } + value={ageInputType} + onChange={(v) => { + if ( + v === "age" && + ageInputType === "date_of_birth" + ) { + setAgeInputType("alert_for_age"); + return; + } + setAgeInputType(v); + }} + /> +
+ {ageInputType !== "age" ? ( +
+ +
+ ) : ( +
+ +

+ {field("age").value !== "" && + "Year_of_Birth:"} +

+ + {field("age").value !== "" && + new Date().getFullYear() - + field("age").value} + +

+ } + placeholder="Enter the age" + className="col-span-6 sm:col-span-3" + type="number" + min={0} + /> +
+ )} +
+
+ +
+ +
+ While entering a patient's age is an + option, please note that only the year of + birth will be captured from this + information. +
+ + Recommended only when the patient's date + of birth is unknown + +
+ } + action="Confirm" + variant="warning" + show={ageInputType == "alert_for_age"} + onClose={() => setAgeInputType("date_of_birth")} + onConfirm={() => setAgeInputType("age")} + /> +
{ ) : (
Age: - {formatAge(patientData?.age, patientData?.date_of_birth)} + {formatPatientAge(patientData)}
)}
diff --git a/src/Components/Patient/models.tsx b/src/Components/Patient/models.tsx index d62a66dbfca..0ce23f68c2e 100644 --- a/src/Components/Patient/models.tsx +++ b/src/Components/Patient/models.tsx @@ -49,7 +49,6 @@ export interface PatientModel { id?: string; action?: number; name?: string; - age?: number; allow_transfer?: boolean; discharge?: boolean; gender?: number; @@ -113,6 +112,8 @@ export interface PatientModel { number_of_doses?: number; last_vaccinated_date?: string; date_of_birth?: string; + year_of_birth?: number; + readonly death_datetime?: string; blood_group?: string; review_interval?: number; review_time?: string; diff --git a/src/Components/Shifting/ListView.tsx b/src/Components/Shifting/ListView.tsx index e1f0a0545e2..5ad0dfa8b38 100644 --- a/src/Components/Shifting/ListView.tsx +++ b/src/Components/Shifting/ListView.tsx @@ -8,7 +8,7 @@ import { ExportButton } from "../Common/Export"; import ListFilter from "./ListFilter"; import Page from "../Common/components/Page"; import SearchInput from "../Form/SearchInput"; -import { formatAge, formatDateTime } from "../../Utils/utils"; +import { formatDateTime, formatPatientAge } from "../../Utils/utils"; import { formatFilter } from "./Commons"; import { navigate } from "raviger"; @@ -90,11 +90,7 @@ export default function ListView() {
{shift.patient_object.name} -{" "} - {formatAge( - shift.patient_object.age, - shift.patient_object.date_of_birth, - true - )} + {formatPatientAge(shift.patient_object, true)}
{shift.emergency && ( diff --git a/src/Components/Shifting/ShiftDetails.tsx b/src/Components/Shifting/ShiftDetails.tsx index acc3565487a..c3f42456f62 100644 --- a/src/Components/Shifting/ShiftDetails.tsx +++ b/src/Components/Shifting/ShiftDetails.tsx @@ -15,7 +15,7 @@ import { CopyToClipboard } from "react-copy-to-clipboard"; import Page from "../Common/components/Page"; import QRCode from "qrcode.react"; import RecordMeta from "../../CAREUI/display/RecordMeta"; -import { formatAge, formatDateTime } from "../../Utils/utils"; +import { formatDateTime, formatPatientAge } from "../../Utils/utils"; import useConfig from "../../Common/hooks/useConfig"; import { useTranslation } from "react-i18next"; @@ -24,6 +24,7 @@ import routes from "../../Redux/api.js"; import request from "../../Utils/request/request.js"; import { ConsultationModel } from "../Facility/models.js"; import CareIcon from "../../CAREUI/icons/CareIcon.js"; +import { PatientModel } from "../Patient/models.js"; const Loading = lazy(() => import("../Common/Loading")); @@ -94,13 +95,9 @@ export default function ShiftDetails(props: { id: string }) { "\n" + t("age") + ":" + - +( - formatAge( - data?.patient_object?.age, - data?.patient_object?.date_of_birth, - true - ) ?? "-" - ) + + +(data?.patient_object + ? formatPatientAge(data.patient_object, true) + : "") + "\n" + t("origin_facility") + ":" + @@ -128,7 +125,7 @@ export default function ShiftDetails(props: { id: string }) { setIsCopied(false); }, 5000); - const showPatientCard = (patientData: any) => { + const showPatientCard = (patientData: PatientModel) => { const patientGender = GENDER_TYPES.find( (i) => i.id === patientData?.gender )?.text; @@ -185,7 +182,7 @@ export default function ShiftDetails(props: { id: string }) { {t("age")}:{" "} - {formatAge(patientData?.age, patientData?.date_of_birth, true)} + {patientData ? formatPatientAge(patientData, true) : ""}
)} {patientData?.gender === 2 && patientData?.is_antenatal && ( @@ -370,7 +367,7 @@ export default function ShiftDetails(props: { id: string }) { {t("age")}:{" "} - {formatAge(patientData.age, patientData.date_of_birth, true)} + {patientData ? formatPatientAge(patientData, true) : ""}
@@ -794,7 +791,7 @@ export default function ShiftDetails(props: { id: string }) {

{t("details_of_patient")} {showCopyToclipBoard(data)}

- {showPatientCard(data?.patient_object)} + {data?.patient_object && showPatientCard(data?.patient_object)}

{t("comments")}

diff --git a/src/Components/Shifting/ShiftingBoard.tsx b/src/Components/Shifting/ShiftingBoard.tsx index ae94514e6e9..e07fb5d96e1 100644 --- a/src/Components/Shifting/ShiftingBoard.tsx +++ b/src/Components/Shifting/ShiftingBoard.tsx @@ -6,7 +6,11 @@ import { useRef, useState, } from "react"; -import { classNames, formatAge, formatDateTime } from "../../Utils/utils"; +import { + classNames, + formatDateTime, + formatPatientAge, +} from "../../Utils/utils"; import { downloadShiftRequests } from "../../Redux/actions"; import { useDrag, useDrop } from "react-dnd"; @@ -88,11 +92,7 @@ const ShiftCard = ({ shift, filter }: any) => {
{shift.patient_object.name} -{" "} - {formatAge( - shift.patient_object?.age, - shift.patient_object?.age.date_of_birth, - true - )} + {formatPatientAge(shift.patient_object, true)}
{shift.emergency && ( diff --git a/src/Components/VitalsMonitor/VitalsMonitorHeader.tsx b/src/Components/VitalsMonitor/VitalsMonitorHeader.tsx index 8fa272d4058..c3b2888c2f7 100644 --- a/src/Components/VitalsMonitor/VitalsMonitorHeader.tsx +++ b/src/Components/VitalsMonitor/VitalsMonitorHeader.tsx @@ -2,6 +2,7 @@ import { PatientAssetBed } from "../Assets/AssetTypes"; import { Link } from "raviger"; import CareIcon from "../../CAREUI/icons/CareIcon"; import { GENDER_TYPES } from "../../Common/constants"; +import { formatPatientAge } from "../../Utils/utils"; interface VitalsMonitorHeaderProps { patientAssetBed?: PatientAssetBed; @@ -27,7 +28,7 @@ const VitalsMonitorHeader = ({ patientAssetBed }: VitalsMonitorHeaderProps) => { )} {patient && ( - {patient.age}y;{" "} + {`${formatPatientAge(patient)}; `} {GENDER_TYPES.find((g) => g.id === patient.gender)?.icon} )} diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index 4bbc6317d2d..0d350267d1a 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -6,6 +6,7 @@ import { import phoneCodesJson from "../Common/static/countryPhoneAndFlags.json"; import dayjs from "./dayjs"; import { UserModel } from "../Components/Users/models"; +import { PatientModel } from "../Components/Patient/models"; interface ApacheParams { age: number; @@ -396,31 +397,46 @@ export const getCountryCode = (phoneNumber: string) => { return undefined; }; -export const formatAge = ( - age?: number, - date_of_birth?: string, - abbreviated = false -) => { - if (!age && !date_of_birth) return undefined; - if (!age) age = 0; - - const daySuffix = abbreviated ? "d" : "days"; - const monthSuffix = abbreviated ? "mo" : "months"; - const yearSuffix = abbreviated ? "yr" : "years"; - - if (age < 1 && date_of_birth) { - const dob = new Date(date_of_birth); - const today = new Date(); - const diffTime = Math.abs(today.getTime() - dob.getTime()); - const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); - const months = Math.floor(diffDays / 30); - const days = diffDays % 30; - if (months === 0) { - return `${days} ${daySuffix}`; - } - return `${months} ${monthSuffix} ${days} ${daySuffix}`; +const getRelativeDateSuffix = (abbreviated: boolean) => { + return { + day: abbreviated ? "d" : "days", + month: abbreviated ? "mo" : "months", + year: abbreviated ? "yr" : "years", + }; +}; + +export const formatPatientAge = (obj: PatientModel, abbreviated = false) => { + const suffixes = getRelativeDateSuffix(abbreviated); + + const start = dayjs( + obj.date_of_birth + ? new Date(obj.date_of_birth) + : new Date(obj.year_of_birth!, 0, 1) + ); + + const end = dayjs( + obj.death_datetime ? new Date(obj.death_datetime) : new Date() + ); + + const years = end.diff(start, "years"); + if (years) { + return `${years}${suffixes.year}`; + } + + // Skip representing as no. of months/days if we don't know the date of birth + // since it would anyways be inaccurate. + if (!obj.date_of_birth) { + return abbreviated + ? `Born ${obj.year_of_birth}` + : `Born on ${obj.year_of_birth}`; + } + + const month = end.diff(start, "month"); + const day = end.diff(start.add(month, "month"), "day"); + if (month) { + return `${month}${suffixes.month} ${day}${suffixes.day}`; } - return `${age} ${yearSuffix}`; + return `${day}${suffixes.day}`; }; export const scrollTo = (id: string | boolean) => { From b9d084562aba890642c30014023bcb3dad607891 Mon Sep 17 00:00:00 2001 From: Ashraf Mohammed <98876115+AshrafMd-1@users.noreply.github.com> Date: Wed, 3 Apr 2024 13:48:26 +0530 Subject: [PATCH 4/4] Add Cypress test to patient file upload (#7499) * Add cypress tests for file upload * modify the cypress test * flaky test * flaky test in inventory --------- Co-authored-by: Mohammed Nihal <57055998+nihal467@users.noreply.github.com> --- cypress/e2e/facility_spec/inventory.cy.ts | 7 +- .../e2e/patient_spec/patient_detailpage.cy.ts | 106 ++++++++++++++++++ .../pageobject/Facility/FacilityCreation.ts | 2 + .../pageobject/Patient/PatientFileupload.ts | 90 +++++++++++++++ src/Components/Common/HeadedTabs.tsx | 1 + .../Facility/ConsultationDetails/index.tsx | 1 + src/Components/Patient/FileUpload.tsx | 8 +- src/Components/Patient/PatientHome.tsx | 1 + src/Utils/VoiceRecorder.tsx | 3 + 9 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 cypress/e2e/patient_spec/patient_detailpage.cy.ts create mode 100644 cypress/pageobject/Patient/PatientFileupload.ts diff --git a/cypress/e2e/facility_spec/inventory.cy.ts b/cypress/e2e/facility_spec/inventory.cy.ts index e7f1c35cb93..4c0a8cb5371 100644 --- a/cypress/e2e/facility_spec/inventory.cy.ts +++ b/cypress/e2e/facility_spec/inventory.cy.ts @@ -7,6 +7,7 @@ describe("Inventory Management Section", () => { const facilityPage = new FacilityPage(); const loginPage = new LoginPage(); const facilityHome = new FacilityHome(); + const inventoryName = "PPE"; before(() => { loginPage.loginAsDisctrictAdmin(); @@ -51,9 +52,10 @@ describe("Inventory Management Section", () => { it("Add New Inventory | Verify Backend and manual Minimum", () => { // Add Inventory facilityPage.clickManageInventory(); - facilityPage.fillInventoryDetails("PPE", "Add Stock", "5"); + facilityPage.fillInventoryDetails(inventoryName, "Add Stock", "5"); facilityPage.clickAddInventory(); facilityPage.verifySuccessNotification("Inventory created successfully"); + cy.closeNotification(); // Verify Backend minimum badge facilityPage.verifyBadgeWithText(".badge-danger", "Low Stock"); // modify with manual minimum badge @@ -68,7 +70,7 @@ describe("Inventory Management Section", () => { } else { // Otherwise, click the 'set-minimum-quantity' element facilityPage.clickSetMinimumQuantity(); - facilityPage.fillInventoryMinimumDetails("PPE", "1"); + facilityPage.fillInventoryMinimumDetails(inventoryName, "1"); facilityPage.clickSetButton(); facilityPage.verifySuccessNotification( "Minimum quantiy updated successfully" @@ -76,6 +78,7 @@ describe("Inventory Management Section", () => { } }); }); + afterEach(() => { cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/patient_detailpage.cy.ts b/cypress/e2e/patient_spec/patient_detailpage.cy.ts new file mode 100644 index 00000000000..c3bc4b0cf8d --- /dev/null +++ b/cypress/e2e/patient_spec/patient_detailpage.cy.ts @@ -0,0 +1,106 @@ +import { afterEach, before, beforeEach, cy, describe, it } from "local-cypress"; +import LoginPage from "../../pageobject/Login/LoginPage"; +import { PatientPage } from "../../pageobject/Patient/PatientCreation"; +import { PatientFileUpload } from "../../pageobject/Patient/PatientFileupload"; + +describe("Patient Details", () => { + const loginPage = new LoginPage(); + const patientPage = new PatientPage(); + const patientFileUpload = new PatientFileUpload(); + const cypressAudioName = "cypress audio"; + const cypressFileName = "cypress name"; + const newFileName = "cypress modified name"; + const patientNameOne = "Dummy Patient 3"; + const patientNameTwo = "Dummy Patient 4"; + const patientNameThree = "Dummy Patient 5"; + before(() => { + loginPage.loginAsDisctrictAdmin(); + cy.saveLocalStorage(); + }); + + beforeEach(() => { + cy.restoreLocalStorage(); + cy.clearLocalStorage(/filters--.+/); + cy.awaitUrl("/patients"); + }); + + it("Record an Audio and download the file", () => { + // Record an audio + patientPage.visitPatient(patientNameOne); + patientFileUpload.visitPatientDetailsPage(); + patientFileUpload.recordAudio(); + patientFileUpload.typeAudioName(cypressAudioName); + patientFileUpload.clickUploadAudioFile(); + // Verify the audio file is uploaded + cy.verifyNotification("File Uploaded Successfully"); + patientFileUpload.verifyUploadFilePresence(cypressAudioName); + // Verify the download of the audio file + cy.get("button").contains("DOWNLOAD").click(); + cy.verifyNotification("Downloading file..."); + }); + + it("Upload a File and archive it", () => { + // Upload the file + patientPage.visitPatient(patientNameTwo); + patientFileUpload.visitPatientDetailsPage(); + patientFileUpload.uploadFile(); + patientFileUpload.typeFileName(cypressFileName); + patientFileUpload.clickUploadFile(); + // Verify the file is uploaded + cy.verifyNotification("File Uploaded Successfully"); + cy.closeNotification(); + patientFileUpload.verifyUploadFilePresence(cypressFileName); + // Archive the file + patientFileUpload.archiveFile(); + patientFileUpload.clickSaveArchiveFile(); + cy.verifyNotification("File archived successfully"); + patientFileUpload.verifyArchiveFile(cypressFileName); + }); + + it("User-level Based Permission for File Modification", () => { + // Login as Nurse 1 + loginPage.login("dummynurse1", "Coronasafe@123"); + cy.reload(); + // Visit the patient details page + patientPage.visitPatient(patientNameThree); + patientFileUpload.visitPatientDetailsPage(); + // Upload the file + patientFileUpload.uploadFile(); + patientFileUpload.typeFileName(cypressFileName); + patientFileUpload.clickUploadFile(); + // Verify the file is uploaded + cy.verifyNotification("File Uploaded Successfully"); + cy.closeNotification(); + patientFileUpload.verifyUploadFilePresence(cypressFileName); + // Edit the file name + patientFileUpload.verifyFileRenameOption(true); + patientFileUpload.renameFile(newFileName); + patientFileUpload.clickSaveFileName(); + // Verify the file name is changed + cy.verifyNotification("File name changed successfully"); + cy.closeNotification(); + patientFileUpload.verifyUploadFilePresence(newFileName); + // Login as Nurse 2 + loginPage.login("dummynurse2", "Coronasafe@123"); + cy.reload(); + // Verify the file edit option is not available + patientFileUpload.verifyUploadFilePresence(newFileName); + patientFileUpload.verifyFileRenameOption(false); + // Login as District Admin + loginPage.loginAsDisctrictAdmin(); + cy.reload(); + // Verify the file edit option is available + patientFileUpload.verifyUploadFilePresence(newFileName); + patientFileUpload.verifyFileRenameOption(true); + patientFileUpload.renameFile(cypressFileName); + patientFileUpload.clickSaveFileName(); + // Verify the file name is changed + cy.verifyNotification("File name changed successfully"); + cy.closeNotification(); + patientFileUpload.verifyUploadFilePresence(cypressFileName); + }); + + afterEach(() => { + cy.saveLocalStorage(); + }); +}); diff --git a/cypress/pageobject/Facility/FacilityCreation.ts b/cypress/pageobject/Facility/FacilityCreation.ts index 8cc340ce217..733546465a6 100644 --- a/cypress/pageobject/Facility/FacilityCreation.ts +++ b/cypress/pageobject/Facility/FacilityCreation.ts @@ -363,6 +363,7 @@ class FacilityPage { } fillInventoryDetails(name: string, status: string, quantity: string) { + cy.wait(2000); cy.get("div#id").click(); cy.get("div#id ul li").contains(name).click(); cy.get("div#isIncoming").click(); @@ -371,6 +372,7 @@ class FacilityPage { } fillInventoryMinimumDetails(name: string, quantity: string) { + cy.wait(2000); cy.get("div#id").click(); cy.get("div#id ul li").contains(name).click(); cy.get("[name='quantity']").type(quantity); diff --git a/cypress/pageobject/Patient/PatientFileupload.ts b/cypress/pageobject/Patient/PatientFileupload.ts new file mode 100644 index 00000000000..6a970e66578 --- /dev/null +++ b/cypress/pageobject/Patient/PatientFileupload.ts @@ -0,0 +1,90 @@ +import { cy } from "local-cypress"; + +export class PatientFileUpload { + visitPatientDetailsPage() { + cy.get("#patient-details").click(); + cy.get("#upload-patient-files").click(); + } + + typeAudioName(name: string) { + cy.get("#consultation_audio_file").clear(); + cy.get("#consultation_audio_file").click().type(name); + } + + typeFileName(name: string) { + cy.get("#consultation_file").clear(); + cy.get("#consultation_file").click().type(name); + } + + recordAudio() { + cy.get("#record-audio").click(); + cy.wait(5000); + cy.get("#stop-recording").click(); + } + + clickUploadAudioFile() { + cy.intercept("POST", "**/api/v1/files/").as("uploadAudioFile"); + cy.verifyAndClickElement("#upload_audio_file", "Save"); + cy.wait("@uploadAudioFile").its("response.statusCode").should("eq", 201); + } + + verifyUploadFilePresence(fileName: string) { + cy.wait(2000); + cy.get("#file-div").scrollIntoView(); + cy.verifyContentPresence("#file-div", [fileName]); + } + + uploadFile() { + cy.get("#file_upload_patient").selectFile( + "cypress/fixtures/sampleAsset.xlsx", + { force: true } + ); + } + + clickUploadFile() { + cy.intercept("POST", "**/api/v1/files/").as("uploadFile"); + cy.get("#upload_file_button").click(); + cy.wait("@uploadFile").its("response.statusCode").should("eq", 201); + } + + archiveFile() { + cy.get("button").contains("ARCHIVE").click().scrollIntoView(); + cy.get("#editFileName").clear().type("Cypress File Archive"); + } + + clickSaveArchiveFile() { + cy.intercept("PATCH", "**/api/v1/files/**").as("saveArchiveFile"); + cy.submitButton("Proceed"); + cy.wait("@saveArchiveFile").its("response.statusCode").should("eq", 200); + } + + verifyArchiveFile(fileName: string) { + cy.get("#archived-files").click(); + cy.get("button").contains("MORE DETAILS").click().scrollIntoView(); + cy.get("#archive-file-name").should("contain.text", fileName); + cy.get("#archive-file-reason").then(($reason) => { + expect($reason.text().split(":")[1]).to.contain("Cypress File Archive"); + }); + } + + verifyFileRenameOption(status: boolean) { + cy.get("#file-div").then(($fileDiv) => { + if (status) { + expect($fileDiv.text()).to.contain("RENAME"); + } else { + expect($fileDiv.text()).to.not.contain("RENAME"); + } + }); + } + + renameFile(newFileName: string) { + cy.get("button").contains("RENAME").click().scrollIntoView(); + cy.get("#editFileName").clear().type(newFileName); + } + + clickSaveFileName() { + cy.intercept("PATCH", "**/api/v1/files/**").as("saveFileName"); + cy.submitButton("Proceed"); + cy.wait("@saveFileName").its("response.statusCode").should("eq", 200); + } +} diff --git a/src/Components/Common/HeadedTabs.tsx b/src/Components/Common/HeadedTabs.tsx index 1128c274af9..f3535041e56 100644 --- a/src/Components/Common/HeadedTabs.tsx +++ b/src/Components/Common/HeadedTabs.tsx @@ -42,6 +42,7 @@ export default function HeadedTabs(props: headedTabsProps) { {tabs.map((tab) => (
{ Patient Details diff --git a/src/Components/Patient/FileUpload.tsx b/src/Components/Patient/FileUpload.tsx index 0c8cad60005..4f74d9f62f4 100644 --- a/src/Components/Patient/FileUpload.tsx +++ b/src/Components/Patient/FileUpload.tsx @@ -569,6 +569,7 @@ export const FileUpload = (props: FileUploadProps) => { return (
{!item.is_archived ? ( @@ -749,6 +750,7 @@ export const FileUpload = (props: FileUploadProps) => { ) : ( { triggerDownload( url[item.id!], @@ -1431,9 +1433,10 @@ export const FileUpload = (props: FileUploadProps) => {
- {modalDetails?.name} file is archived. + {modalDetails?.name} file is + archived.
-
+
Reason: {modalDetails?.reason}
@@ -1522,6 +1525,7 @@ export const FileUpload = (props: FileUploadProps) => { {audioBlobExists && (
{ handleAudioUpload(); }} diff --git a/src/Components/Patient/PatientHome.tsx b/src/Components/Patient/PatientHome.tsx index 919a0048e22..d78008a204b 100644 --- a/src/Components/Patient/PatientHome.tsx +++ b/src/Components/Patient/PatientHome.tsx @@ -1282,6 +1282,7 @@ export const PatientHome = (props: any) => {
navigate( `/facility/${patientData?.facility}/patient/${id}/files` diff --git a/src/Utils/VoiceRecorder.tsx b/src/Utils/VoiceRecorder.tsx index ab14738df89..471c267e47d 100644 --- a/src/Utils/VoiceRecorder.tsx +++ b/src/Utils/VoiceRecorder.tsx @@ -4,6 +4,7 @@ import ButtonV2 from "../Components/Common/components/ButtonV2"; import CareIcon from "../CAREUI/icons/CareIcon"; import { NonReadOnlyUsers } from "./AuthorizeFor"; import { useTranslation } from "react-i18next"; + export const VoiceRecorder = (props: any) => { const { t } = useTranslation(); const { createAudioBlob, confirmAudioBlobExists, reset, setResetRecording } = @@ -49,6 +50,7 @@ export const VoiceRecorder = (props: any) => { {t("recording") + "..."}
{ stopRecording(); confirmAudioBlobExists(); @@ -67,6 +69,7 @@ export const VoiceRecorder = (props: any) => {
{!audioURL && (