read all notif
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
@@ -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"] });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import { useRouter } from 'next/navigation';
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { useTranslation } from 'react-i18next';
|
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 type { Notification } from './types/Types';
|
||||||
|
import { useGetNotificationsCount } from '../../(Main)/hooks/useMenuData';
|
||||||
|
import Prompt from '@/components/utils/Prompt';
|
||||||
|
|
||||||
type Props = object
|
type Props = object
|
||||||
|
|
||||||
@@ -33,6 +35,9 @@ export default function NotificationsIndex({ }: Props) {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { data, isLoading } = useGetNotifications();
|
const { data, isLoading } = useGetNotifications();
|
||||||
const { mutate: deleteNotification } = useDeleteNotification();
|
const { mutate: deleteNotification } = useDeleteNotification();
|
||||||
|
const { mutate: readAllNotifications } = useReadAllNotifications();
|
||||||
|
const { data: notificationsCount } = useGetNotificationsCount();
|
||||||
|
const [showReadAllConfirm, setShowReadAllConfirm] = React.useState(false);
|
||||||
|
|
||||||
const notifications = React.useMemo(() => {
|
const notifications = React.useMemo(() => {
|
||||||
return data?.data ?? [];
|
return data?.data ?? [];
|
||||||
@@ -42,6 +47,23 @@ export default function NotificationsIndex({ }: Props) {
|
|||||||
deleteNotification(id);
|
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 (
|
return (
|
||||||
<div className='overflow-y-auto h-full noscrollbar flex flex-col'>
|
<div className='overflow-y-auto h-full noscrollbar flex flex-col'>
|
||||||
<div className='grid grid-cols-3 items-center'>
|
<div className='grid grid-cols-3 items-center'>
|
||||||
@@ -55,6 +77,9 @@ export default function NotificationsIndex({ }: Props) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="mt-8 flex-1 h-full">
|
<div className="mt-8 flex-1 h-full">
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className='flex flex-col items-center justify-center gap-2 py-12 text-sm2 text-muted-foreground'>
|
<div className='flex flex-col items-center justify-center gap-2 py-12 text-sm2 text-muted-foreground'>
|
||||||
@@ -75,7 +100,15 @@ export default function NotificationsIndex({ }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<ul className='flex flex-col gap-4 pb-20'>
|
<ul className='flex flex-col gap-4 pb-20 px-0.5'>
|
||||||
|
{
|
||||||
|
notificationsCount?.data?.count && notificationsCount?.data?.count > 0 ? (
|
||||||
|
<div className='flex'>
|
||||||
|
<Image src={'/assets/images/readall.png'} alt='notification' width={20} height={20} className='object-contain -mt-3 cursor-pointer' onClick={handleReadAllClick} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
{notifications.map((notification: Notification) => {
|
{notifications.map((notification: Notification) => {
|
||||||
const isNew = !notification.sentAt;
|
const isNew = !notification.sentAt;
|
||||||
const formattedDate = formatDate(notification.createdAt);
|
const formattedDate = formatDate(notification.createdAt);
|
||||||
@@ -83,7 +116,7 @@ export default function NotificationsIndex({ }: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<li key={notification.id} className='bg-container py-5 px-4 rounded-container shadow-lg'>
|
<li key={notification.id} className='bg-container py-5 px-4 rounded-container shadow-lg'>
|
||||||
<h5 className='font-medium text-sm'>{notification.title}</h5>
|
{/* <h5 className='font-medium text-sm'>{notification.title}</h5> */}
|
||||||
<p className='text-xs mt-2 leading-5'>{notification.content}</p>
|
<p className='text-xs mt-2 leading-5'>{notification.content}</p>
|
||||||
|
|
||||||
<div className='flex items-center justify-between mt-5 '>
|
<div className='flex items-center justify-between mt-5 '>
|
||||||
@@ -101,11 +134,6 @@ export default function NotificationsIndex({ }: Props) {
|
|||||||
{ef(formattedTime)}
|
{ef(formattedTime)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<Trash
|
|
||||||
size={24}
|
|
||||||
className='stroke-primary dark:stroke-foreground cursor-pointer'
|
|
||||||
onClick={() => handleDelete(notification.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
@@ -113,6 +141,19 @@ export default function NotificationsIndex({ }: Props) {
|
|||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={showReadAllConfirm ? 'fixed inset-0 z-1001' : 'pointer-events-none fixed inset-0 z-1001'}>
|
||||||
|
<Prompt
|
||||||
|
title='خواندن همه اعلانها'
|
||||||
|
description='آیا از خواندن همه اعلانها اطمینان دارید؟'
|
||||||
|
textConfirm='بله'
|
||||||
|
textCancel='خیر'
|
||||||
|
onConfirm={handleReadAll}
|
||||||
|
onCancel={toggleReadAllConfirm}
|
||||||
|
visible={showReadAllConfirm}
|
||||||
|
onClick={toggleReadAllConfirm}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ import { BaseResponse } from "@/app/[name]/(Main)/types/Types";
|
|||||||
|
|
||||||
export const getNotifications = async (): Promise<NotificationsResponse> => {
|
export const getNotifications = async (): Promise<NotificationsResponse> => {
|
||||||
const { data } = await api.get<NotificationsResponse>(
|
const { data } = await api.get<NotificationsResponse>(
|
||||||
"/public/notifications"
|
"/public/notifications?status=unseen"
|
||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
@@ -17,3 +17,8 @@ export const deleteNotification = async (
|
|||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const readAll = async () => {
|
||||||
|
const { data } = await api.put("/public/notifications/read/all");
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ interface SearchboxProps
|
|||||||
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
|
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SearchBox ({
|
export default function SearchBox({
|
||||||
className,
|
className,
|
||||||
value,
|
value,
|
||||||
placeholder = '',
|
placeholder = '',
|
||||||
@@ -29,7 +29,7 @@ export default function SearchBox ({
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
value={value}
|
value={value}
|
||||||
placeholder={placeholder}
|
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'
|
type='search'
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user