add notification list, add notification page

This commit is contained in:
smanylov
2026-03-30 19:11:48 +07:00
parent 884fb8dc50
commit f4b0a63e23
7 changed files with 376 additions and 47 deletions
+101 -23
View File
@@ -1,18 +1,60 @@
"use client"
import { useState, useRef } from 'react';
import { useState, useRef, useEffect } from 'react';
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,
}
export default function NotificationsButton() {
const [isOpen, setIsOpen] = useState(false);
const [data, setData] = useState<string | null>(null);
const [notificationData, setNotificationData] = useState<Notification[] | []>([]);
const [error, setError] = useState<string | null>(null);
const menuRef = useRef<HTMLDivElement | null>(null);
const t = useTranslations('Global');
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: '#'
}
])
}, [])
useClickOutside(
menuRef,
() => {
@@ -29,6 +71,14 @@ export default function NotificationsButton() {
}
};
function markAsReadHandler() {
console.log('click: mark as read');
}
function notificationClickHandler(id: string) {
console.log(`click: ${id}`);
}
return (
<div className="notification-wrapper" ref={menuRef}>
<button
@@ -50,35 +100,63 @@ export default function NotificationsButton() {
<h4>
{t('notifications')}
</h4>
<span className="notification-count">
{t('no-new')}
</span>
<Link
href={'/pages/notifications'}
className="notification-count"
onClick={() => {
setIsOpen(false);
}}
>
{t('no-new')} / {t('all')}
</Link>
</div>
{data ? (
<div className="notification-list">
<div className="notification-item">
<div className="notification-icon">
<IconNotification />
</div>
<div className="notification-content">
<div className="notification-title">
{t('tokens-added')}
{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>
{/* <div className="notification-title">
{t('tokens-added')}
</div> */}
<div className="notification-text">
{item.notificationText}
</div>
</div>
</div>
<div className="notification-text">{t('added')} 100 {t('tokens')}.</div>
<div className="notification-time">4 {t('days-ago')}</div>
</div>
</div>
{JSON.stringify(data)}
)
})}
</div>
) : (
<p>
{t('no-data')}
{/* {t('no-data')} */}
</p>
)}
<div className="notification-footer">
<Link href="#" className="notification-link">
{t('view-all')}
</Link>
<button
className="notification-link"
onClick={() => {
markAsReadHandler();
}}
>
{t('mark-all-as-read')}
</button>
</div>
</>
)}
@@ -0,0 +1,132 @@
'use client'
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,
}
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: '#'
},
{
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: '#'
}
];
export function NotificationsList() {
const t = useTranslations('Global');
const [selectedFiles, setSelectedFiles] = useState<Set<string>>(new Set());
function selectHandler(fileId: string) {
setSelectedFiles((prev) => {
const newSet = new Set(prev)
if (newSet.has(fileId)) {
newSet.delete(fileId)
} else {
newSet.add(fileId)
}
return newSet;
});
}
function clearHandler() {
setSelectedFiles(new Set());
}
return (
<div
className="block-wrapper"
>
<div
className="notifications-list-wrapper"
>
<div
className="notifications-list-header"
>
<h4>
{t('all-notifications')}
</h4>
<div
className="notifications-list-action"
>
{(selectedFiles.size !== 0) && (
<button
className="btn btn-primary"
onClick={() => {
clearHandler();
}}
>
{t('deselect')}
</button>
)}
</div>
</div>
<div
className="notifications-list-body"
>
{(noitficationList.length !== 0) && (
noitficationList.map(item => {
return (
<div
className="notification-item"
>
<div
className="notification-check"
>
<button
onClick={() => {
selectHandler(item.id);
}}
>
{selectedFiles.has(item.id) && (
<IconCheck />
)}
</button>
</div>
<div
className="notification-text"
>
{item.notificationText}
</div>
</div>
)
})
)}
</div>
</div>
</div>
)
}