Message count

This commit is contained in:
Brad Traversy
2024-07-15 12:02:48 -04:00
parent a51dbc3276
commit 2c9dccd4b0
6 changed files with 94 additions and 11 deletions
+26
View File
@@ -0,0 +1,26 @@
'use server';
import connectDB from '@/config/database';
import Message from '@/models/Message';
import { getSessionUser } from '@/utils/getSessionUser';
async function getUnreadMessageCount() {
await connectDB();
const sessionUser = await getSessionUser();
if (!sessionUser || !sessionUser.user) {
return { error: 'User ID is required' };
}
const { userId } = sessionUser;
const count = await Message.countDocuments({
recipient: userId,
read: false,
});
return { count };
}
export default getUnreadMessageCount;
+3
View File
@@ -1,5 +1,6 @@
import Navbar from '@/components/Navbar'; import Navbar from '@/components/Navbar';
import AuthProvider from '@/components/AuthProvider'; import AuthProvider from '@/components/AuthProvider';
import { GlobalProvider } from '@/context/GlobalContext';
import { ToastContainer } from 'react-toastify'; import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css'; import 'react-toastify/dist/ReactToastify.css';
import '@/assets/styles/globals.css'; import '@/assets/styles/globals.css';
@@ -13,6 +14,7 @@ export const metadata = {
const MainLayout = ({ children }) => { const MainLayout = ({ children }) => {
return ( return (
<AuthProvider> <AuthProvider>
<GlobalProvider>
<html lang='en'> <html lang='en'>
<body> <body>
<Navbar /> <Navbar />
@@ -20,6 +22,7 @@ const MainLayout = ({ children }) => {
<ToastContainer /> <ToastContainer />
</body> </body>
</html> </html>
</GlobalProvider>
</AuthProvider> </AuthProvider>
); );
}; };
+5
View File
@@ -3,20 +3,25 @@ import { useState } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import markMessageAsRead from '@/app/actions/markMessageAsRead'; import markMessageAsRead from '@/app/actions/markMessageAsRead';
import deleteMessage from '@/app/actions/deleteMessage'; import deleteMessage from '@/app/actions/deleteMessage';
import { useGlobalContext } from '@/context/GlobalContext';
const MessageCard = ({ message }) => { const MessageCard = ({ message }) => {
const [isRead, setIsRead] = useState(message.read); const [isRead, setIsRead] = useState(message.read);
const [isDeleted, setIsDeleted] = useState(false); const [isDeleted, setIsDeleted] = useState(false);
const { setUnreadCount } = useGlobalContext();
const handleReadClick = async () => { const handleReadClick = async () => {
const read = await markMessageAsRead(message._id); const read = await markMessageAsRead(message._id);
setIsRead(read); setIsRead(read);
setUnreadCount((prevCount) => (read ? prevCount - 1 : prevCount + 1));
toast.success(`Marked as ${read ? 'read' : 'new'}`); toast.success(`Marked as ${read ? 'read' : 'new'}`);
}; };
const handleDeleteClick = async () => { const handleDeleteClick = async () => {
await deleteMessage(message._id); await deleteMessage(message._id);
setIsDeleted(true); setIsDeleted(true);
setUnreadCount((prevCount) => (isRead ? prevCount : prevCount - 1));
toast.success('Message Deleted'); toast.success('Message Deleted');
}; };
+2 -4
View File
@@ -7,6 +7,7 @@ import { FaGoogle } from 'react-icons/fa';
import logo from '@/assets/images/logo-white.png'; import logo from '@/assets/images/logo-white.png';
import profileDefault from '@/assets/images/profile.png'; import profileDefault from '@/assets/images/profile.png';
import { signIn, signOut, useSession, getProviders } from 'next-auth/react'; import { signIn, signOut, useSession, getProviders } from 'next-auth/react';
import UnreadMessageCount from './UnreadMessageCount';
const Navbar = () => { const Navbar = () => {
const { data: session } = useSession(); const { data: session } = useSession();
@@ -151,10 +152,7 @@ const Navbar = () => {
/> />
</svg> </svg>
</button> </button>
<span className='absolute top-0 right-0 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-white transform translate-x-1/2 -translate-y-1/2 bg-red-600 rounded-full'> <UnreadMessageCount />
2
{/* <!-- Replace with the actual number of notifications --> */}
</span>
</Link> </Link>
{/* <!-- Profile dropdown button --> */} {/* <!-- Profile dropdown button --> */}
<div className='relative ml-3'> <div className='relative ml-3'>
+13
View File
@@ -0,0 +1,13 @@
'use client';
import { useGlobalContext } from '@/context/GlobalContext';
const UnreadMessageCount = () => {
const { unreadCount } = useGlobalContext();
return unreadCount > 0 ? (
<span className='absolute top-0 right-0 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-white transform translate-x-1/2 -translate-y-1/2 bg-red-600 rounded-full'>
{unreadCount}
</span>
) : null;
};
export default UnreadMessageCount;
+38
View File
@@ -0,0 +1,38 @@
'use client';
import getUnreadMessageCount from '@/app/actions/getUnreadMessageCount';
import { useSession } from 'next-auth/react';
import { createContext, useContext, useState, useEffect } from 'react';
// Create context
const GlobalContext = createContext();
// Create a provider
export function GlobalProvider({ children }) {
const [unreadCount, setUnreadCount] = useState(0);
const { data: session } = useSession();
useEffect(() => {
if (session && session.user) {
getUnreadMessageCount().then((res) => {
if (res.count) setUnreadCount(res.count);
});
}
}, [getUnreadMessageCount, session]);
return (
<GlobalContext.Provider
value={{
unreadCount,
setUnreadCount,
}}
>
{children}
</GlobalContext.Provider>
);
}
// Create a custom hook to access context
export function useGlobalContext() {
return useContext(GlobalContext);
}