Skip to content

feat: replace spoofAvailabilityCounts with real per-category API counts #33

Description

@mekarpeles

Problem

utils/filters.js exports a function that generates fake per-availability counts:

export function spoofAvailabilityCounts(numFound) {
  const counts = {};
  for (const opt of AVAILABILITY_OPTIONS) {
    counts[opt.value] = Math.round(numFound * opt.fraction);
  }
  return counts;
}

The fractions (1.0, 0.092, 0.054, 0.036) are hardcoded estimates. If the availability distribution of the catalog changes, or if we display these numbers prominently in the UI, they will silently be wrong. The function's own comment says: "Replace with real per-category searches once the UX stabilises."

The UX has stabilised.

Proposed approach

Issue parallel fetch requests — one per availability option — and aggregate the numFound values:

async function fetchAvailabilityCounts(q, filters, { signal, apiBase = '' } = {}) {
  const options = AVAILABILITY_OPTIONS.filter(o => o.value !== '');
  const results = await Promise.allSettled(
    options.map(opt =>
      fetch(`${apiBase}/api/search?${buildSearchParams(q, { ...filters, availability: opt.value }, 1, 0)}`, { signal })
        .then(r => r.json())
        .then(d => [opt.value, d.numFound ?? 0])
    )
  );
  return Object.fromEntries(
    results.filter(r => r.status === 'fulfilled').map(r => r.value)
  );
}

This adds 3 parallel network requests. Cache the result by (q, filters) key if performance is a concern.

Tests needed

  • Unit: returns a count for every non-empty availability option
  • Unit: handles partial failure (one fetch rejects) gracefully
  • Unit: passes the correct availability param to each sub-request

Risk

Low correctness risk (it's additive). Medium performance risk — 3 extra fetches per search. Consider a debounce or lazy-load strategy if the counts are only shown in a dropdown rather than the primary results header.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions