All files / src/features/collections collectionsList.ts

100% Statements 17/17
100% Branches 11/11
100% Functions 6/6
100% Lines 15/15

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        2x       25x     40x               25x 25x 25x   81x 28x         23x 23x 19x 6x 13x 2x 11x    
import type { Collection } from "@/types";
import { viewHref } from "@/components/ui/viewHref";
 
export type CollectionsView = "all" | "archived";
export const COLLECTION_PILLS: [CollectionsView, string][] = [["all", "All"], ["archived", "Archived"]];
 
/** `?status=archived` is the only non-default view; the retired "active" and anything else is All. */
export function collectionsViewFrom(status: unknown): CollectionsView {
  return status === "archived" ? "archived" : "all";
}
 
export const collectionsViewHref = (view: CollectionsView, q: string) => viewHref("/collections", view, q);
 
/** All = not archived (no status is silently hidden), Archived = archived; plain-text
 *  search (never a pattern) over name and description. */
export function filterCollections(
  collections: Collection[],
  opts: { view: CollectionsView; q: string },
): Collection[] {
  const wantArchived = opts.view === "archived";
  const needle = opts.q.trim().toLocaleLowerCase();
  return collections.filter(
    (c) =>
      (c.status === "archived") === wantArchived &&
      (!needle || [c.name, c.description].some((text) => text?.toLocaleLowerCase().includes(needle))),
  );
}
 
export function collectionsEmptyState(opts: { hasAny: boolean; view: CollectionsView; q: string }) {
  const q = opts.q.trim();
  if (q) return { heading: `Nothing matches “${q}”`, message: "Try another word, or clear the search." };
  if (opts.view === "archived")
    return { heading: "Nothing archived", message: "Collections you archive rest here, ready to come back whenever you like." };
  if (!opts.hasAny)
    return { heading: "Nothing here yet", message: "Start a new collection whenever you’re ready — there’s no rush." };
  return { heading: "Nothing here right now", message: "Your archived collections are under Archived." };
}