Add Company and Job Title filters to Members page - #37
Closed
Bjjj834 wants to merge 2 commits into
Closed
Conversation
jest-dom was already a devDependency but no setupTests.js imported it, so matchers like toBeInTheDocument/toHaveValue were unavailable to any test in the suite.
The Members page already loads the full ~993-row Google Sheet into the browser in one request and paginates/searches it client-side, so the new filters apply to the complete dataset rather than just the current page. - memberFilters.js: pure normalize/dedupe/match helpers (unit tested) - FilterCombobox.js: searchable dropdown shared by both filters — Company requires an exact (case/whitespace-insensitive) match against known values; Job Title uses case-insensitive keyword/contains matching so "CEO" matches "Founder / CEO", "Founder & CEO", etc. - ArmorMembers.js: wires up both filters alongside the existing search, combines all three with AND semantics, resets to page 1 on filter change (but not on initial URL-hydrated load), clamps page into range, syncs search/company/jobTitle/page to URL query params (omitting empty ones), adds removable filter chips, a Clear filters action, and an empty state for zero matches - Debounces the free-text search input (250ms) to avoid re-filtering on every keystroke Fixed a related race in FilterCombobox: its value-sync effect ran once on mount as all effects do, which could revert a user's first keystroke if the mount-time effect flush was delayed past that keystroke. Skipped that effect's first run since initial state already derives from props.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Members page (
/community/members, ~993 members / ~100 pages) only had a single free-text search box. Users had no way to narrow the list by Company or Job Title specifically.Current Members page behavior (investigated before making changes)
ArmorMembers.js, routed at/membersunderMain.js.SHEET_ID=1IREd2vCxo7rDGOoDUYtzoywVGLqqUFCsu3qGsA0HsMc, tabSheet-1) directly from the Google Sheets API in one request — no backend, no database, no paginated API.filtered.slice((page-1)*pageSize, page*pageSize),pageSize=10) over the full in-memory array.Company Namecolumn →member.company,Job Titlecolumn →member.title.Proposed solution
memberFilters.js— pure, unit-tested helpers: value normalization, deduped/sorted option lists (blank-free), and the three match functions (general search, Company = exact case/whitespace-insensitive match, Job Title = case-insensitive keyword/contains match).FilterCombobox.js— a shared searchable dropdown/autocomplete used for both filters, with keyboard navigation, an individual clear button, and accessible labeling.ArmorMembers.js— wires both filters in next to the existing search box, combines all three conditions with AND semantics, adds removable filter chips, a "Clear filters" action, and an empty state ("No members match the selected filters.") with its own clear action.useDebouncedValue.js— 250ms debounce for the free-text search box.setupTests.js—@testing-library/jest-domwas already a devDependency but never wired up (nosetupTests.jsexisted), so matchers liketoBeInTheDocument/toHaveValueweren't available to any test in the suite. Added the standard CRA setup file.Data and API changes
None. No backend/API changes — everything operates on the dataset already loaded into the browser, per the investigation above.
Filter and pagination behavior
?page=999against a narrower filter).?company=Anote&jobTitle=CEO&page=2), empty params omitted, so the page is refresh-safe and shareable.Manual verification (real data, not mocks)
Ran the app locally against the live Google Sheet (993 real members, 100 pages) and verified:
Tests completed
npm test), including 2 new suites:memberFilters.test.js(pure-logic unit tests) andArmorMembers.test.js(integration tests covering Company/Job Title filtering, AND-combination with search, case-insensitivity, keyword matching, page-reset-on-filter-change, filter persistence across pagination, clear-all and individual-chip clearing, empty state, deduped/blank-free dropdown options, URL hydration/sync, and loading/error states) — using a 25-row fixture specifically constructed so matches span pages 1, 2, and 3, to catch any "only filters the visible page" regression.npm run lint: 0 errors (160 pre-existing warnings elsewhere in the repo, none introduced by this change).npm run build(CI=false, matching this repo's owndeploy.yml/ci.ymlconvention): succeeds.Known limitations
ArmorMembers.jsstill calls the Google Sheets API with a hardcoded API key committed in source (pre-existing, unrelated to this PR — same pattern that was previously fixed inArmorReferrals.js). Not addressed here to keep this PR focused on the filtering feature.