Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
Implements Phase 1 of notification bell feature with: - NotificationBell component with badge counter (99+ max) - useNotifications hook with 30s polling and caching - Notifications API client for backend integration - Integration into AppShell header next to user avatar - Responsive dropdown (400px desktop, full-width mobile) - Empty state, loading, and error handling - Optimistic UI updates for mark as read - Animated badge with pulse effect - Icon mapping for notification types 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
73 lines
1.9 KiB
TypeScript
73 lines
1.9 KiB
TypeScript
import { apiClient } from './client';
|
|
|
|
export interface Notification {
|
|
id: string;
|
|
userId: string;
|
|
type: 'feeding' | 'sleep' | 'diaper' | 'medication' | 'milestone' | 'family' | 'system' | 'reminder';
|
|
title: string;
|
|
message: string;
|
|
data?: Record<string, any>;
|
|
isRead: boolean;
|
|
isDismissed: boolean;
|
|
createdAt: string;
|
|
readAt?: string | null;
|
|
dismissedAt?: string | null;
|
|
}
|
|
|
|
export interface GetNotificationsParams {
|
|
limit?: number;
|
|
offset?: number;
|
|
isRead?: boolean;
|
|
type?: Notification['type'];
|
|
}
|
|
|
|
export interface GetNotificationsResponse {
|
|
notifications: Notification[];
|
|
total: number;
|
|
unreadCount: number;
|
|
}
|
|
|
|
export const notificationsApi = {
|
|
/**
|
|
* Get user notifications with optional filters
|
|
*/
|
|
async getNotifications(params?: GetNotificationsParams): Promise<GetNotificationsResponse> {
|
|
const { data } = await apiClient.get<GetNotificationsResponse>('/notifications', { params });
|
|
return data;
|
|
},
|
|
|
|
/**
|
|
* Mark a notification as read
|
|
*/
|
|
async markAsRead(notificationId: string): Promise<Notification> {
|
|
const { data } = await apiClient.patch<Notification>(`/notifications/${notificationId}/read`);
|
|
return data;
|
|
},
|
|
|
|
/**
|
|
* Mark all notifications as read
|
|
*/
|
|
async markAllAsRead(): Promise<{ count: number }> {
|
|
const { data } = await apiClient.patch<{ count: number }>('/notifications/mark-all-read');
|
|
return data;
|
|
},
|
|
|
|
/**
|
|
* Dismiss a notification
|
|
*/
|
|
async dismiss(notificationId: string): Promise<Notification> {
|
|
const { data } = await apiClient.patch<Notification>(`/notifications/${notificationId}/dismiss`);
|
|
return data;
|
|
},
|
|
|
|
/**
|
|
* Get unread notification count
|
|
*/
|
|
async getUnreadCount(): Promise<number> {
|
|
const { data } = await apiClient.get<GetNotificationsResponse>('/notifications', {
|
|
params: { limit: 1, isRead: false },
|
|
});
|
|
return data.unreadCount;
|
|
},
|
|
};
|