feat: add real-time notification system with Socket.IO client
Implements the frontend notification client for TEC-2217: 1. notifications-api.ts — API client for list, unread-count, markAsRead, markAllAsRead endpoints 2. notifications-store.ts — Zustand store for notification state (recent list, unread count, dropdown open state) 3. use-socket-notifications.ts — Socket.IO hook that connects with httpOnly cookie auth, listens for notification:new events, auto-reconnects, and syncs unread count on (re)connect 4. notification-bell.tsx — Bell icon with unread badge + dropdown showing 10 most recent notifications with time-ago formatting, mark-as-read on click, mark-all-as-read, and "Xem tất cả" link 5. notifications-provider.tsx — Provider wired into locale layout (inside AuthProvider) to initialize Socket.IO connection 6. Dashboard header — NotificationBell placed before LanguageSwitcher Added socket.io-client dependency. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useState } from 'react';
|
||||
import { NotificationBell } from '@/components/notifications/notification-bell';
|
||||
import { useTheme } from '@/components/providers/theme-provider';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { LanguageSwitcher } from '@/components/ui/language-switcher';
|
||||
@@ -247,6 +248,7 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
|
||||
{user.fullName}
|
||||
</span>
|
||||
)}
|
||||
<NotificationBell />
|
||||
<LanguageSwitcher />
|
||||
<Button
|
||||
variant="ghost"
|
||||
|
||||
@@ -4,6 +4,7 @@ import { notFound } from 'next/navigation';
|
||||
import { NextIntlClientProvider } from 'next-intl';
|
||||
import { getMessages, getTranslations } from 'next-intl/server';
|
||||
import { AuthProvider } from '@/components/providers/auth-provider';
|
||||
import { NotificationsProvider } from '@/components/providers/notifications-provider';
|
||||
import { QueryProvider } from '@/components/providers/query-provider';
|
||||
import { ThemeProvider } from '@/components/providers/theme-provider';
|
||||
import { WebVitals } from '@/components/providers/web-vitals';
|
||||
@@ -122,8 +123,10 @@ export default async function LocaleLayout({
|
||||
<ThemeProvider>
|
||||
<QueryProvider>
|
||||
<AuthProvider>
|
||||
<WebVitals />
|
||||
{children}
|
||||
<NotificationsProvider>
|
||||
<WebVitals />
|
||||
{children}
|
||||
</NotificationsProvider>
|
||||
</AuthProvider>
|
||||
</QueryProvider>
|
||||
</ThemeProvider>
|
||||
|
||||
Reference in New Issue
Block a user