From f532a1514f07133306ab313ae00c8057ca32890c Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Thu, 25 Dec 2025 10:18:47 +0330 Subject: [PATCH] read all notif --- public/assets/images/readall.png | Bin 0 -> 6749 bytes .../hooks/useNotificationData.ts | 11 ++++ .../[name]/(Dialogs)/notifications/page.tsx | 57 +++++++++++++++--- .../service/NotificationService.ts | 7 ++- src/components/input/SearchBox.tsx | 4 +- 5 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 public/assets/images/readall.png diff --git a/public/assets/images/readall.png b/public/assets/images/readall.png new file mode 100644 index 0000000000000000000000000000000000000000..1b21a52c856f44bc9033fd1fbca5402c1aa3cdb7 GIT binary patch literal 6749 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 literal 0 HcmV?d00001 diff --git a/src/app/[name]/(Dialogs)/notifications/hooks/useNotificationData.ts b/src/app/[name]/(Dialogs)/notifications/hooks/useNotificationData.ts index 48c7cea..6092672 100644 --- a/src/app/[name]/(Dialogs)/notifications/hooks/useNotificationData.ts +++ b/src/app/[name]/(Dialogs)/notifications/hooks/useNotificationData.ts @@ -17,3 +17,14 @@ export const useDeleteNotification = () => { }, }); }; + +export const useReadAllNotifications = () => { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: api.readAll, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["notifications"] }); + queryClient.invalidateQueries({ queryKey: ["notificationsCount"] }); + }, + }); +}; diff --git a/src/app/[name]/(Dialogs)/notifications/page.tsx b/src/app/[name]/(Dialogs)/notifications/page.tsx index 11e2edf..da33b31 100644 --- a/src/app/[name]/(Dialogs)/notifications/page.tsx +++ b/src/app/[name]/(Dialogs)/notifications/page.tsx @@ -6,8 +6,10 @@ import { useRouter } from 'next/navigation'; import React from 'react' import Image from 'next/image'; import { useTranslation } from 'react-i18next'; -import { useGetNotifications, useDeleteNotification } from './hooks/useNotificationData'; +import { useGetNotifications, useDeleteNotification, useReadAllNotifications } from './hooks/useNotificationData'; import type { Notification } from './types/Types'; +import { useGetNotificationsCount } from '../../(Main)/hooks/useMenuData'; +import Prompt from '@/components/utils/Prompt'; type Props = object @@ -33,6 +35,9 @@ export default function NotificationsIndex({ }: Props) { const router = useRouter(); const { data, isLoading } = useGetNotifications(); const { mutate: deleteNotification } = useDeleteNotification(); + const { mutate: readAllNotifications } = useReadAllNotifications(); + const { data: notificationsCount } = useGetNotificationsCount(); + const [showReadAllConfirm, setShowReadAllConfirm] = React.useState(false); const notifications = React.useMemo(() => { return data?.data ?? []; @@ -42,6 +47,23 @@ export default function NotificationsIndex({ }: Props) { deleteNotification(id); }; + const handleReadAll = (e: React.MouseEvent) => { + e?.preventDefault(); + e?.stopPropagation(); + readAllNotifications(); + setShowReadAllConfirm(false); + }; + + const toggleReadAllConfirm = (e: React.MouseEvent) => { + e?.preventDefault(); + e?.stopPropagation(); + setShowReadAllConfirm(false); + }; + + const handleReadAllClick = () => { + setShowReadAllConfirm(true); + }; + return (
@@ -55,6 +77,9 @@ export default function NotificationsIndex({ }: Props) { />
+
+
+
{isLoading ? (
@@ -75,7 +100,15 @@ export default function NotificationsIndex({ }: Props) {
) : ( -
    +
      + { + notificationsCount?.data?.count && notificationsCount?.data?.count > 0 ? ( +
      + notification +
      + ) + : null + } {notifications.map((notification: Notification) => { const isNew = !notification.sentAt; const formattedDate = formatDate(notification.createdAt); @@ -83,7 +116,7 @@ export default function NotificationsIndex({ }: Props) { return (
    • -
      {notification.title}
      + {/*
      {notification.title}
      */}

      {notification.content}

      @@ -101,11 +134,6 @@ export default function NotificationsIndex({ }: Props) { {ef(formattedTime)}
      - handleDelete(notification.id)} - />
); @@ -113,6 +141,19 @@ export default function NotificationsIndex({ }: Props) { )} + +
+ +
) } \ No newline at end of file diff --git a/src/app/[name]/(Dialogs)/notifications/service/NotificationService.ts b/src/app/[name]/(Dialogs)/notifications/service/NotificationService.ts index 3d668c7..097710d 100644 --- a/src/app/[name]/(Dialogs)/notifications/service/NotificationService.ts +++ b/src/app/[name]/(Dialogs)/notifications/service/NotificationService.ts @@ -4,7 +4,7 @@ import { BaseResponse } from "@/app/[name]/(Main)/types/Types"; export const getNotifications = async (): Promise => { const { data } = await api.get( - "/public/notifications" + "/public/notifications?status=unseen" ); return data; }; @@ -17,3 +17,8 @@ export const deleteNotification = async ( ); return data; }; + +export const readAll = async () => { + const { data } = await api.put("/public/notifications/read/all"); + return data; +}; diff --git a/src/components/input/SearchBox.tsx b/src/components/input/SearchBox.tsx index 100b1c7..c242a68 100644 --- a/src/components/input/SearchBox.tsx +++ b/src/components/input/SearchBox.tsx @@ -10,7 +10,7 @@ interface SearchboxProps onChange: (e: React.ChangeEvent) => void } -export default function SearchBox ({ +export default function SearchBox({ className, value, placeholder = '', @@ -29,7 +29,7 @@ export default function SearchBox ({ onChange={onChange} value={value} placeholder={placeholder} - className='text-[#8C90A3] pt-1 block outline-none border-none focus:ring-0 focus:outline-none text-sm px-[7px] h-full items-center w-full' + className='text-[#8C90A3] pt-1 block outline-none border-none focus:ring-0 focus:outline-none px-[7px] h-full items-center w-full text-xs!' type='search' {...props} />