From aa7d7aa4de5c6442a8fc39a62dd7a2884fc21eaf Mon Sep 17 00:00:00 2001 From: Khavin Shankar Date: Mon, 20 May 2024 20:07:41 +0530 Subject: [PATCH] Abdm improvements (#7861) --- .../hooks/useNotificationSubscriptionState.ts | 55 +++++++++++++++++++ src/Components/ABDM/ABDMFacilityRecords.tsx | 15 ++++- src/Components/ABDM/FetchRecordsModal.tsx | 30 +++++++++- .../Facility/PatientNotesSlideover.tsx | 36 ++++-------- 4 files changed, 108 insertions(+), 28 deletions(-) create mode 100644 src/Common/hooks/useNotificationSubscriptionState.ts diff --git a/src/Common/hooks/useNotificationSubscriptionState.ts b/src/Common/hooks/useNotificationSubscriptionState.ts new file mode 100644 index 00000000000..b7927e0cc70 --- /dev/null +++ b/src/Common/hooks/useNotificationSubscriptionState.ts @@ -0,0 +1,55 @@ +import { useEffect, useState } from "react"; +import routes from "../../Redux/api"; +import request from "../../Utils/request/request"; +import useAuthUser from "./useAuthUser"; +import * as Sentry from "@sentry/browser"; + +export type NotificationSubscriptionState = + | "unsubscribed" + | "subscribed" + | "subscribed_on_other_device" + | "subscribed" + | "pending" + | "error"; + +/** + * This is a temporary hook and will be removed in the future. + * + * This hook is used to get the initial notification subscription state of the user. + * @returns NotificationSubscriptionState + */ +export default function useNotificationSubscriptionState( + dependencies: any[] = [], +) { + const { username } = useAuthUser(); + const [subscriptionState, setSubscriptionState] = + useState("pending"); + + const getSubscriptionState = async () => { + try { + const res = await request(routes.getUserPnconfig, { + pathParams: { username }, + }); + + const reg = await navigator.serviceWorker.ready; + const subscription = await reg.pushManager.getSubscription(); + + if (!subscription && !res.data?.pf_endpoint) { + setSubscriptionState("unsubscribed"); + } else if (subscription?.endpoint !== res.data?.pf_endpoint) { + setSubscriptionState("subscribed_on_other_device"); + } else { + setSubscriptionState("subscribed"); + } + } catch (error) { + setSubscriptionState("error"); + Sentry.captureException(error); + } + }; + + useEffect(() => { + getSubscriptionState(); + }, [username, ...dependencies]); + + return subscriptionState; +} diff --git a/src/Components/ABDM/ABDMFacilityRecords.tsx b/src/Components/ABDM/ABDMFacilityRecords.tsx index 8178e037a7f..96040905d6c 100644 --- a/src/Components/ABDM/ABDMFacilityRecords.tsx +++ b/src/Components/ABDM/ABDMFacilityRecords.tsx @@ -4,6 +4,8 @@ import useQuery from "../../Utils/request/useQuery"; import { formatDateTime } from "../../Utils/utils"; import Loading from "../Common/Loading"; import Page from "../Common/components/Page"; +import CareIcon from "../../CAREUI/icons/CareIcon"; +import ButtonV2 from "../Common/components/ButtonV2"; interface IProps { facilityId: string; @@ -21,7 +23,11 @@ const TableHeads = [ ]; export default function ABDMFacilityRecords({ facilityId }: IProps) { - const { data: consentsResult, loading } = useQuery(routes.abha.listConsents, { + const { + data: consentsResult, + loading, + refetch, + } = useQuery(routes.abha.listConsents, { query: { facility: facilityId, ordering: "-created_date" }, }); @@ -53,6 +59,13 @@ export default function ABDMFacilityRecords({ facilityId }: IProps) { scope="col" className="sticky right-0 top-0 py-3.5 pl-3 pr-4 sm:pr-6" > + refetch()} + ghost + className="max-w-2xl text-sm text-gray-700 hover:text-gray-900" + > + Refresh + View diff --git a/src/Components/ABDM/FetchRecordsModal.tsx b/src/Components/ABDM/FetchRecordsModal.tsx index 8273a9763f1..950b69611c4 100644 --- a/src/Components/ABDM/FetchRecordsModal.tsx +++ b/src/Components/ABDM/FetchRecordsModal.tsx @@ -21,6 +21,7 @@ import CircularProgress from "../Common/components/CircularProgress.js"; import CareIcon from "../../CAREUI/icons/CareIcon.js"; import { classNames } from "../../Utils/utils.js"; import { ConsentHIType, ConsentPurpose } from "./types/consent.js"; +import useNotificationSubscriptionState from "../../Common/hooks/useNotificationSubscriptionState.js"; const getDate = (value: any) => value && dayjs(value).isValid() && dayjs(value).toDate(); @@ -46,6 +47,9 @@ export default function FetchRecordsModal({ patient, show, onClose }: IProps) { dayjs().add(30, "day").toDate(), ); const [errors, setErrors] = useState({}); + const notificationSubscriptionState = useNotificationSubscriptionState([ + show, + ]); useMessageListener((data) => { if (data.type === "MESSAGE" && data.from === "patients/on_find") { @@ -62,7 +66,23 @@ export default function FetchRecordsModal({ patient, show, onClose }: IProps) { }); return ( - + + {["unsubscribed", "subscribed_on_other_device"].includes( + notificationSubscriptionState, + ) && ( +

+ {" "} + Notifications needs to be enabled on this device to verify the + patient. +

+ )} +
Request Consent diff --git a/src/Components/Facility/PatientNotesSlideover.tsx b/src/Components/Facility/PatientNotesSlideover.tsx index 3fd46f92f57..e2da270e532 100644 --- a/src/Components/Facility/PatientNotesSlideover.tsx +++ b/src/Components/Facility/PatientNotesSlideover.tsx @@ -12,9 +12,9 @@ import routes from "../../Redux/api"; import { PatientNoteStateType } from "./models"; import useKeyboardShortcut from "use-keyboard-shortcut"; import AutoExpandingTextInputFormField from "../Form/FormFields/AutoExpandingTextInputFormField.js"; -import * as Sentry from "@sentry/browser"; import useAuthUser from "../../Common/hooks/useAuthUser"; import { PATIENT_NOTES_THREADS } from "../../Common/constants.js"; +import useNotificationSubscriptionState from "../../Common/hooks/useNotificationSubscriptionState.js"; interface PatientNotesProps { patientId: string; @@ -25,6 +25,7 @@ interface PatientNotesProps { export default function PatientNotesSlideover(props: PatientNotesProps) { const authUser = useAuthUser(); + const notificationSubscriptionState = useNotificationSubscriptionState(); const [thread, setThread] = useState( authUser.user_type === "Nurse" ? PATIENT_NOTES_THREADS.Nurses @@ -35,32 +36,17 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { const [reload, setReload] = useState(false); const [focused, setFocused] = useState(false); - const { username } = useAuthUser(); - - const intialSubscriptionState = async () => { - try { - const res = await request(routes.getUserPnconfig, { - pathParams: { username }, + useEffect(() => { + if (notificationSubscriptionState === "unsubscribed") { + Notification.Warn({ + msg: "Please subscribe to notifications to get live updates on discussion notes.", + }); + } else if (notificationSubscriptionState === "subscribed_on_other_device") { + Notification.Warn({ + msg: "Please subscribe to notifications on this device to get live updates on discussion notes.", }); - const reg = await navigator.serviceWorker.ready; - const subscription = await reg.pushManager.getSubscription(); - if (!subscription && !res.data?.pf_endpoint) { - Notification.Warn({ - msg: "Please subscribe to notifications to get live updates on discussion notes.", - }); - } else if (subscription?.endpoint !== res.data?.pf_endpoint) { - Notification.Warn({ - msg: "Please subscribe to notifications on this device to get live updates on discussion notes.", - }); - } - } catch (error) { - Sentry.captureException(error); } - }; - - useEffect(() => { - intialSubscriptionState(); - }, []); + }, [notificationSubscriptionState]); const initialData: PatientNoteStateType = { notes: [],