Skip to content

feat: volunteers list view (flat table) #476#500

Merged
need4deed merged 3 commits into
developfrom
feat/476-volunteers-list-view
May 11, 2026
Merged

feat: volunteers list view (flat table) #476#500
need4deed merged 3 commits into
developfrom
feat/476-volunteers-list-view

Conversation

@ivannissimrch
Copy link
Copy Markdown
Collaborator

Description

Adds the flat table list view for the volunteers search page (/dashboard/volunteers).
Reuses the team's shared core/common/Table primitives, same pattern as CommunicationTracker.tsx.

Related Issues

Closes #476

Changes

  • New VolunteerTableList.tsx and VolunteerTableRow.tsx , uses core/common/Table
  • 7 columns: Name, Type, Engagement, Matching, Language, District, Email
  • VolunteerListController.tsx : renders VolunteerTableList for the List tab
  • Tab labels fixed in Volunteers.tsx: "TABLE VIEW"/"MAP VIEW" to "List"/"Cards" (EN + DE)
  • New translation keys for the column headers
  • Match + Email show "—" since they're not on ApiVolunteerGetList
  • Also updated createEngagementStatusLabelMap keys were out of sync after Fix: Volunteers dashboard: selecting "Temporarily Unavailable" in the Engagement filter returns 0 results #430 #475 PR

Screenshots / Demos

Screenshot from 2026-05-07 09-21-00

Checklist

  • WITHIN THE SCOPE OF AN ISSUE; No unnecessary files included
  • Tests added/updated
  • Documentation updated
  • CI passes

@ivannissimrch ivannissimrch requested a review from nadavosa May 7, 2026 13:37
@nadavosa
Copy link
Copy Markdown
Collaborator

nadavosa commented May 7, 2026

Review

Overview: Adds a flat table/list view to the volunteer search page, toggled by the existing tab switcher. Uses the Table component system Hans built in src/components/core/common/Table/styles.ts. The structure is clean and the reuse of existing infrastructure is correct.


Bugs

1. createEngagementStatusLabelMap translation keys changed to non-existent vol-* keys

The PR changes the translation key references from:

t("dashboard.volunteers.filters.engagement.new")

to:

t("dashboard.volunteers.filters.engagement.vol-new")

But vol-new, vol-active, vol-inactive, vol-unresponsive, vol-available, vol-temp-unavailable are never added to either translations.json file. The function is also used by AccordionVolunteer.tsx (in the volunteer-agent profile section), so this breaks engagement status labels in existing profile views too — they'll silently render the raw key string. Either add the new keys to both locale files and keep both sets, or revert this change and use the existing keys.

2. email and matchingStatus columns are hardcoded to "—"

ApiVolunteerGetList doesn't expose email, and statusMatch isn't yet in the SDK (there's already a TODO for this in the codebase). Showing permanently empty columns is misleading and adds visual noise. Drop these two columns for now and add them when the data is available — the table columns can be extended then.

3. Pagination limit is wrong for the list view

limit = columns * rows = 9 is sized for the card grid. A flat table should show more rows (typically 20–25). Consider defining a separate TABLE_LIMIT constant and passing the appropriate one to useGetQuery based on selectedTabIndex, or defaulting the table to a larger page size.


Minor

4. Redundant import in VolunteerTableRow

createEngagementStatusLabelMap and createStatusLabelMap are imported in VolunteerTableRow.tsx but only used for their ReturnType<> — the actual functions are never called (labels are passed as props). The import should be the type only:

import type { createEngagementStatusLabelMap, createStatusLabelMap } from "...";

Looking ahead — opportunity and agent list views

Since the same pattern will apply to opportunities and agents, a few things to standardise now rather than repeat three times:

  • Generic TableList + TableRowVolunteerTableList is mostly boilerplate (wrapper, header, pagination). Worth extracting a shared EntityTableList that accepts columns config and a row renderer, the same way CardsHeader is shared across all three dashboards.
  • selectedTabIndex prop coupling — passing the tab index into the controller works but leaks UI state into data-fetching logic. A viewMode: "cards" | "list" prop would be cleaner and easier to replicate for agents/opportunities.
  • TABLE_LIMIT constant — define it once in config/constants.ts alongside cacheTTL so all three controllers share it.
  • Hans's ActionCell / ActionButton from the Table component will be useful when the table needs row-level actions (e.g. assign opportunity directly from the list).

Summary

Two blockers before merging:

  1. Add the vol-* translation keys (or revert the key rename)
  2. Remove the email and matchingStatus columns until the data is available

The overall structure and reuse of Hans's table components is correct. Fix the above and this is ready.

@nadavosa
Copy link
Copy Markdown
Collaborator

nadavosa commented May 7, 2026

Follow-up

Disregard the earlier suggestion to drop the email and matchingStatus columns — keep them as placeholders. Two BE issues have been opened to track the missing data:

@ivannissimrch please clarify on both issues exactly what is needed from the BE so the columns can be wired up once the endpoints are ready.

The two blockers from the original review still stand:

  1. Add the missing vol-* translation keys (or revert the key rename in createEngagementStatusLabelMap)
  2. Fix the pagination limit for the list view (limit = 9 is sized for the card grid)

@ivannissimrch
Copy link
Copy Markdown
Collaborator Author

Thank you for the review. I want to provide a quick note on the engagement keys: vol-new, vol-active, vol-inactive, vol-unresponsive, vol-available, and vol-temp-unavailable are actually present in both translations.json files (lines 363-368). PR #475 renamed the old keys to these new vol-* names and updated the filter consumers but missed updating the createEngagementStatusLabelMap. That's why the function was calling deleted keys, returning raw strings, and resulting in broken text in my table.

I'm going with your option 1 anyway: I'll add the old keys back to translations and revert my function change. I'll start working on the rest of the changes as soon as I can.

@ivannissimrch ivannissimrch force-pushed the feat/476-volunteers-list-view branch from 9e3294f to a743fa5 Compare May 8, 2026 01:24
@ivannissimrch
Copy link
Copy Markdown
Collaborator Author

I committed new changes

  • Reverted createEngagementStatusLabelMap to original keys
  • Added old engagement keys back to en, de translations alongside vol-* (both sets coexist now)
  • Separated CARD_LIMIT (9) and TABLE_LIMIT (20), pick based on isListView
  • Moved TABLE_LIMIT to src/config/constants.ts
  • Switched to import type in VolunteerTableRow
  • Comments posted on be#471 (be#472 was closed as duplicate, tracked via be#433/fe#432)

Also I discovered during testing that BE returns locations as string[] despite SDK typing as OptionItem[] I added a runtime typeof check so the District column renders correctly.

I'm planning a follow-up PR this weekend with the bigger architectural items (generic EntityTableList , EntityTableRow and viewMode prop refactor) before starting #477.

@nadavosa nadavosa force-pushed the feat/476-volunteers-list-view branch from 2951fd2 to c438217 Compare May 11, 2026 12:05
@need4deed need4deed merged commit 04f4920 into develop May 11, 2026
1 check passed
@need4deed need4deed deleted the feat/476-volunteers-list-view branch May 11, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: volunteers list view

3 participants