Skip to content

Commit

Permalink
Merge branch 'issues/8804/profile-update-validation' of github.com:Ja…
Browse files Browse the repository at this point in the history
…vidSumra/care_fe into issues/8804/profile-update-validation
  • Loading branch information
JavidSumra committed Oct 21, 2024
2 parents 7700550 + cf1fd70 commit 1a2b837
Show file tree
Hide file tree
Showing 15 changed files with 1,863 additions and 954 deletions.
2 changes: 1 addition & 1 deletion cypress/pageobject/Facility/FacilityCreation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class FacilityPage {
}

fillAddress(address: string) {
cy.get("#address").click().clear().type(address);
cy.get("#address").click().type(address);
}

fillPhoneNumber(phoneNumber: string) {
Expand Down
2,237 changes: 1,730 additions & 507 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 0 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
"@radix-ui/react-tooltip": "^1.1.3",
"@sentry/browser": "^8.33.0",
"@yudiel/react-qr-scanner": "^2.0.8",
"axios": "^1.7.7",
"bowser": "^2.11.0",
"browser-image-compression": "^2.0.2",
"browserslist": "^4.24.0",
Expand Down Expand Up @@ -93,10 +92,7 @@
"react-infinite-scroll-component": "^6.1.0",
"react-markdown": "^8.0.7",
"react-pdf": "^9.1.0",
"react-redux": "^8.1.1",
"react-webcam": "^7.2.0",
"redux": "^4.2.1",
"redux-thunk": "^2.4.2",
"rehype-raw": "^6.1.1",
"tailwind-merge": "^2.5.2",
"tailwindcss-animate": "^1.0.7",
Expand Down Expand Up @@ -137,7 +133,6 @@
"postcss": "^8.4.38",
"prettier": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.5",
"redux-devtools-extension": "^2.13.9",
"snyk": "^1.1291.0",
"tailwindcss": "^3.4.3",
"typescript": "^5.4.5",
Expand Down
166 changes: 72 additions & 94 deletions src/Components/Facility/ConsultationDetails/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { GENDER_TYPES } from "../../../Common/constants";
import { ConsultationModel } from "../models";
import { getConsultation, getPatient } from "../../../Redux/actions";
import { statusType, useAbortableEffect } from "../../../Common/utils";
import { useCallback, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import DoctorVideoSlideover from "../DoctorVideoSlideover";
import { PatientModel } from "../../Patient/models";
import {
Expand All @@ -13,7 +11,6 @@ import {
} from "../../../Utils/utils";

import { Link, navigate, useQueryParams } from "raviger";
import { useDispatch } from "react-redux";
import { triggerGoal } from "../../../Integrations/Plausible";
import useAuthUser from "../../../Common/hooks/useAuthUser";
import { ConsultationUpdatesTab } from "./ConsultationUpdatesTab";
Expand All @@ -40,6 +37,7 @@ import request from "../../../Utils/request/request";
import { CameraFeedPermittedUserTypes } from "../../../Utils/permissions";
import Error404 from "../../ErrorPages/404";
import { useTranslation } from "react-i18next";
import useQuery from "../../../Utils/request/useQuery";

import Loading from "@/Components/Common/Loading";
import PageTitle from "@/Components/Common/PageTitle";
Expand Down Expand Up @@ -76,18 +74,11 @@ export const ConsultationDetails = (props: any) => {
if (Object.keys(TABS).includes(props.tab.toUpperCase())) {
tab = props.tab.toUpperCase() as keyof typeof TABS;
}
const dispatch: any = useDispatch();
const [isLoading, setIsLoading] = useState(false);
const [showDoctors, setShowDoctors] = useState(false);
const [qParams, _] = useQueryParams();

const [consultationData, setConsultationData] = useState<ConsultationModel>(
{} as ConsultationModel,
);
const [patientData, setPatientData] = useState<PatientModel>({});
const [abhaNumberData, setAbhaNumberData] = useState<AbhaNumberModel>();
const [activeShiftingData, setActiveShiftingData] = useState<Array<any>>([]);
const [isCameraAttached, setIsCameraAttached] = useState(false);

const getPatientGender = (patientData: any) =>
GENDER_TYPES.find((i) => i.id === patientData.gender)?.text;
Expand All @@ -108,98 +99,86 @@ export const ConsultationDetails = (props: any) => {

const authUser = useAuthUser();

const fetchData = useCallback(
async (status: statusType) => {
setIsLoading(true);
const res = await dispatch(getConsultation(consultationId));
if (!status.aborted) {
if (res?.data) {
const data: ConsultationModel = {
...res.data,
symptoms_text: "",
};
if (facilityId != data.facility || patientId != data.patient) {
navigate(
`/facility/${data.facility}/patient/${data.patient}/consultation/${data?.id}`,
);
}
setConsultationData(data);
const consultationQuery = useQuery(routes.getConsultation, {
pathParams: { id: consultationId },
onResponse: ({ data }) => {
if (!data) {
navigate("/not-found");
return;
}
if (facilityId != data.facility || patientId != data.patient) {
navigate(
`/facility/${data.facility}/patient/${data.patient}/consultation/${data?.id}`,
);
}
},
});

setIsCameraAttached(
await (async () => {
const bedId = data?.current_bed?.bed_object?.id;
if (!bedId) {
return false;
}
const { data: assetBeds } = await request(routes.listAssetBeds, {
query: { bed: bedId },
});
if (!assetBeds) {
return false;
}
return assetBeds.results.some(
(a) => a.asset_object.asset_class === "ONVIF",
);
})(),
);
const consultationData = consultationQuery.data;
const bedId = consultationData?.current_bed?.bed_object?.id;

// Get patient data
const id = res.data.patient;
const patientRes = await dispatch(getPatient({ id }));
if (patientRes?.data) {
const patientGender = getPatientGender(patientRes.data);
const patientAddress = getPatientAddress(patientRes.data);
const patientComorbidities = getPatientComorbidities(
patientRes.data,
);
const data = {
...patientRes.data,
gender: patientGender,
address: patientAddress,
comorbidities: patientComorbidities,
is_declared_positive: patientRes.data.is_declared_positive
? "Yes"
: "No",
is_vaccinated: patientData.is_vaccinated ? "Yes" : "No",
};
const isCameraAttached = useQuery(routes.listAssetBeds, {
prefetch: !!bedId,
query: { bed: bedId },
}).data?.results.some((a) => a.asset_object.asset_class === "ONVIF");

setPatientData(data);
}
const patientDataQuery = useQuery(routes.getPatient, {
pathParams: { id: consultationQuery.data?.patient ?? "" },
prefetch: !!consultationQuery.data?.patient,
onResponse: ({ data }) => {
if (!data) {
return;
}
setPatientData({
...data,
gender: getPatientGender(data),
address: getPatientAddress(data),
comorbidities: getPatientComorbidities(data),
is_declared_positive: data.is_declared_positive ? "Yes" : "No",
is_vaccinated: patientData.is_vaccinated ? "Yes" : "No",
} as any);
},
});

// Get abha number data
const { data: abhaNumberData } = await request(
routes.abdm.abhaNumber.get,
{
pathParams: { abhaNumberId: id ?? "" },
silent: true,
},
);
setAbhaNumberData(abhaNumberData);
const fetchData = useCallback(
async (id: string) => {
// Get abha number data
const { data: abhaNumberData } = await request(
routes.abdm.abhaNumber.get,
{
pathParams: { abhaNumberId: id ?? "" },
silent: true,
},
);
setAbhaNumberData(abhaNumberData);

// Get shifting data
const shiftRequestsQuery = await request(routes.listShiftRequests, {
query: { patient: id },
});
if (shiftRequestsQuery.data?.results) {
setActiveShiftingData(shiftRequestsQuery.data.results);
}
} else {
navigate("/not-found");
}
setIsLoading(false);
// Get shifting data
const shiftRequestsQuery = await request(routes.listShiftRequests, {
query: { patient: id },
});
if (shiftRequestsQuery.data?.results) {
setActiveShiftingData(shiftRequestsQuery.data.results);
}
},
[consultationId, dispatch, patientData.is_vaccinated],
[consultationId, patientData.is_vaccinated],
);

useAbortableEffect((status: statusType) => {
fetchData(status);
useEffect(() => {
const id = patientDataQuery.data?.id;
if (!id) {
return;
}
fetchData(id);
triggerGoal("Patient Consultation Viewed", {
facilityId: facilityId,
consultationId: consultationId,
userId: authUser.id,
});
}, []);
}, [patientDataQuery.data?.id]);

if (!consultationData || patientDataQuery.loading) {
return <Loading />;
}

const consultationTabProps: ConsultationTabProps = {
consultationId,
Expand All @@ -215,10 +194,6 @@ export const ConsultationDetails = (props: any) => {

const SelectedTab = TABS[tab];

if (isLoading) {
return <Loading />;
}

const tabButtonClasses = (selected: boolean) =>
`capitalize min-w-max-content cursor-pointer font-bold whitespace-nowrap ${
selected === true
Expand Down Expand Up @@ -309,7 +284,10 @@ export const ConsultationDetails = (props: any) => {
patient={patientData}
abhaNumber={abhaNumberData}
consultation={consultationData}
fetchPatientData={fetchData}
fetchPatientData={() => {
consultationQuery.refetch();
patientDataQuery.refetch();
}}
consultationId={consultationId}
activeShiftingData={activeShiftingData}
showAbhaProfile={qParams["show-abha-profile"] === "true"}
Expand Down
25 changes: 10 additions & 15 deletions src/Components/Facility/DischargeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import { SelectFormField } from "../Form/FormFields/SelectFormField";
import TextAreaFormField from "../Form/FormFields/TextAreaFormField";
import TextFormField from "../Form/FormFields/TextFormField";
import dayjs from "../../Utils/dayjs";
import { dischargePatient } from "../../Redux/actions";
import { useDispatch } from "react-redux";
import { useMessageListener } from "../../Common/hooks/useMessageListener";
import useQuery from "../../Utils/request/useQuery";
import { useTranslation } from "react-i18next";
Expand All @@ -31,6 +29,7 @@ import routes from "../../Redux/api";
import { EditDiagnosesBuilder } from "../Diagnosis/ConsultationDiagnosisBuilder/ConsultationDiagnosisBuilder";
import Loading from "../Common/Loading";
import careConfig from "@careConfig";
import request from "../../Utils/request/request";

interface PreDischargeFormInterface {
new_discharge_reason: number | null;
Expand Down Expand Up @@ -64,8 +63,6 @@ const DischargeModal = ({
death_datetime = dayjs().format("YYYY-MM-DDTHH:mm"),
}: IProps) => {
const { t } = useTranslation();

const dispatch: any = useDispatch();
const [preDischargeForm, setPreDischargeForm] =
useState<PreDischargeFormInterface>({
new_discharge_reason,
Expand Down Expand Up @@ -175,19 +172,17 @@ const DischargeModal = ({

const submitAction = useConfirmedAction(async () => {
setIsSendingDischargeApi(true);
const dischargeResponse = await dispatch(
dischargePatient(
{
...preDischargeForm,
new_discharge_reason: discharge_reason,
discharge_date: dayjs(preDischargeForm.discharge_date).toISOString(),
},
{ id: consultationData.id },
),
);
const { res } = await request(routes.dischargePatient, {
pathParams: { id: consultationData.id },
body: {
...preDischargeForm,
new_discharge_reason: discharge_reason,
discharge_date: dayjs(preDischargeForm.discharge_date).toISOString(),
},
});
setIsSendingDischargeApi(false);

if (dischargeResponse?.status === 200) {
if (res?.ok) {
Notification.Success({ msg: "Patient Discharged Successfully" });
afterSubmit?.();
}
Expand Down
38 changes: 15 additions & 23 deletions src/Components/Facility/FacilityFilter/DistrictSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useCallback } from "react";
import { useDispatch } from "react-redux";
import { getDistrictByName } from "../../../Redux/actions";
import routes from "../../../Redux/api";
import request from "../../../Utils/request/request";
import AutoCompleteAsync from "../../Form/AutoCompleteAsync";

interface DistrictSelectProps {
Expand All @@ -13,29 +12,22 @@ interface DistrictSelectProps {
}

function DistrictSelect(props: DistrictSelectProps) {
const { name, errors, className, multiple, selected, setSelected } = props;
const dispatchAction: any = useDispatch();

const districtSearch = useCallback(
async (text: string) => {
const params = { limit: 50, offset: 0, district_name: text };
const res = await dispatchAction(getDistrictByName(params));
return res?.data?.results;
},
[dispatchAction],
);

return (
<AutoCompleteAsync
name={name}
multiple={multiple}
selected={selected}
fetchData={districtSearch}
onChange={setSelected}
optionLabel={(option: any) => option.name}
name={props.name}
multiple={props.multiple}
selected={props.selected}
fetchData={async (search) => {
const { data } = await request(routes.getDistrictByName, {
query: { limit: 50, offset: 0, district_name: search },
});
return data?.results;
}}
onChange={props.setSelected}
optionLabel={(option) => option.name}
compareBy="id"
error={errors}
className={className}
error={props.errors}
className={props.className}
/>
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Components/Form/FieldValidators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,13 @@ export const EmailValidator = (message = "Invalid email address") => {
// return RegexValidator(SUPPORT_PHONE_NUMBER_REGEX, message);
// };

// References: https://trai.gov.in/sites/default/files/Recommendations_29052020.pdf
const INDIAN_MOBILE_NUMBER_REGEX = /^(?=^\+91)(^\+91[6-9]\d{9}$)/;
const INTERNATIONAL_MOBILE_NUMBER_REGEX = /^(?!^\+91)(^\+\d{1,3}\d{8,14}$)/;
const MOBILE_NUMBER_REGEX = new RegExp(
`(${INDIAN_MOBILE_NUMBER_REGEX.source})|(${INTERNATIONAL_MOBILE_NUMBER_REGEX.source})`,
);
const INDIAN_LANDLINE_NUMBER_REGEX = /^\+91[2-9]\d{7,9}$/;
const INDIAN_LANDLINE_NUMBER_REGEX = /^\+91[2-9]\d{9}$/;
const INDIAN_SUPPORT_NUMBER_REGEX = /^(1800|1860)\d{6,7}$/;

const PHONE_NUMBER_REGEX_MAP = {
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Form/FormFields/PhoneNumberFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export default function PhoneNumberFormField(props: Props) {
<FormField
field={{
...field,
error: field.error || error,
error: field.error ?? error,
labelSuffix: field.labelSuffix || (
<PhoneNumberTypesHelp types={props.types} />
),
Expand Down
Loading

0 comments on commit 1a2b837

Please sign in to comment.