import type { PageCommentsView } from '@dorfteich/shared'; import { useQuery, useQueryClient, type UseQueryResult } from '@tanstack/react-query'; import { apiGet } from '../lib/api'; /** * Page comments data (issue #92). One query per page, shared between the * panel and the toggle button's unread badge. "Unread" is a purely local * notion: newer than the last time this browser opened the panel * (localStorage — no server round-trip, per the issue's design). */ export const commentsQueryKey = (pageId: string): [string, string] => ['comments', pageId]; export function useComments(pageId: string | undefined): UseQueryResult { return useQuery({ queryKey: commentsQueryKey(pageId ?? ''), queryFn: () => apiGet(`/pages/${pageId}/comments`), enabled: Boolean(pageId), }); } export function useInvalidateComments(pageId: string): () => Promise { const queryClient = useQueryClient(); return () => queryClient.invalidateQueries({ queryKey: commentsQueryKey(pageId) }); } const seenKey = (pageId: string): string => `dorfteich.comments.seen.${pageId}`; export function markCommentsSeen(pageId: string): void { try { localStorage.setItem(seenKey(pageId), new Date().toISOString()); } catch { // Storage full/blocked: the badge simply stays — never break the page. } } /** Comments newer than the last visit, not authored by the viewer. */ export function unreadCount( view: PageCommentsView | undefined, pageId: string, viewerId: string | undefined, ): number { if (!view) return 0; let since = 0; try { const stored = localStorage.getItem(seenKey(pageId)); since = stored ? new Date(stored).getTime() : 0; } catch { since = 0; } let count = 0; for (const thread of view.threads) { for (const comment of [thread.root, ...thread.replies]) { if (new Date(comment.createdAt).getTime() > since && comment.author?.id !== viewerId) { count += 1; } } } return count; }