feat(layout): unified Inbox + UserMenu extraction
Replaces the topbar's separate AlertBell + NotificationBell with a single Inbox popover that tabs between alerts and notifications. NotificationBell keeps a popover-gate so it doesn't fire its list fetch when Inbox is mounted alongside it. Extracts the user dropdown into <UserMenu> and moves the port switcher + role label + theme toggle into the sidebar footer so the topbar can reclaim space for breadcrumbs and command search. Adds dedicated Insights / Receipts nav sections in the sidebar (scaffolds the website-analytics + upload-receipts entry points). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Bell } from 'lucide-react';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
@@ -27,11 +28,18 @@ interface NotificationListResponse {
|
||||
export function NotificationBell() {
|
||||
const { unreadCount } = useNotifications();
|
||||
const queryClient = useQueryClient();
|
||||
// Track popover open state so we only fire the list fetch when the user
|
||||
// actually opens the bell. Without this, an instance of NotificationBell
|
||||
// mounted alongside <Inbox /> would populate the same ['notifications',
|
||||
// 'list'] cache key without the gating Inbox carefully applies, defeating
|
||||
// Inbox's enabled-on-open optimization.
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const { data, isLoading } = useQuery<NotificationListResponse>({
|
||||
queryKey: ['notifications', 'list'],
|
||||
queryFn: () => apiFetch('/api/v1/notifications?limit=20'),
|
||||
staleTime: 30_000,
|
||||
enabled: open,
|
||||
});
|
||||
|
||||
const markReadMutation = useMutation({
|
||||
@@ -52,7 +60,7 @@ export function NotificationBell() {
|
||||
const notifications = data?.data ?? [];
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="relative">
|
||||
<Bell className="h-5 w-5" />
|
||||
|
||||
Reference in New Issue
Block a user