feat: add notification bell polling to dashboard shell
- Poll /api/me/notifications/unread-count every 30 seconds - Show orange dot badge when unread count > 0 - Matches PRD requirement for real-time notifications
This commit is contained in:
parent
bbf11b91e1
commit
eee2c367ca
1 changed files with 53 additions and 12 deletions
|
|
@ -3,7 +3,7 @@
|
|||
* Used for pages that need actual backend connectivity
|
||||
* (My Profile, My Portfolio, Verification) instead of the preview mock.
|
||||
*/
|
||||
import { For, JSX, Show, createMemo } from 'solid-js';
|
||||
import { For, JSX, Show, createMemo, createSignal, onMount } from 'solid-js';
|
||||
import {
|
||||
User, Briefcase, LayoutDashboard, FolderOpen, MapPin, Star,
|
||||
CreditCard, Globe, ShieldCheck, HelpCircle, Settings,
|
||||
|
|
@ -65,6 +65,33 @@ export default function DashboardShell(props: Props) {
|
|||
return k.charAt(0).toUpperCase() + k.slice(1).toLowerCase();
|
||||
});
|
||||
|
||||
const [unreadCount, setUnreadCount] = createSignal(0);
|
||||
|
||||
// Fetch unread notification count
|
||||
const fetchUnreadCount = async () => {
|
||||
try {
|
||||
const token = typeof window !== 'undefined' ? window.sessionStorage.getItem('nxtgauge_access_token') || '' : '';
|
||||
if (!token) return;
|
||||
const res = await fetch('/api/me/notifications/unread-count', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
credentials: 'include',
|
||||
});
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
setUnreadCount(data.unread_count || 0);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to fetch unread count:', e);
|
||||
}
|
||||
};
|
||||
|
||||
// Start polling on mount
|
||||
onMount(() => {
|
||||
fetchUnreadCount();
|
||||
const interval = setInterval(fetchUnreadCount, 30000);
|
||||
return () => clearInterval(interval);
|
||||
});
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
|
|
@ -160,17 +187,31 @@ export default function DashboardShell(props: Props) {
|
|||
<p style={{ margin: '0', 'font-size': '15px', 'font-weight': '700', color: NAVY }}>
|
||||
{props.activeSidebar}
|
||||
</p>
|
||||
<div style={{ display: 'flex', 'align-items': 'center', gap: '12px' }}>
|
||||
<Bell size={18} style={{ color: '#9CA3AF' }} />
|
||||
<div style={{
|
||||
width: '32px', height: '32px', 'border-radius': '999px',
|
||||
background: ORANGE, color: '#fff', display: 'flex',
|
||||
'align-items': 'center', 'justify-content': 'center',
|
||||
'font-size': '13px', 'font-weight': '700',
|
||||
}}>
|
||||
{(props.userName || 'U').charAt(0).toUpperCase()}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'flex', 'align-items': 'center', gap: '12px' }}>
|
||||
<button type="button" style={{ position: 'relative', border: 'none', background: 'transparent', cursor: 'pointer', display: 'flex', 'align-items': 'center', 'justify-content': 'center', padding: 0 }}>
|
||||
<Bell size={18} style={{ color: '#9CA3AF' }} />
|
||||
<Show when={unreadCount() > 0}>
|
||||
<span style={{
|
||||
position: 'absolute',
|
||||
top: '-2px',
|
||||
right: '-2px',
|
||||
width: '8px',
|
||||
height: '8px',
|
||||
background: '#FF5E13',
|
||||
'border-radius': '50%',
|
||||
border: '1px solid white'
|
||||
}}></span>
|
||||
</Show>
|
||||
</button>
|
||||
<div style={{
|
||||
width: '32px', height: '32px', 'border-radius': '999px',
|
||||
background: ORANGE, color: '#fff', display: 'flex',
|
||||
'align-items': 'center', 'justify-content': 'center',
|
||||
'font-size': '13px', 'font-weight': '700',
|
||||
}}>
|
||||
{(props.userName || 'U').charAt(0).toUpperCase()}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* Page content */}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue