finish notifications featur
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "no-copy-frontend",
|
"name": "no-copy-frontend",
|
||||||
"version": "0.79.0",
|
"version": "0.80.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -p 2999",
|
"dev": "next dev -p 2999",
|
||||||
|
|||||||
@@ -62,9 +62,9 @@ export async function fetchAllNotifications(page: number = 0, size: number = 10)
|
|||||||
page: page,
|
page: page,
|
||||||
size: size,
|
size: size,
|
||||||
sortBy: "createdAt",
|
sortBy: "createdAt",
|
||||||
sortDirection: "DESC",
|
sortDirection: "ASC", //DESC, ASC
|
||||||
types: [], //"SEARCH_RESULT", "MONITORING_RESULT"
|
types: [], //"SEARCH_RESULT", "MONITORING_RESULT"
|
||||||
statuses: [] //"NEW"
|
statuses: ["NEW", "READIED"] //"NEW"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
headers: {
|
headers: {
|
||||||
@@ -76,7 +76,7 @@ export async function fetchAllNotifications(page: number = 0, size: number = 10)
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
let parsed = await response.json();
|
let parsed = await response.json();
|
||||||
|
|
||||||
if (parsed?.message_body) {
|
if (parsed?.message_code === 0) {
|
||||||
return parsed?.message_body
|
return parsed?.message_body
|
||||||
} else {
|
} else {
|
||||||
throw parsed;
|
throw parsed;
|
||||||
@@ -114,7 +114,7 @@ export async function notificationsMarkAsRead(ids: number[]) {
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
let parsed = await response.json();
|
let parsed = await response.json();
|
||||||
|
|
||||||
if (parsed?.message_body) {
|
if (parsed?.message_code === 0) {
|
||||||
return parsed?.message_body
|
return parsed?.message_body
|
||||||
} else {
|
} else {
|
||||||
throw parsed;
|
throw parsed;
|
||||||
|
|||||||
@@ -50,6 +50,10 @@
|
|||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* &.active {
|
||||||
|
background: v.$color-warning;
|
||||||
|
} */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,6 +245,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-unread-count {
|
||||||
|
position: absolute;
|
||||||
|
right: -5px;
|
||||||
|
bottom: -5px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: v.$red;
|
||||||
|
color: v.$white;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-menu {
|
.user-menu {
|
||||||
|
|||||||
@@ -5114,6 +5114,10 @@
|
|||||||
&:last-child {
|
&:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.loading {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-header {
|
&-header {
|
||||||
@@ -5127,7 +5131,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-title {
|
&-title {
|
||||||
font-weight: 600;
|
font-weight: 800;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
@@ -5135,6 +5139,7 @@
|
|||||||
&-text {
|
&-text {
|
||||||
color: v.$text-s;
|
color: v.$text-s;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-status {
|
&-status {
|
||||||
@@ -5188,6 +5193,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notification-item.READIED {
|
||||||
|
|
||||||
|
.notification-title,
|
||||||
|
.notification-text {
|
||||||
|
font-weight: 500;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-footer {
|
&-footer {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { IconNotification } from '@/app/ui/icons/icons';
|
|||||||
import { useActiveNotifications } from '@/app/hooks/react-query/useActiveNotificationsList';
|
import { useActiveNotifications } from '@/app/hooks/react-query/useActiveNotificationsList';
|
||||||
import { NotificationBody, notificationsMarkAsRead } from '@/app/actions/notificationActions';
|
import { NotificationBody, notificationsMarkAsRead } from '@/app/actions/notificationActions';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
|
import { formatDate } from '@/app/lib/formatDate';
|
||||||
|
|
||||||
export default function NotificationsButton() {
|
export default function NotificationsButton() {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
@@ -77,7 +78,7 @@ export default function NotificationsButton() {
|
|||||||
return (
|
return (
|
||||||
<div className="notification-wrapper" ref={menuRef}>
|
<div className="notification-wrapper" ref={menuRef}>
|
||||||
<button
|
<button
|
||||||
className="icon-btn"
|
className={`icon-btn ${notificationList?.unreadCount ? 'active' : ''}`}
|
||||||
id="notifications-btn"
|
id="notifications-btn"
|
||||||
title="Уведомления"
|
title="Уведомления"
|
||||||
onClick={handleButtonClick}
|
onClick={handleButtonClick}
|
||||||
@@ -85,6 +86,13 @@ export default function NotificationsButton() {
|
|||||||
<svg viewBox="0 0 24 24" fill="currentColor" style={{ width: "20px", height: "20px" }}>
|
<svg viewBox="0 0 24 24" fill="currentColor" style={{ width: "20px", height: "20px" }}>
|
||||||
<path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z"></path>
|
<path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
{notificationList?.unreadCount && (
|
||||||
|
<span
|
||||||
|
className="notification-unread-count"
|
||||||
|
>
|
||||||
|
{notificationList?.unreadCount ? notificationList?.unreadCount : ''}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
<div className={`notification-dropdown ${isOpen ? 'show' : ''}`}>
|
<div className={`notification-dropdown ${isOpen ? 'show' : ''}`}>
|
||||||
{error ? (
|
{error ? (
|
||||||
@@ -118,7 +126,7 @@ export default function NotificationsButton() {
|
|||||||
>
|
>
|
||||||
<div className="notification-content">
|
<div className="notification-content">
|
||||||
<div className="notification-data">
|
<div className="notification-data">
|
||||||
{item.createdAt ? item.createdAt : '#'}
|
{item.createdAt ? formatDate(item.createdAt) : '#'}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <div className="notification-title">
|
{/* <div className="notification-title">
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useEffect, useState } from 'react';
|
|||||||
import { useAllNotifications } from '@/app/hooks/react-query/useAllNotificationsList';
|
import { useAllNotifications } from '@/app/hooks/react-query/useAllNotificationsList';
|
||||||
import { notificationsMarkAsRead } from '@/app/actions/notificationActions';
|
import { notificationsMarkAsRead } from '@/app/actions/notificationActions';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
|
import { formatDate, formatDateTime } from '@/app/lib/formatDate';
|
||||||
|
|
||||||
export function NotificationsList() {
|
export function NotificationsList() {
|
||||||
const t = useTranslations('Global');
|
const t = useTranslations('Global');
|
||||||
@@ -88,12 +89,12 @@ export function NotificationsList() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
/* const response = await notificationsMarkAsRead(ids);
|
const response = await notificationsMarkAsRead(ids);
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
await queryClient.invalidateQueries({ queryKey: ['activeNotifications'] });
|
await queryClient.invalidateQueries({ queryKey: ['activeNotifications'] });
|
||||||
await queryClient.invalidateQueries({ queryKey: ['allNotifications'] });
|
await queryClient.invalidateQueries({ queryKey: ['allNotifications'] });
|
||||||
} */
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setError(error instanceof Error ? error.message : 'Failed to mark as read');
|
setError(error instanceof Error ? error.message : 'Failed to mark as read');
|
||||||
} finally {
|
} finally {
|
||||||
@@ -173,7 +174,7 @@ export function NotificationsList() {
|
|||||||
allNotifications?.notifications.map(item => {
|
allNotifications?.notifications.map(item => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="notification-item"
|
className={`notification-item ${loadingIds.has(item.id) ? 'loading' : ''} ${item.status}`}
|
||||||
key={item.id}
|
key={item.id}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -199,13 +200,13 @@ export function NotificationsList() {
|
|||||||
<div
|
<div
|
||||||
className="notification-title"
|
className="notification-title"
|
||||||
>
|
>
|
||||||
{item.type}
|
{item.type} {item.id}
|
||||||
</div>
|
</div>
|
||||||
<div
|
{/* <div
|
||||||
className="notification-status"
|
className="notification-status"
|
||||||
>
|
>
|
||||||
{item.status}
|
{item.status}
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="notification-text"
|
className="notification-text"
|
||||||
@@ -218,7 +219,7 @@ export function NotificationsList() {
|
|||||||
<div
|
<div
|
||||||
className="notification-date"
|
className="notification-date"
|
||||||
>
|
>
|
||||||
{item.createdAt}
|
{item.createdAt ? `${formatDate(item.createdAt)}: ${formatDateTime(item.createdAt)}` : '---'}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
@@ -226,7 +227,7 @@ export function NotificationsList() {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
removeHandler(item.id);
|
removeHandler(item.id);
|
||||||
}}
|
}}
|
||||||
disabled={false}
|
disabled={loadingIds.has(item.id)}
|
||||||
>
|
>
|
||||||
{t('remove')}
|
{t('remove')}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user