add read notifications route and update notifications behavior

This commit is contained in:
2026-01-08 15:00:43 +01:00
parent 21259f2838
commit 42748ad722
6 changed files with 301 additions and 11 deletions
+48 -9
View File
@@ -1,25 +1,54 @@
import styles from "./Header.module.css"
import { Link, NavLink } from "react-router";
import { useEffect, useRef, useState } from "react";
import {useContext, useEffect, useRef, useState} from "react";
import getUserNotifications from "../../utils/notifications/getUserNotifications.js";
import deleteNotificationUser from "../../utils/notifications/deleteNotificationUser.js";
import initEcho from "../../utils/echo/initEcho.js"
import readNotifications from "../../utils/notifications/readNotifications.js";
import {AuthContext} from "../../contexts/auth/AuthContext.js";
function Header() {
const { update } = useContext(AuthContext);
const [notificationMenu, setnotificationMenu] = useState(false);
const [unreadNotification, setunreadNotification] = useState(true);
const [unreadNotification, setunreadNotification] = useState(false);
const [mobileMenu, setMobileMenu] = useState(false);
const [notifications, setNotifications] = useState([]);
const notificationRef = useRef(null);
useEffect(() => {
const echo = initEcho();
echo.private("admins-private")
.listen(".user.created", (event) => {
const newNotification = {
id: Date.now(),
content: `Nouvel demande d'inscription : ${event.user.name} ${event.user.lastname}`,
is_new: true
};
setNotifications(prevNotifications => [newNotification, ...prevNotifications]);
setunreadNotification(true);
});
return () => {
echo.leave("admins-private");
};
}, []);
useEffect(() => {
async function loadNotifications() {
const notifData = await getUserNotifications();
const data = notifData || [];
setNotifications(notifData || []);
const hasUnread = data.some(n => n.pivot && n.pivot.unread === 1);
setunreadNotification(hasUnread);
}
loadNotifications();
const handleClickOutside = (event) => {
if (
notificationRef.current &&
@@ -40,12 +69,25 @@ function Header() {
const toggleNotificationMenu = async () => {
try {
setnotificationMenu(!notificationMenu);
if (unreadNotification) {
const result = await readNotifications();
if (result) {
setunreadNotification(false);
update();
}
}
} catch (err) {
console.error('Erreur suppression notification :', err);
}
}
async function deleteNotification(notificationId) {
try {
const result = await deleteNotificationUser(notificationId);
console.log(result);
if (result) {
setNotifications(prev => prev.filter(n => n.id !== notificationId));
}
@@ -81,10 +123,7 @@ function Header() {
<div className={styles.headerRightContent}>
<button
className={`${styles.bellBtn} ${notificationMenu ? styles.activeBellBtn : ""}`}
onClick={() => {
setnotificationMenu(!notificationMenu);
setunreadNotification(false);
}}
onClick={() => {toggleNotificationMenu();}}
>
<img className={styles.notificationsImg} src="bell.svg" alt="notifications"/>
{unreadNotification && <span className={styles.notificationBadge}></span>}
+21
View File
@@ -0,0 +1,21 @@
import Echo from "laravel-echo";
import Pusher from "pusher-js";
window.Pusher = Pusher;
export default function initEcho() {
const echoInstance = new Echo({
broadcaster: import.meta.env.VITE_BROADCASTER,
key: import.meta.env.VITE_REVERB_KEY,
wsHost: import.meta.env.VITE_REVERB_HOST,
wsPort: Number(import.meta.env.VITE_REVERB_PORT),
forceTLS: import.meta.env.VITE_FORCE_TLS === 'true',
disableStats: import.meta.env.VITE_DISABLE_STATS === 'true',
encrypted: import.meta.env.VITE_ENCRYPTED === 'true',
cluster: import.meta.env.VITE_CLUSTER,
enabledTransports: ['ws', 'wss'],
});
window.Echo = echoInstance;
return echoInstance;
}
@@ -0,0 +1,27 @@
import getXSRFToken from "../getXSRF.js";
export default async function readNotifications() {
const csrfToken = await getXSRFToken();
try {
const res = await fetch(`http://${import.meta.env.VITE_API_URL}/api/users/notifications/read`, {
method: 'POST',
credentials: 'include',
headers: {
'Accept': 'application/json',
'X-XSRF-TOKEN': csrfToken,
'Content-Type': 'application/json',
},
});
if (!res.ok) {
throw new Error(`Erreur serveur : ${res.status}`);
}
return await res.json();
} catch (err) {
console.error('Erreur :', err);
return null;
}
}