Skip to content

Commit

Permalink
Patient Notification client completed ✅
Browse files Browse the repository at this point in the history
  • Loading branch information
sinanptm committed Sep 22, 2024
1 parent a9ea8b5 commit 98fc88e
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 53 deletions.
10 changes: 7 additions & 3 deletions client/components/button/PatientNotificationButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@ import { Badge } from "@/components/ui/badge";
import { ButtonV2 } from "@/components/common/ButtonV2";
import NotificationModal from "@/components/models/NotificationModel";
import { useState } from "react";
import { useGetAllPatientNotifications } from "@/lib/hooks/notification/useSlotPatient";
import { useGetAllPatientNotifications } from "@/lib/hooks/notification/useNotificationPatient";
import { INotification } from "@/types";

const NotificationButton = () => {
const [isNotificationModalOpen, setIsNotificationModalOpen] = useState(false);
const { data: notifications, isLoading } = useGetAllPatientNotifications();
const { data: notifications, refetch, error } = useGetAllPatientNotifications();

const notificationCount = notifications?.length || 0;

const handleNotificationClick = () => {
setIsNotificationModalOpen(true);
};

const unauthorized = error?.status === 401 || error?.status === 403;

return (
<>
<ButtonV2 variant="ghost" size="icon" className="relative" onClick={handleNotificationClick}>
Expand All @@ -34,8 +36,10 @@ const NotificationButton = () => {
</ButtonV2>
<NotificationModal
open={isNotificationModalOpen}
unauthorized={unauthorized!}
setOpen={setIsNotificationModalOpen}
notifications={notifications as INotification[] || []}
refetch={refetch}
/>
</>
);
Expand Down
176 changes: 128 additions & 48 deletions client/components/models/NotificationModel.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,155 @@
import { Dispatch, SetStateAction } from "react";
import Image from "next/image";
'use client'

import { Dispatch, SetStateAction } from "react"
import Image from "next/image"
import {
AlertDialog,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { INotification, NotificationTypes } from "@/types";
import getNotificationDetails from "@/lib/utils/getNotificationDetails";
} from "@/components/ui/alert-dialog"
import { Card, CardContent } from "@/components/ui/card"
import { INotification } from "@/types"
import getNotificationDetails from "@/lib/utils/getNotificationDetails"
import { useClearMultiplePatientNotifications, useClearPatientNotification } from "@/lib/hooks/notification/useNotificationPatient"
import { XIcon, Trash2Icon } from "lucide-react"
import { ButtonV2 } from "../common/ButtonV2"

type Props = {
open: boolean;
setOpen: Dispatch<SetStateAction<boolean>>;
notifications: INotification[];
};
open: boolean
setOpen: Dispatch<SetStateAction<boolean>>
notifications: INotification[]
unauthorized: boolean,
refetch: any
}

const NotificationModal = ({ open, setOpen, notifications }: Props) => {
export default function NotificationModal({ open, setOpen, notifications, unauthorized, refetch }: Props) {
const closeModal = () => {
setOpen(false);
};
setOpen(false)
}
const { mutate: clearSingleNotification } = useClearPatientNotification()
const { mutate: clearMultipleNotification } = useClearMultiplePatientNotifications()

const handleClearSingleNotification = (notificationId: string) => {
clearSingleNotification(
{ notificationId },
{
onSuccess: refetch,
onError: (error) => {
console.error("Failed to clear notification:", error)
},
},
)
}

const handleClearAllNotifications = () => {
const notificationIds = notifications.map(notification => notification._id!)
clearMultipleNotification(
{ notificationIds },
{
onSuccess: refetch,
onError: (error) => {
console.error("Failed to clear multiple notifications:", error)
},
}
)
}

return (
<AlertDialog open={open} onOpenChange={setOpen}>
<AlertDialogContent className="max-w-3xl bg-dark-200">
<AlertDialogHeader>
<AlertDialogTitle className="flex items-center justify-between text-2xl font-semibold">
Notifications
<Button variant="ghost" size="icon" onClick={closeModal}>
<Image
src="/assets/icons/close.svg"
width={24}
height={24}
alt="Close"
className="cursor-pointer"
/>
</Button>
<ButtonV2 variant="ghost" size="icon" onClick={closeModal}>
<XIcon className="h-6 w-6" />
</ButtonV2>
</AlertDialogTitle>
</AlertDialogHeader>
<AlertDialogDescription></AlertDialogDescription>
<div className="space-y-4">
{notifications.map((notification) => {
const { icon, title } = getNotificationDetails(notification.type!);
return (
<Card key={notification._id}>
<CardContent className="flex items-center space-x-4 p-4">
<Image
src={icon}
width={24}
height={24}
alt={title}
className="h-6 w-6"
/>
<div>
<h3 className="font-semibold">{title}</h3>
<p className="text-sm text-muted-foreground">{notification.message}</p>
</div>
</CardContent>
</Card>
);
})}
{unauthorized ? (
<div className="flex flex-col items-center justify-center space-y-2 py-6">
<Image
src="/assets/icons/cancelled.svg"
width={64}
height={64}
alt="Unauthorized"
className="opacity-50"
/>
<p className="text-center text-muted-foreground text-sm">
You are not authorized to view these notifications.
</p>
</div>
) : notifications && notifications.length > 0 ? (
<>
{notifications.map((notification) => {
const { icon, title } = getNotificationDetails(notification.type!)
return (
<Card key={notification._id}>
<CardContent className="flex items-center justify-between p-4">
<div className="flex items-center space-x-4">
<Image
src={icon}
width={24}
height={24}
alt={title}
className="h-6 w-6"
/>
<div>
<h3 className="font-semibold">{title}</h3>
<p className="text-sm text-muted-foreground">{notification.message}</p>
</div>
</div>
<ButtonV2
variant="expandIcon"
size="icon"
onClick={() => handleClearSingleNotification(notification._id!)}
iconPlacement="left"
Icon={Trash2Icon}
className="text-muted-foreground hover:text-primary w-20"
>
Clear
</ButtonV2>

</CardContent>
</Card>
)
})}
</>
) : (
<div className="flex flex-col items-center justify-center space-y-2 py-6">
<Image
src="/assets/icons/emoji/😑.svg"
width={64}
height={64}
alt="No Notifications"
className="opacity-50"
/>
<p className="text-center text-muted-foreground text-sm">
You're all caught up! No new notifications.
</p>
</div>
)}
</div>

<AlertDialogFooter>
<Button onClick={closeModal}>Close</Button>
<div className="flex justify-end space-x-2">
{notifications.length > 0 && (
<ButtonV2
variant="outline"
onClick={handleClearAllNotifications}
className="text-muted-foreground hover:text-primary"
>
Clear All
</ButtonV2>
)}
<ButtonV2 onClick={closeModal}>Close</ButtonV2>
</div>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}

export default NotificationModal;
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { AxiosError } from "axios"
export const useGetAllDoctorNotifications = ()=>{
return useQuery<INotification[],AxiosError<ErrorResponse>>({
queryKey:["notifications"],
queryFn:getDoctorNotifications
queryFn:getDoctorNotifications,
retry:1,
retryOnMount:false,
refetchInterval:1000*60
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { AxiosError } from "axios"
export const useGetAllPatientNotifications = ()=>{
return useQuery<INotification[],AxiosError<ErrorResponse>>({
queryKey:["notifications"],
queryFn:getPatientNotifications
queryFn:getPatientNotifications,
retry:1,
retryOnMount:false,
refetchInterval:1000*60
})
}

Expand Down
1 change: 1 addition & 0 deletions client/public/assets/icons/emoji/😑.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 98fc88e

Please sign in to comment.