feature/IO-3096-GlobalNotifications - Checkpoint - clicking an individual notification will mark it read

This commit is contained in:
Dave Richer
2025-02-26 16:30:16 -05:00
parent e4d437018d
commit abd530b8b2
4 changed files with 143 additions and 131 deletions

View File

@@ -1,13 +1,8 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { useMutation, useQuery } from "@apollo/client";
import { useQuery } from "@apollo/client";
import { connect } from "react-redux";
import NotificationCenterComponent from "./notification-center.component";
import {
GET_NOTIFICATIONS,
MARK_ALL_NOTIFICATIONS_READ,
MARK_NOTIFICATION_READ,
GET_UNREAD_COUNT
} from "../../graphql/notifications.queries";
import { GET_NOTIFICATIONS } from "../../graphql/notifications.queries";
import { useSocket } from "../../contexts/SocketIO/socketContext.jsx";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors.js";
@@ -16,7 +11,7 @@ export function NotificationCenterContainer({ visible, onClose, bodyshop }) {
const [showUnreadOnly, setShowUnreadOnly] = useState(false);
const [notifications, setNotifications] = useState([]);
const [error, setError] = useState(null);
const { isConnected } = useSocket();
const { isConnected, markNotificationRead, markAllNotificationsRead } = useSocket();
const userAssociationId = bodyshop?.associations?.[0]?.id;
@@ -51,106 +46,6 @@ export function NotificationCenterContainer({ visible, onClose, bodyshop }) {
}
});
const [markAllReadMutation, { error: mutationError }] = useMutation(MARK_ALL_NOTIFICATIONS_READ, {
variables: { associationid: userAssociationId },
update: (cache, { data: mutationData }) => {
const timestamp = new Date().toISOString();
cache.modify({
fields: {
notifications(existing = [], { readField }) {
return existing.map((notif) => {
if (readField("read", notif) === null && readField("associationid", notif) === userAssociationId) {
return { ...notif, read: timestamp };
}
return notif;
});
},
notifications_aggregate() {
return { aggregate: { count: 0, __typename: "notifications_aggregate_fields" } };
}
}
});
if (isConnected) {
const cachedNotifications = cache.readQuery({
query: GET_NOTIFICATIONS,
variables: {
limit: 20,
offset: 0,
where: whereClause
}
});
if (cachedNotifications?.notifications) {
cache.writeQuery({
query: GET_NOTIFICATIONS,
variables: {
limit: 20,
offset: 0,
where: whereClause
},
data: {
notifications: cachedNotifications.notifications.map((notif) =>
notif.read === null ? { ...notif, read: timestamp } : notif
)
}
});
}
}
},
onError: (err) => {
setError(err.message);
console.error("MARK_ALL_NOTIFICATIONS_READ error:", err);
}
});
const [markNotificationRead] = useMutation(MARK_NOTIFICATION_READ, {
update: (cache, { data: { update_notifications } }) => {
const timestamp = new Date().toISOString();
const updatedNotification = update_notifications.returning[0];
// Update the notifications list
cache.modify({
fields: {
notifications(existing = [], { readField }) {
return existing.map((notif) => {
if (readField("id", notif) === updatedNotification.id) {
return { ...notif, read: timestamp };
}
return notif;
});
}
}
});
// Update the unread count in notifications_aggregate
const unreadCountQuery = cache.readQuery({
query: GET_UNREAD_COUNT,
variables: { associationid: userAssociationId }
});
if (unreadCountQuery?.notifications_aggregate?.aggregate?.count > 0) {
cache.writeQuery({
query: GET_UNREAD_COUNT,
variables: { associationid: userAssociationId },
data: {
notifications_aggregate: {
...unreadCountQuery.notifications_aggregate,
aggregate: {
...unreadCountQuery.notifications_aggregate.aggregate,
count: unreadCountQuery.notifications_aggregate.aggregate.count - 1
}
}
}
});
}
},
onError: (err) => {
setError(err.message);
console.error("MARK_NOTIFICATION_READ error:", err);
}
});
useEffect(() => {
if (data?.notifications) {
const processedNotifications = data.notifications
@@ -187,10 +82,10 @@ export function NotificationCenterContainer({ visible, onClose, bodyshop }) {
}, [data]);
useEffect(() => {
if (queryError || mutationError) {
setError(queryError?.message || mutationError?.message);
if (queryError) {
setError(queryError.message);
}
}, [queryError, mutationError]);
}, [queryError]);
const loadMore = useCallback(() => {
if (!loading && data?.notifications.length) {
@@ -213,19 +108,24 @@ export function NotificationCenterContainer({ visible, onClose, bodyshop }) {
setShowUnreadOnly(value);
};
const handleMarkAllRead = () => {
markAllReadMutation()
const handleMarkAllRead = useCallback(() => {
markAllNotificationsRead()
.then(() => {
const timestamp = new Date().toISOString();
setNotifications((prev) => {
const updatedNotifications = prev.map((notif) =>
notif.read === null && notif.associationid === userAssociationId ? { ...notif, read: timestamp } : notif
notif.read === null && notif.associationid === userAssociationId
? {
...notif,
read: timestamp
}
: notif
);
return [...updatedNotifications];
});
})
.catch((e) => console.error(`Error marking all notifications read: ${e?.message || ""}`));
};
}, [markAllNotificationsRead, userAssociationId]);
const handleNotificationClick = useCallback(
(notificationId) => {