diff --git a/package-lock.json b/package-lock.json index baa3205a234..0da53d597ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23708,4 +23708,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/Components/Notifications/NoticeBoard.tsx b/src/Components/Notifications/NoticeBoard.tsx index 7fd16efb3cf..8ad3afba0f8 100644 --- a/src/Components/Notifications/NoticeBoard.tsx +++ b/src/Components/Notifications/NoticeBoard.tsx @@ -1,43 +1,23 @@ -import { useEffect, useState } from "react"; -import { useDispatch } from "react-redux"; -import { getNotifications } from "../../Redux/actions"; import Page from "../Common/components/Page"; import Loading from "../Common/Loading"; import { formatDateTime } from "../../Utils/utils"; import { useTranslation } from "react-i18next"; import CareIcon from "../../CAREUI/icons/CareIcon"; +import useQuery from "../../Utils/request/useQuery"; +import routes from "../../Redux/api"; export const NoticeBoard = () => { - const dispatch: any = useDispatch(); - const [isLoading, setIsLoading] = useState(true); - const [data, setData] = useState([]); const { t } = useTranslation(); - - useEffect(() => { - setIsLoading(true); - dispatch( - getNotifications( - { offset: 0, event: "MESSAGE", medium_sent: "SYSTEM" }, - new Date().getTime().toString() - ) - ) - .then((res: any) => { - if (res && res.data) { - setData(res.data.results); - } - setIsLoading(false); - }) - .catch(() => { - setIsLoading(false); - }); - }, [dispatch]); + const { data, loading } = useQuery(routes.getNotifications, { + query: { offset: 0, event: "MESSAGE", medium_sent: "SYSTEM" }, + }); let notices; - if (data?.length) { + if (data?.results.length) { notices = (
- {data.map((item) => ( + {data.results.map((item) => (
{ ); } - if (isLoading) return ; + if (loading) return ; return (
{notices}
diff --git a/src/Components/Notifications/NotificationsList.tsx b/src/Components/Notifications/NotificationsList.tsx index 5f124516a14..864208a432f 100644 --- a/src/Components/Notifications/NotificationsList.tsx +++ b/src/Components/Notifications/NotificationsList.tsx @@ -1,13 +1,5 @@ import { navigate } from "raviger"; import { useEffect, useState } from "react"; -import { useDispatch } from "react-redux"; -import { - getNotifications, - markNotificationAsRead, - getUserPnconfig, - updateUserPnconfig, - getPublicKey, -} from "../../Redux/actions"; import Spinner from "../Common/Spinner"; import { NOTIFICATION_EVENTS } from "../../Common/constants"; import { Error } from "../../Utils/Notifications.js"; @@ -24,6 +16,8 @@ import SelectMenuV2 from "../Form/SelectMenuV2"; import { useTranslation } from "react-i18next"; import CircularProgress from "../Common/components/CircularProgress"; import useAuthUser from "../../Common/hooks/useAuthUser"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; const RESULT_LIMIT = 14; @@ -38,14 +32,16 @@ const NotificationTile = ({ onClickCB, setShowNotifications, }: NotificationTileProps) => { - const dispatch: any = useDispatch(); const [result, setResult] = useState(notification); const [isMarkingAsRead, setIsMarkingAsRead] = useState(false); const { t } = useTranslation(); const handleMarkAsRead = async () => { setIsMarkingAsRead(true); - await dispatch(markNotificationAsRead(result.id)); + await request(routes.markNotificationAsRead, { + pathParams: { id: result.id }, + body: { read_at: new Date() }, + }); setResult({ ...result, read_at: new Date() }); setIsMarkingAsRead(false); }; @@ -153,7 +149,6 @@ export default function NotificationsList({ handleOverflow, }: NotificationsListProps) { const { username } = useAuthUser(); - const dispatch: any = useDispatch(); const [data, setData] = useState([]); const [isLoading, setIsLoading] = useState(false); const [offset, setOffset] = useState(0); @@ -180,12 +175,14 @@ export default function NotificationsList({ const intialSubscriptionState = async () => { try { - const res = await dispatch(getUserPnconfig({ username: username })); + const res = await request(routes.getUserPnconfig, { + pathParams: { username: username }, + }); const reg = await navigator.serviceWorker.ready; const subscription = await reg.pushManager.getSubscription(); - if (!subscription && !res?.data?.pf_endpoint) { + if (!subscription && !res.data?.pf_endpoint) { setIsSubscribed("NotSubscribed"); - } else if (subscription?.endpoint === res?.data?.pf_endpoint) { + } else if (subscription?.endpoint === res.data?.pf_endpoint) { setIsSubscribed("SubscribedOnThisDevice"); } else { setIsSubscribed("SubscribedOnAnotherDevice"); @@ -247,9 +244,11 @@ export default function NotificationsList({ pf_p256dh: "", pf_auth: "", }; - await dispatch( - updateUserPnconfig(data, { username: username }) - ); + + await request(routes.updateUserPnconfig, { + pathParams: { username: username }, + body: data, + }); setIsSubscribed("NotSubscribed"); setIsSubscribing(false); @@ -271,8 +270,8 @@ export default function NotificationsList({ async function subscribe() { setIsSubscribing(true); - const response = await dispatch(getPublicKey()); - const public_key = response.data.public_key; + const response = await request(routes.getPublicKey); + const public_key = response.data?.public_key; const sw = await navigator.serviceWorker.ready; const push = await sw.pushManager.subscribe({ userVisibleOnly: true, @@ -297,11 +296,12 @@ export default function NotificationsList({ pf_auth: auth, }; - const res = await dispatch( - updateUserPnconfig(data, { username: username }) - ); + const { res } = await request(routes.updateUserPnconfig, { + pathParams: { username: username }, + body: data, + }); - if (res.status >= 200 && res.status <= 300) { + if (res?.ok) { setIsSubscribed("SubscribedOnThisDevice"); } setIsSubscribing(false); @@ -310,8 +310,11 @@ export default function NotificationsList({ const handleMarkAllAsRead = async () => { setIsMarkingAllAsRead(true); await Promise.all( - data.map(async (notification) => { - return await dispatch(markNotificationAsRead(notification.id)); + data.map((notification) => { + return request(routes.markNotificationAsRead, { + pathParams: { id: notification.id }, + body: { read_at: new Date() }, + }); }) ); setReload(!reload); @@ -320,10 +323,10 @@ export default function NotificationsList({ useEffect(() => { setIsLoading(true); - dispatch( - getNotifications({ offset, event: eventFilter, medium_sent: "SYSTEM" }) - ) - .then((res: any) => { + request(routes.getNotifications, { + query: { offset, event: eventFilter, medium_set: "SYSTEM" }, + }) + .then((res) => { if (res && res.data) { setData(res.data.results); setUnreadCount( @@ -341,7 +344,7 @@ export default function NotificationsList({ setOffset((prev) => prev - RESULT_LIMIT); }); intialSubscriptionState(); - }, [dispatch, reload, open, offset, eventFilter, isSubscribed]); + }, [reload, open, offset, eventFilter, isSubscribed]); if (!offset && isLoading) { manageResults = ( diff --git a/src/Components/Notifications/ShowPushNotification.tsx b/src/Components/Notifications/ShowPushNotification.tsx index 09b62bb9333..35e9ecd7e70 100644 --- a/src/Components/Notifications/ShowPushNotification.tsx +++ b/src/Components/Notifications/ShowPushNotification.tsx @@ -1,29 +1,34 @@ -import { useDispatch } from "react-redux"; -import { getNotificationData } from "../../Redux/actions"; -import { useEffect } from "react"; import { DetailRoute } from "../../Routers/types"; +import useQuery from "../../Utils/request/useQuery"; +import routes from "../../Redux/api"; +import { NotificationData } from "./models"; export default function ShowPushNotification({ id }: DetailRoute) { - const dispatch: any = useDispatch(); + useQuery(routes.getNotificationData, { + pathParams: { id }, + onResponse(res) { + if (res.data) { + window.location.href = resultUrl(res.data); + } + }, + }); - const resultUrl = async () => { - const res = await dispatch(getNotificationData({ id })); - const data = res.data.caused_objects; - switch (res.data.event) { + const resultUrl = ({ caused_objects, event }: NotificationData) => { + switch (event) { case "PATIENT_CREATED": - return `/facility/${data.facility}/patient/${data.patient}`; + return `/facility/${caused_objects?.facility}/patient/${caused_objects?.patient}`; case "PATIENT_UPDATED": - return `/facility/${data.facility}/patient/${data.patient}`; + return `/facility/${caused_objects?.facility}/patient/${caused_objects?.patient}`; case "PATIENT_CONSULTATION_CREATED": - return `/facility/${data.facility}/patient/${data.patient}/consultation/${data.consultation}`; + return `/facility/${caused_objects?.facility}/patient/${caused_objects?.patient}/consultation/${caused_objects?.consultation}`; case "PATIENT_CONSULTATION_UPDATED": - return `/facility/${data.facility}/patient/${data.patient}/consultation/${data.consultation}`; + return `/facility/${caused_objects?.facility}/patient/${caused_objects?.patient}/consultation/${caused_objects?.consultation}`; case "PATIENT_CONSULTATION_UPDATE_CREATED": - return `/facility/${data.facility}/patient/${data.patient}/consultation/${data.consultation}/daily-rounds/${data.daily_round}`; + return `/facility/${caused_objects?.facility}/patient/${caused_objects?.patient}/consultation/${caused_objects?.consultation}/daily-rounds/${caused_objects?.daily_round}`; case "PATIENT_CONSULTATION_UPDATE_UPDATED": - return `/facility/${data.facility}/patient/${data.patient}/consultation/${data.consultation}/daily-rounds/${data.daily_round}`; + return `/facility/${caused_objects?.facility}/patient/${caused_objects?.patient}/consultation/${caused_objects?.consultation}/daily-rounds/${caused_objects?.daily_round}`; case "INVESTIGATION_SESSION_CREATED": - return `/facility/${data.facility}/patient/${data.patient}/consultation/${data.consultation}/investigation/${data.session}`; + return `/facility/${caused_objects?.facility}/patient/${caused_objects?.patient}/consultation/${caused_objects?.consultation}/investigation/${caused_objects?.session}`; case "MESSAGE": return "/notice_board/"; default: @@ -31,13 +36,5 @@ export default function ShowPushNotification({ id }: DetailRoute) { } }; - useEffect(() => { - resultUrl() - .then((url) => { - window.location.href = url; - }) - .catch((err) => console.log(err)); - }, []); - return <>; } diff --git a/src/Components/Notifications/models.tsx b/src/Components/Notifications/models.tsx new file mode 100644 index 00000000000..edb29178cb5 --- /dev/null +++ b/src/Components/Notifications/models.tsx @@ -0,0 +1,29 @@ +export interface NotificationData { + id: string; + title: string; + caused_objects: cause_object; + caused_by: any; + content: string; + offset: number; + event: string; + event_type: string; + medium_sent: string; + created_date: string; + read_at: string; + message: string; + public_key: string; +} + +export interface cause_object { + facility: string; + patient: string; + consultation: string; + daily_round: string; + session: string; +} + +export interface PNconfigData { + pf_auth: string; + pf_endpoint: string; + pf_p256dh: string; +} diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index 0e3fabf0bff..7c78322da94 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -45,6 +45,10 @@ import { } from "../Components/ExternalResult/models"; import { UserModel } from "../Components/Users/models"; import { PaginatedResponse } from "../Utils/request/types"; +import { + NotificationData, + PNconfigData, +} from "../Components/Notifications/models"; import { PatientModel } from "../Components/Patient/models"; import { IComment, IResource } from "../Components/Resource/models"; @@ -204,11 +208,14 @@ const routes = { getUserPnconfig: { path: "/api/v1/users/{username}/pnconfig/", + method: "GET", + TRes: Type(), }, updateUserPnconfig: { path: "/api/v1/users/{username}/pnconfig/", method: "PATCH", + TRes: Type(), }, // Skill Endpoints @@ -770,19 +777,27 @@ const routes = { path: "/api/v1/shift/{id}/comment/", method: "POST", }, + // Notifications getNotifications: { path: "/api/v1/notification/", + method: "GET", + TRes: Type>(), }, getNotificationData: { path: "/api/v1/notification/{id}/", + method: "GET", + TRes: Type(), }, markNotificationAsRead: { path: "/api/v1/notification/{id}/", method: "PATCH", + TRes: Type(), }, getPublicKey: { path: "/api/v1/notification/public_key/", + method: "GET", + TRes: Type(), }, sendNotificationMessages: { path: "/api/v1/notification/notify/",