@@ -5,13 +5,33 @@ import { env } from '@/env.mjs';
55import { Inbox } from '@novu/nextjs' ;
66import { useSession } from '@/utils/auth-client' ;
77import { Bell , Settings } from 'lucide-react' ;
8+ import { useState , useRef , useEffect } from 'react' ;
89
910export function NotificationBell ( ) {
1011 const applicationIdentifier = env . NEXT_PUBLIC_NOVU_APPLICATION_IDENTIFIER ;
1112 const { data : session } = useSession ( ) ;
1213 const sessionData = session ?. session ;
1314 const pathname = usePathname ( ) ;
1415 const orgId = pathname ?. split ( '/' ) [ 1 ] || null ;
16+ const [ visible , setVisible ] = useState ( false ) ;
17+ const inboxRef = useRef < HTMLDivElement > ( null ) ;
18+
19+ // Handle click outside to close inbox
20+ useEffect ( ( ) => {
21+ function handleClickOutside ( event : MouseEvent ) {
22+ if ( inboxRef . current && ! inboxRef . current . contains ( event . target as Node ) ) {
23+ setVisible ( false ) ;
24+ }
25+ }
26+
27+ if ( visible ) {
28+ document . addEventListener ( 'mousedown' , handleClickOutside ) ;
29+ }
30+
31+ return ( ) => {
32+ document . removeEventListener ( 'mousedown' , handleClickOutside ) ;
33+ } ;
34+ } , [ visible ] ) ;
1535
1636 // Don't render if we don't have the required config
1737 if ( ! applicationIdentifier || ! sessionData ?. userId || ! orgId ) {
@@ -20,7 +40,6 @@ export function NotificationBell() {
2040
2141 const appearance = {
2242 icons : {
23- bell : ( ) => < Bell size = { 20 } /> ,
2443 cogs : ( ) => < Settings size = { 20 } /> ,
2544 } ,
2645 elements : {
@@ -40,18 +59,33 @@ export function NotificationBell() {
4059 } ;
4160
4261 return (
43- < Inbox
44- applicationIdentifier = { applicationIdentifier }
45- subscriber = { `${ sessionData . userId } -${ orgId } ` }
46- appearance = { appearance }
47- renderSubject = { ( notification ) => < strong > { notification . subject } </ strong > }
48- renderBody = { ( notification ) => (
49- < div className = "mt-1" >
50- < p className = "text-xs text-muted-foreground" >
51- { notification . body }
52- </ p >
53- </ div >
54- ) }
55- />
62+ < div ref = { inboxRef } >
63+ < Inbox
64+ applicationIdentifier = { applicationIdentifier }
65+ subscriber = { `${ sessionData . userId } -${ orgId } ` }
66+ appearance = { appearance }
67+ open = { visible }
68+ renderBell = { ( { total } ) => (
69+ < button
70+ onClick = { ( ) => setVisible ( ! visible ) }
71+ className = "relative cursor-pointer"
72+ >
73+ < Bell size = { 20 } />
74+ { total > - 1 && (
75+ < span className = "absolute top-0 right-0 h-2 w-2 rounded-full bg-red-500" />
76+ ) }
77+ </ button >
78+ ) }
79+ renderSubject = { ( notification ) => < strong > { notification . subject } </ strong > }
80+ renderBody = { ( notification ) => (
81+ < div className = "mt-1" >
82+ < p className = "text-xs text-muted-foreground" >
83+ { notification . body }
84+ </ p >
85+ </ div >
86+ ) }
87+ onNotificationClick = { ( ) => setVisible ( false ) }
88+ />
89+ </ div >
5690 ) ;
5791}
0 commit comments