diff --git a/.github/workflows/combine.yml b/.github/workflows/combine.yml
new file mode 100644
index 00000000000..d44461ff5a7
--- /dev/null
+++ b/.github/workflows/combine.yml
@@ -0,0 +1,23 @@
+name: Combine Dependencies
+
+on: workflow_dispatch
+
+# The minimum permissions required to run this Action
+permissions:
+ contents: write
+ pull-requests: write
+ checks: read
+
+jobs:
+ combine-prs:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Combine dependencies
+ id: combine-dependencies
+ uses: github/combine-prs@v5.0.0
+ with:
+ pr_title: Combined dependencies # The title of the pull request to create
+ select_label: dependencies # The label which marks PRs that should be combined.
+ labels: combined-dependencies # Add a label to the combined PR
+ ci_required: "false" # Whether or not CI should be passing to combine the PR
diff --git a/src/Components/ABDM/LinkABHANumberModal.tsx b/src/Components/ABDM/LinkABHANumberModal.tsx
index fe789e6c909..d7dfc9f60c1 100644
--- a/src/Components/ABDM/LinkABHANumberModal.tsx
+++ b/src/Components/ABDM/LinkABHANumberModal.tsx
@@ -194,12 +194,12 @@ const ScanABHAQRSection = ({
body: {
patientId,
hidn: abha?.hidn,
- phr: abha?.hid,
+ phr: (abha?.phr ?? abha?.hid) as string,
name: abha?.name,
gender: abha?.gender,
dob: abha?.dob.replace(/\//g, "-"),
address: abha?.address,
- "dist name": abha?.district_name,
+ "dist name": abha?.["dist name"] ?? abha?.district_name,
"state name": abha?.["state name"],
},
});
diff --git a/src/Components/ABDM/models.ts b/src/Components/ABDM/models.ts
index 957dc9c2d17..9dc362f5cac 100644
--- a/src/Components/ABDM/models.ts
+++ b/src/Components/ABDM/models.ts
@@ -123,10 +123,12 @@ export interface ILinkViaQRBody {
export interface ABHAQRContent {
address: string;
distlgd: string;
- district_name: string;
+ district_name?: string;
dob: string;
- gender: "M";
- hid: string;
+ gender: "M" | "F" | "O";
+ hid?: string;
+ phr?: string;
+ "dist name"?: string;
hidn: string;
mobile: string;
name: string;
diff --git a/src/Components/Facility/FacilityCreate.tsx b/src/Components/Facility/FacilityCreate.tsx
index 8aec0861d62..3138f374e4b 100644
--- a/src/Components/Facility/FacilityCreate.tsx
+++ b/src/Components/Facility/FacilityCreate.tsx
@@ -18,7 +18,7 @@ import {
SelectFormField,
} from "../Form/FormFields/SelectFormField";
import { Popover, Transition } from "@headlessui/react";
-import { Fragment, lazy, useState } from "react";
+import { Fragment, lazy, useEffect, useState } from "react";
import Steps, { Step } from "../Common/Steps";
import {
getPincodeDetails,
@@ -57,6 +57,7 @@ import request from "../../Utils/request/request.js";
import routes from "../../Redux/api.js";
import useQuery from "../../Utils/request/useQuery.js";
import { RequestResult } from "../../Utils/request/types.js";
+import useAuthUser from "../../Common/hooks/useAuthUser";
const Loading = lazy(() => import("../Common/Loading"));
@@ -159,6 +160,21 @@ export const FacilityCreate = (props: FacilityProps) => {
const headerText = !facilityId ? "Create Facility" : "Update Facility";
const buttonText = !facilityId ? "Save Facility" : "Update Facility";
+ const authUser = useAuthUser();
+ useEffect(() => {
+ if (
+ authUser &&
+ authUser.user_type !== "StateAdmin" &&
+ authUser.user_type !== "DistrictAdmin" &&
+ authUser.user_type !== "DistrictLabAdmin"
+ ) {
+ navigate("/facility");
+ Notification.Error({
+ msg: "You don't have permission to perform this action. Contact the admin",
+ });
+ }
+ }, [authUser]);
+
const {
data: districtData,
refetch: districtFetch,
diff --git a/src/Components/Facility/TreatmentSummary.tsx b/src/Components/Facility/TreatmentSummary.tsx
index d0d1658cd61..a83cb64ec66 100644
--- a/src/Components/Facility/TreatmentSummary.tsx
+++ b/src/Components/Facility/TreatmentSummary.tsx
@@ -78,9 +78,13 @@ const TreatmentSummary = (props: any) => {
-
Date of admission :
+ {consultationData?.suggestion === "DC" ? (
+
Date of domiciliary care commenced :
+ ) : (
+
Date of admission :
+ )}
- {consultationData?.admitted
+ {consultationData?.encounter_date
? formatDateTime(consultationData.encounter_date)
: " --/--/----"}
diff --git a/src/Components/Form/FormFields/TextFormField.tsx b/src/Components/Form/FormFields/TextFormField.tsx
index 8f1ee341e34..b2a84e51595 100644
--- a/src/Components/Form/FormFields/TextFormField.tsx
+++ b/src/Components/Form/FormFields/TextFormField.tsx
@@ -100,7 +100,7 @@ const TextFormField = forwardRef((props: TextFormFieldProps, ref) => {
);
const _trailing =
trailing === trailingFocused ? (
-
+
{trailing}
) : (
diff --git a/src/Components/Notifications/NotificationsList.tsx b/src/Components/Notifications/NotificationsList.tsx
index 02cb1f4fa8b..c9e6720e6ad 100644
--- a/src/Components/Notifications/NotificationsList.tsx
+++ b/src/Components/Notifications/NotificationsList.tsx
@@ -46,6 +46,16 @@ const NotificationTile = ({
setIsMarkingAsRead(false);
};
+ const handleMarkAsUnRead = async () => {
+ setIsMarkingAsRead(true);
+ await request(routes.markNotificationAsUnRead, {
+ pathParams: { id: result.id },
+ body: { read_at: null },
+ });
+ setResult({ ...result, read_at: null });
+ setIsMarkingAsRead(false);
+ };
+
const resultUrl = (event: string, data: any) => {
switch (event) {
case "PATIENT_CREATED":
@@ -107,24 +117,33 @@ const NotificationTile = ({
{
event.stopPropagation();
- handleMarkAsRead();
+ if (result.read_at) {
+ handleMarkAsUnRead();
+ } else {
+ handleMarkAsRead();
+ }
}}
>
- {t("mark_as_read")}
+
+ {result.read_at ? t("mark_as_unread") : t("mark_as_read")}
+
{
diagnoses_provisional: qParams.diagnoses_provisional || undefined,
diagnoses_unconfirmed: qParams.diagnoses_unconfirmed || undefined,
diagnoses_differential: qParams.diagnoses_differential || undefined,
+ review_missed: qParams.review_missed || undefined,
};
useEffect(() => {
@@ -944,6 +945,7 @@ export const PatientManager = () => {
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",
diff --git a/src/Components/Patient/PatientFilter.tsx b/src/Components/Patient/PatientFilter.tsx
index 0c0087e6d66..79a04242170 100644
--- a/src/Components/Patient/PatientFilter.tsx
+++ b/src/Components/Patient/PatientFilter.tsx
@@ -100,6 +100,7 @@ export default function PatientFilter(props: any) {
diagnoses_provisional: filter.diagnoses_provisional || null,
diagnoses_unconfirmed: filter.diagnoses_unconfirmed || null,
diagnoses_differential: filter.diagnoses_differential || null,
+ review_missed: filter.review_missed || null,
});
useQuery(routes.getAnyFacility, {
@@ -203,6 +204,7 @@ export default function PatientFilter(props: any) {
diagnoses_provisional,
diagnoses_unconfirmed,
diagnoses_differential,
+ review_missed,
} = filterState;
const data = {
district: district || "",
@@ -270,6 +272,7 @@ export default function PatientFilter(props: any) {
diagnoses_provisional: diagnoses_provisional || "",
diagnoses_unconfirmed: diagnoses_unconfirmed || "",
diagnoses_differential: diagnoses_differential || "",
+ review_missed: review_missed || "",
};
onChange(data);
};
@@ -437,6 +440,18 @@ export default function PatientFilter(props: any) {
}
/>
+
+ Review Missed
+ (o === "true" ? "Yes" : "No")}
+ value={filterState.review_missed}
+ onChange={(v) =>
+ setFilterState({ ...filterState, review_missed: v })
+ }
+ />
+
Is Medico-Legal Case
{consultation?.encounter_date && (
- Admission on:{" "}
+ {consultation.suggestion === "DC"
+ ? "Commenced on: "
+ : "Admitted on: "}
{formatDateTime(consultation?.encounter_date)}
)}
diff --git a/src/Components/Patient/PatientRegister.tsx b/src/Components/Patient/PatientRegister.tsx
index 3be6b985dda..dbc5b869e3e 100644
--- a/src/Components/Patient/PatientRegister.tsx
+++ b/src/Components/Patient/PatientRegister.tsx
@@ -1382,10 +1382,10 @@ export const PatientRegister = (props: PatientRegisterProps) => {
{...field("age")}
errorClassName="hidden"
trailing={
-
-
+
+
{field("age").value !== "" &&
- "Year_of_Birth:"}
+ "Year of Birth:"}
{field("age").value !== "" &&
diff --git a/src/Components/Patient/SampleDetails.tsx b/src/Components/Patient/SampleDetails.tsx
index f66805a3ded..a3d3df95c21 100644
--- a/src/Components/Patient/SampleDetails.tsx
+++ b/src/Components/Patient/SampleDetails.tsx
@@ -265,7 +265,7 @@ export const SampleDetails = ({ id }: DetailRoute) => {
);
};
- if (isLoading) {
+ if (isLoading || !sampleDetails) {
return ;
}
diff --git a/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx b/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx
index 0d5a137becc..61c62f80c70 100644
--- a/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx
+++ b/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx
@@ -151,9 +151,11 @@ export default function HL7PatientVitalsMonitor(props: IVitalsComponentProps) {
>
- No incoming data from HL7 Monitor
+
+ No incoming data from HL7 Monitor
+
(),
},
+ markNotificationAsUnRead: {
+ path: "/api/v1/notification/{id}/",
+ method: "PATCH",
+ TRes: Type(),
+ },
getPublicKey: {
path: "/api/v1/notification/public_key/",
method: "GET",
diff --git a/src/Utils/useRecorder.js b/src/Utils/useRecorder.js
index 5c9dc324ce1..585e557d787 100644
--- a/src/Utils/useRecorder.js
+++ b/src/Utils/useRecorder.js
@@ -7,6 +7,12 @@ const useRecorder = (handleMicPermission) => {
const [recorder, setRecorder] = useState(null);
const [newBlob, setNewBlob] = useState(null);
+ useEffect(() => {
+ if (!isRecording && recorder && audioURL) {
+ setRecorder(null);
+ }
+ }, [isRecording, recorder, audioURL]);
+
useEffect(() => {
// Lazily obtain recorder first time we're recording.
if (recorder === null) {
@@ -32,6 +38,7 @@ const useRecorder = (handleMicPermission) => {
if (isRecording) {
recorder.start();
} else {
+ recorder.stream.getTracks().forEach((i) => i.stop());
recorder.stop();
}
diff --git a/src/Utils/useSegmentedRecorder.ts b/src/Utils/useSegmentedRecorder.ts
index d58ca67bc7c..9434ea8383c 100644
--- a/src/Utils/useSegmentedRecorder.ts
+++ b/src/Utils/useSegmentedRecorder.ts
@@ -2,7 +2,6 @@ import { useState, useEffect } from "react";
import * as Notify from "./Notifications";
const useSegmentedRecording = () => {
- const [audioURL, setAudioURL] = useState("");
const [isRecording, setIsRecording] = useState(false);
const [recorder, setRecorder] = useState(null);
const [audioBlobs, setAudioBlobs] = useState([]);
@@ -11,6 +10,12 @@ const useSegmentedRecording = () => {
const bufferInterval = 1 * 1000;
const splitSizeLimit = 20 * 1000000; // 20MB
+ useEffect(() => {
+ if (!isRecording && recorder && audioBlobs.length > 0) {
+ setRecorder(null);
+ }
+ }, [isRecording, recorder, audioBlobs]);
+
useEffect(() => {
if (recorder === null) {
if (isRecording || restart) {
@@ -37,6 +42,9 @@ const useSegmentedRecording = () => {
} else {
if (restart) {
setIsRecording(true);
+ } else {
+ recorder?.stream?.getTracks()?.forEach((i) => i?.stop());
+ recorder.stop();
}
recorder.state === "recording" && recorder.stop();
}
@@ -96,12 +104,10 @@ const useSegmentedRecording = () => {
};
const resetRecording = () => {
- setAudioURL("");
setAudioBlobs([]);
};
return {
- audioURL,
isRecording,
startRecording,
stopRecording,