shoc-frontend-new/src/components/notifications/use-notification-center.ts
2026-09-18 14:23:43 -03:00

47 lines
1.7 KiB
TypeScript

import { useMemo } from "react";
import { useNavigate } from "react-router";
import type { NotificationItem } from "@/domain/notifications/types/notification-feed";
import { useNotificationSession } from "@/domain/notifications/session/notification-session-context";
import { useNotificationFeed } from "@/domain/notifications/use-cases/use-notification-feed";
import { notificationTargetUrl } from "@/domain/notifications/utils/notification-target-url";
import {
isDismissable,
visibleNotificationSections,
} from "@/domain/notifications/utils/visible-notification-sections";
export function useNotificationCenter(onNavigate?: () => void) {
const navigate = useNavigate();
const feed = useNotificationFeed();
const { dismissedIds, readIds, dismiss, markRead } = useNotificationSession();
const sections = useMemo(
() => visibleNotificationSections(feed.data?.sections ?? [], dismissedIds),
[feed.data, dismissedIds],
);
const items = useMemo(() => sections.flatMap((section) => section.items), [sections]);
const unreadIds = useMemo(
() => new Set(items.filter((item) => !readIds.has(item.id)).map((item) => item.id)),
[items, readIds],
);
const open = (item: NotificationItem, url = notificationTargetUrl(item)) => {
markRead([item.id]);
if (url == null) return;
onNavigate?.();
navigate(url);
};
return {
sections,
unreadIds,
isLoading: feed.isLoading,
hasData: feed.data != null,
error: feed.error,
open,
dismiss: (item: NotificationItem) => dismiss([item.id]),
dismissAll: () => dismiss(items.filter(isDismissable).map((item) => item.id)),
markAllRead: () => markRead(items.map((item) => item.id)),
};
}
export type NotificationCenter = ReturnType<typeof useNotificationCenter>;