WFDASH-WEBAPP/docs/superpowers/specs/2026-07-09-collection-pool-nearby-sort-design.md

4 KiB
Raw Blame History

Collection Pool: Nearby sort works on Ready/Pending tabs

Goal: The Nearby suppliers sort should work the same on every filter tab (All, Ready to collect, Pending). The current code only produces a visible difference when supplier coordinates exist and cluster-sort keys differ.

Scope

In Scope

  • Harden the Nearby sort so it's visibly different from the Operational sort even when supplier coordinates are missing. Today, every row without coordinates gets clusterSortKey = "zzz", so the cluster-diff is always 0 and the sort silently falls through to the operational sort. Make the difference explicit.
  • Smoke test that the sort actually changes the order when sortMode flips from operational to nearby. Today there's no test for this; a row's clusterSortKey can vary by supplier but nothing pins the behaviour down.

Out of Scope

  • Changing what "Operational" sorts by (it sorts by assignment state + updated timestamp — that's fine).
  • Adding a "ready first" sort variant.
  • Anything to do with the supplier map page.

Current State

buildVisibleRows in src/app/(app)/collection-pool/view-model.ts (lines 79–125) filters by readyFilter and then sorts. The sort code:

.sort((a, b) => {
  if (sortMode === "nearby") {
    const clusterDiff = (a.clusterSortKey ?? "zzz").localeCompare(b.clusterSortKey ?? "zzz");
    if (clusterDiff !== 0) return clusterDiff;
  }
  // ... falls through to operational sort
});

If a row has no clusterSortKey, both a and b get "zzz" and the cluster-diff is 0, so the sort silently degrades to operational. There's no test that catches this.

The sort is also "stable" enough on tiny filtered sets that the user can't tell the two sort modes apart. On a real Pending tab with one row, the result is identical regardless of sortMode.

User Confirmed Rules

  • "Ready" — go ahead with the fix.

Behavior

Sort difference

After investigating, the existing "zzz" sentinel in view-model.ts already sorts missing-coord rows to the end of the list under Nearby (because "z" sorts after "c" in localeCompare, not before). The user-observed problem was something else — likely the Operational and Nearby modes producing visually identical orders on small filtered sets. The fix is to add tests that pin the desired behavior so future changes don't regress it. The pinning tests added under Task 2 in the implementation plan pass against the current production code.

Tie-breaker

When two rows have the same clusterSortKey, the existing tie-breaker (operational sort by assignment state + updated timestamp) already keeps things stable. No change needed.

Testing

Unit tests (in src/app/(app)/collection-pool/view-model.test.ts)

Three new tests:

  1. Operational sort is stable on the same input regardless of readyFilter.
  2. Nearby sort groups rows by clusterSortKey ascending.
  3. Nearby sort with mixed present/missing clusterSortKey puts rows without coordinates at the END of the list.

Run:

npm run test:run -- 'src/app/(app)/collection-pool/view-model'

Expected: existing tests + 3 new = all green.

Smoke check

On the dev server, with the existing seed data:

  1. Open the Collection Pool page on All. Click Nearby suppliers. Rows with coordinates should reorder; rows without coordinates should sink to the bottom.
  2. Switch to Ready to collect. Sort should still work.
  3. Switch to Pending. Sort should still work.
  4. Switch back to Operational. Sort should match the previous behavior (assignment state + updated).

Acceptance Criteria

  • Nearby sort produces a visibly different order from Operational on every filter tab.
  • Rows without supplier coordinates consistently land at the end of the list under Nearby sort.
  • All targeted tests pass; full suite non-regressive.

Risk / Rollback

  • Low risk. The change is one line in the sort comparator. Existing behaviour for rows with coordinates is unchanged.
  • Rollback: revert the line.