All files / src/web/hooks useGroupCounts.ts

100% Statements 47/47
87.5% Branches 14/16
100% Functions 2/2
100% Lines 47/47

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 731x 1x                               1x 6x     6x   6x 3x   3x 3x 1x 1x 1x   2x 2x 2x 2x 2x 2x 2x 2x   2x 2x   2x 2x 4x 4x 3x 3x 4x 4x 1x 1x 2x 2x   2x 2x 2x 2x 2x 3x   3x 3x 3x 3x 6x   6x 6x  
import { optimizedNewsletterService } from '@common/services/optimizedNewsletterService';
import { useEffect, useMemo, useState } from 'react';
 
// Minimal shape we need from the caller
type GroupLike = { id: string; name: string; sources?: { id: string }[] };
 
// Minimal filter shape aligned with NewsletterService params naming used in Inbox
type BaseFilter = {
  search?: string;
  isRead?: boolean;
  isArchived?: boolean;
  isLiked?: boolean;
  tagIds?: string[];
  dateFrom?: string;
  dateTo?: string;
};
 
export function useGroupCounts(groups: GroupLike[] = [], baseFilter: BaseFilter = {}) {
  const [counts, setCounts] = useState<Record<string, number>>({});
 
  // Stable snapshot of inputs
  const input = useMemo(() => ({ groups, baseFilter }), [groups, baseFilter]);
 
  useEffect(() => {
    let cancelled = false;
 
    const run = async () => {
      if (!input.groups || input.groups.length === 0) {
        setCounts({});
        return;
      }
 
      const baseParams = {
        search: input.baseFilter.search,
        isRead: input.baseFilter.isRead,
        isArchived: input.baseFilter.isArchived,
        isLiked: input.baseFilter.isLiked,
        tagIds: input.baseFilter.tagIds,
        dateFrom: input.baseFilter.dateFrom,
        dateTo: input.baseFilter.dateTo,
        // small page; we only need count
        limit: 1,
      } as const;
 
      const results = await Promise.all(
        input.groups.map(async (g) => {
          const sourceIds = g.sources?.map((s) => s.id) || [];
          if (sourceIds.length === 0) return [g.id, 0] as const;
          try {
            const res = await optimizedNewsletterService.getAll({ ...baseParams, sourceIds });
            return [g.id, res.count || 0] as const;
          } catch {
            return [g.id, 0] as const;
          }
        })
      );
 
      if (!cancelled) {
        const next: Record<string, number> = {};
        results.forEach(([id, cnt]) => (next[id] = cnt));
        setCounts(next);
      }
    };
 
    run();
    return () => {
      cancelled = true;
    };
  }, [input]);
 
  return counts;
}