finished header notifications
This commit is contained in:
@@ -5,55 +5,24 @@ import { useClickOutside } from '@/app/hooks/useClickOutside';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Link from 'next/link';
|
||||
import { IconNotification } from '@/app/ui/icons/icons';
|
||||
|
||||
interface Notification {
|
||||
id: string,
|
||||
notificationText: string,
|
||||
data: string,
|
||||
link: string,
|
||||
}
|
||||
import { useActiveNotifications } from '@/app/hooks/react-query/useActiveNotificationsList';
|
||||
import { NotificationBody, notificationsMarkAsRead } from '@/app/actions/notificationActions';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
export default function NotificationsButton() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [notificationData, setNotificationData] = useState<Notification[] | []>([]);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const menuRef = useRef<HTMLDivElement | null>(null);
|
||||
const [loadingIds, setLoadingIds] = useState<Set<number>>(new Set());
|
||||
const [isMarkingAll, setIsMarkingAll] = useState(false);
|
||||
const t = useTranslations('Global');
|
||||
|
||||
const { data: notificationList } = useActiveNotifications();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
useEffect(() => {
|
||||
setNotificationData([
|
||||
{
|
||||
id: '1',
|
||||
notificationText: 'text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1',
|
||||
data: '20.20.20',
|
||||
link: '#'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
notificationText: 'text2',
|
||||
data: '20.20.20',
|
||||
link: '#'
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
notificationText: 'text3',
|
||||
data: '20.20.20',
|
||||
link: '#'
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
notificationText: 'text4',
|
||||
data: '20.20.20',
|
||||
link: '#'
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
notificationText: 'text5',
|
||||
data: '20.20.20',
|
||||
link: '#'
|
||||
}
|
||||
])
|
||||
}, [])
|
||||
console.log(notificationList);
|
||||
}, [notificationList])
|
||||
|
||||
useClickOutside(
|
||||
menuRef,
|
||||
@@ -71,12 +40,42 @@ export default function NotificationsButton() {
|
||||
}
|
||||
};
|
||||
|
||||
function markAsReadHandler() {
|
||||
console.log('click: mark as read');
|
||||
async function markAsReadHandler(ids: number[]) {
|
||||
setLoadingIds(prev => {
|
||||
const newSet = new Set(prev);
|
||||
ids.forEach(id => newSet.add(id));
|
||||
return newSet;
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await notificationsMarkAsRead(ids);
|
||||
|
||||
if (response.success) {
|
||||
await queryClient.invalidateQueries({ queryKey: ['activeNotifications'] });
|
||||
await queryClient.invalidateQueries({ queryKey: ['allNotifications'] });
|
||||
}
|
||||
} catch (error) {
|
||||
setError(error instanceof Error ? error.message : 'Failed to mark as read');
|
||||
} finally {
|
||||
setLoadingIds(prev => {
|
||||
const newSet = new Set(prev);
|
||||
ids.forEach(id => newSet.delete(id));
|
||||
return newSet;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function notificationClickHandler(id: string) {
|
||||
console.log(`click: ${id}`);
|
||||
async function markAllAsReadHandler() {
|
||||
const array = notificationList?.notifications?.map(e => e.id) ?? [];
|
||||
if (array.length === 0) return;
|
||||
|
||||
setIsMarkingAll(true);
|
||||
|
||||
try {
|
||||
await markAsReadHandler(array);
|
||||
} finally {
|
||||
setIsMarkingAll(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -107,57 +106,79 @@ export default function NotificationsButton() {
|
||||
setIsOpen(false);
|
||||
}}
|
||||
>
|
||||
{t('no-new')} / {t('all')}
|
||||
{notificationList?.unreadCount ? notificationList?.unreadCount : t('no-new')} / {t('all')}
|
||||
</Link>
|
||||
</div>
|
||||
{notificationData.length !== 0 ? (
|
||||
<div
|
||||
className="notification-list"
|
||||
>
|
||||
{notificationData.map((item) => {
|
||||
return (
|
||||
<div
|
||||
key={item.id}
|
||||
className="notification-item"
|
||||
onClick={() => {
|
||||
notificationClickHandler(item.id);
|
||||
}}
|
||||
>
|
||||
<div className="notification-icon">
|
||||
<IconNotification />
|
||||
</div>
|
||||
<div className="notification-content">
|
||||
<div className="notification-data">
|
||||
{item.data}
|
||||
</div>
|
||||
{notificationList?.notifications.length !== 0 ? (
|
||||
<>
|
||||
<div
|
||||
className="notification-list"
|
||||
>
|
||||
{notificationList?.notifications?.map((item) => {
|
||||
return (
|
||||
<div
|
||||
key={item.id}
|
||||
className={`notification-item ${loadingIds.has(item.id) ? 'loading' : ''}`}
|
||||
>
|
||||
<div className="notification-content">
|
||||
<div className="notification-data">
|
||||
{item.createdAt ? item.createdAt : '#'}
|
||||
</div>
|
||||
|
||||
{/* <div className="notification-title">
|
||||
{/* <div className="notification-title">
|
||||
{t('tokens-added')}
|
||||
</div> */}
|
||||
|
||||
<div className="notification-text">
|
||||
{item.notificationText}
|
||||
<div className="notification-text">
|
||||
{item.message}
|
||||
</div>
|
||||
|
||||
<button
|
||||
className="notification-mark-as-read"
|
||||
onClick={() => {
|
||||
markAsReadHandler([item.id]);
|
||||
}}
|
||||
disabled={loadingIds.has(item.id)}
|
||||
>
|
||||
{t('mark-as-read')}
|
||||
</button>
|
||||
|
||||
{loadingIds.has(item.id) && (
|
||||
<div className="loading-animation">
|
||||
<div className="global-spinner"></div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="notification-footer">
|
||||
<button
|
||||
className="notification-link"
|
||||
onClick={() => {
|
||||
markAllAsReadHandler()
|
||||
}}
|
||||
disabled={isMarkingAll || loadingIds.size > 0}
|
||||
>
|
||||
{isMarkingAll || loadingIds.size > 0 && (
|
||||
<div className="loading-animation">
|
||||
<div className="global-spinner"></div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{t('mark-all-as-read')}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<p>
|
||||
{/* {t('no-data')} */}
|
||||
<p
|
||||
className="text-center mb-4 mt-4"
|
||||
>
|
||||
{t('no-new-notifications')}
|
||||
</p>
|
||||
)}
|
||||
<div className="notification-footer">
|
||||
<button
|
||||
className="notification-link"
|
||||
onClick={() => {
|
||||
markAsReadHandler();
|
||||
}}
|
||||
>
|
||||
{t('mark-all-as-read')}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -2,65 +2,19 @@
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { IconCheck } from '@/app/ui/icons/icons';
|
||||
import { useState } from 'react';
|
||||
|
||||
interface Notification {
|
||||
id: string,
|
||||
notificationText: string,
|
||||
data: string,
|
||||
link: string,
|
||||
title: string,
|
||||
status: string,
|
||||
}
|
||||
|
||||
const noitficationList: Notification[] = [
|
||||
{
|
||||
id: '1',
|
||||
notificationText: 'text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1 text1',
|
||||
data: '20.20.20',
|
||||
link: '#',
|
||||
title: 'title 1',
|
||||
status: 'status'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
notificationText: 'text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 text2 ',
|
||||
data: '20.20.20',
|
||||
link: '#',
|
||||
title: 'title 2',
|
||||
status: 'status'
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
notificationText: 'text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 text3 ',
|
||||
data: '20.20.20',
|
||||
link: '#',
|
||||
title: 'title 3',
|
||||
status: 'status'
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
notificationText: 'text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 text4 ',
|
||||
data: '20.20.20',
|
||||
link: '#',
|
||||
title: 'title 4',
|
||||
status: 'status'
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
notificationText: 'text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 text5 ',
|
||||
data: '20.20.20',
|
||||
link: '#',
|
||||
title: 'title 5',
|
||||
status: 'status'
|
||||
}
|
||||
];
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useAllNotifications } from '@/app/hooks/react-query/useAllNotificationsList';
|
||||
|
||||
export function NotificationsList() {
|
||||
const t = useTranslations('Global');
|
||||
const [selectedFiles, setSelectedFiles] = useState<Set<string>>(new Set());
|
||||
const [selectedFiles, setSelectedFiles] = useState<Set<number>>(new Set());
|
||||
const { data: allNotifications } = useAllNotifications();
|
||||
|
||||
function selectHandler(fileId: string) {
|
||||
useEffect(() => {
|
||||
console.log(allNotifications);
|
||||
}, [allNotifications])
|
||||
|
||||
function selectHandler(fileId: number) {
|
||||
setSelectedFiles((prev) => {
|
||||
const newSet = new Set(prev);
|
||||
|
||||
@@ -78,7 +32,7 @@ export function NotificationsList() {
|
||||
}
|
||||
|
||||
function selectAllHandler() {
|
||||
setSelectedFiles(new Set(noitficationList.map(item => item.id)));
|
||||
setSelectedFiles(new Set(allNotifications?.notifications.map(item => item.id)));
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -129,8 +83,8 @@ export function NotificationsList() {
|
||||
<div
|
||||
className="notifications-list-body"
|
||||
>
|
||||
{(noitficationList.length !== 0) && (
|
||||
noitficationList.map(item => {
|
||||
{(allNotifications?.notifications.length !== 0) && (
|
||||
allNotifications?.notifications.map(item => {
|
||||
return (
|
||||
<div
|
||||
className="notification-item"
|
||||
@@ -159,7 +113,7 @@ export function NotificationsList() {
|
||||
<div
|
||||
className="notification-title"
|
||||
>
|
||||
{item.title}
|
||||
{item.type}
|
||||
</div>
|
||||
<div
|
||||
className="notification-status"
|
||||
@@ -170,7 +124,7 @@ export function NotificationsList() {
|
||||
<div
|
||||
className="notification-text"
|
||||
>
|
||||
{item.notificationText}
|
||||
{item.message}
|
||||
</div>
|
||||
<div
|
||||
className="notification-footer"
|
||||
@@ -178,7 +132,7 @@ export function NotificationsList() {
|
||||
<div
|
||||
className="notification-date"
|
||||
>
|
||||
{item.data}
|
||||
{item.createdAt}
|
||||
</div>
|
||||
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user