Corp/frontend/src/lib/api/notifications.ts
lizerk 3ca4d108b6 refactor: split monolithic api.ts into domain modules, extract AppShell calendar/mobile concerns
- Split frontend/src/lib/api.ts (2042 lines) into 12 focused domain modules:
  client.ts (base HTTP/auth), calendar.ts, documents.ts, employees.ts,
  equipment.ts, feed.ts, messages.ts, notifications.ts, procurement.ts,
  requests.ts, utils.ts, and index.ts barrel that preserves all existing imports
- Extract calendar modal state from AppShell into useCalendarModals hook
- Extract CalendarModals and MobileDrawers into components/layout/
- AppShell: 745 → 460 lines, focused on layout concerns only
- Fix setState-in-effect lint error with startTransition pattern
- Stabilize notifications memo to prevent unnecessary re-renders
- Fix flaky WS test: handle CancelledError in channels-testing cleanup
- All 609 backend tests pass, TypeScript typecheck clean, ESLint clean
2026-04-01 15:56:10 +03:00

38 lines
2.8 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import type { RequestFn } from './utils';
export function createNotificationsApi(request: RequestFn) {
return {
getNotifications: (params?: { page?: number; page_size?: number; unread_only?: boolean }) => {
const qp = new URLSearchParams();
if (params?.page) qp.append('page', String(params.page));
if (params?.page_size) qp.append('page_size', String(params.page_size));
if (params?.unread_only) qp.append('unread_only', 'true');
const qs = qp.toString();
return request(qs ? `/api/v1/notifications/?${qs}` : '/api/v1/notifications/');
},
getUnreadNotificationsCount: (): Promise<{ count: number }> => request('/api/v1/notifications/count/'),
markNotificationAsRead: (id: number): Promise<void> => request(`/api/v1/notifications/${id}/read/`, { method: 'POST' }),
markAllNotificationsAsRead: (): Promise<void> => request('/api/v1/notifications/read-all/', { method: 'POST' }),
markCategoryAsRead: async (category: string): Promise<{ status: string; count: number }> => {
const { getVerbsByCategory } = await import('../verbTranslations');
const verbs = getVerbsByCategory(category);
return request('/api/v1/notifications/category/read/', { method: 'POST', body: JSON.stringify({ verbs, category }) });
},
// Push
getVapidPublicKey: (): Promise<{ vapid_public_key: string }> => request('/api/v1/notifications/push/vapid-key/'),
subscribePush: (data: { endpoint: string; keys: { p256dh: string; auth: string }; device_name?: string }): Promise<{ status: string; message: string; created: boolean }> =>
request('/api/v1/notifications/push/subscribe/', { method: 'POST', body: JSON.stringify(data) }),
unsubscribePush: (endpoint?: string): Promise<{ status: string; message: string }> =>
request('/api/v1/notifications/push/unsubscribe/', { method: 'DELETE', body: JSON.stringify({ endpoint }) }),
getPushSubscriptions: (): Promise<{ subscriptions: any[] }> => request('/api/v1/notifications/push/subscriptions/'),
// CRUD
deleteNotification: (id: number): Promise<void> => request(`/api/v1/notifications/${id}/`, { method: 'DELETE' }),
deleteAllReadNotifications: (): Promise<{ status: string; count: number }> => request('/api/v1/notifications/delete-all-read/', { method: 'DELETE' }),
// Preferences
getNotificationPreferences: () => request('/api/v1/notifications/preferences/'),
updateNotificationPreferences: (data: Record<string, any>) => request('/api/v1/notifications/preferences/', { method: 'PUT', body: JSON.stringify(data) }),
getVerbTypes: (): Promise<{ verb_types: any[] }> => request('/api/v1/notifications/verb-types/'),
};
}