Skip to content

120 migrate volunteer management hi fi page to chakra v3#126

Open
brelieu05 wants to merge 68 commits intomainfrom
120-migrate-volunteer-management-hi-fi-page-to-chakra-v3
Open

120 migrate volunteer management hi fi page to chakra v3#126
brelieu05 wants to merge 68 commits intomainfrom
120-migrate-volunteer-management-hi-fi-page-to-chakra-v3

Conversation

@brelieu05
Copy link
Copy Markdown
Collaborator

@brelieu05 brelieu05 commented Mar 30, 2026

Description

  • Migrated all volunteer management components to Chakra UI v3 (compound components, NativeSelect, Tabs, Drawer, Dialog, etc.)
  • Implemented split-view layout: full table view collapses to 50/50 when a profile panel is opened
  • Added fuzzy search with 250ms debounce filtering volunteers by name
  • Added column sorting (Name, Role) with asc/desc toggle and sliding-window pagination with clickable ellipsis
  • Added select-all checkbox in table header (scoped to current page) with bulk Delete (with confirmation modal) and Archive (TODO)
  • Added Sort & Filter drawer with preset Occupation, Interest, and Language filter categories
  • Added /volunteer-management/new subroute with a two-tab Add Profile form (Profile Information → Occupation & Credentials), tab-gated behind form validation
  • Add Profile form posts to POST /volunteers, POST /volunteers/:id/languages; remaining occupation fields need backend support (see TODOs)
  • Added DELETE /volunteers/:id backend route
  • Updated GET /volunteers to JOIN volunteer_roles and aggregate roles per volunteer via array_agg

Screenshots/Media

image image image image image image image

Known TODOs (b/c of waiting for design or need help with associating with right table)

  • Archive button has no backend implementation yet because no design for archive page that I could find
  • Archived volunteers tab and Staff tab are placeholder content
  • The following Add Profile occupation fields are UI-only and not yet persisted: affiliated, lawSchoolYear, stateBarCertState, stateBarNumber, interests. I have no idea what table they're supposed to go to
    • state bar number + cert have been removed, brooke dont want em no more

Issues

Closes #120

Use Tabs.Root, Tabs.List, Tabs.Trigger, and Tabs.Content instead of legacy Tab components.

Made-with: Cursor
- Add StaffLayout with email-template Sidebar + Outlet for nested staff pages
- Wrap /volunteer-management in ProtectedRoute with staff/supervisor roles
- Reuse existing VolunteerManagement view inside the shell

Made-with: Cursor
…mentView with improved UI and state management
… in VolunteerList for improved user experience
…ed sorting and filtering options in VolunteerManagementView
…eerManagementView to toggle between list and split views
…ing to VolunteerManagementView for improved volunteer filtering
…erList for improved volunteer selection and state management
…roles for volunteers and adjust styling accordingly
…a fetching and improved checkbox functionality
…r deletion confirmation and integrate with VolunteerManagementView
…tView from red to blue for improved UI consistency
…FilterDrawer with static predefined options for occupations, interests, and languages
…e functionality and archived volunteers view
@brelieu05 brelieu05 self-assigned this Mar 30, 2026
@brelieu05 brelieu05 linked an issue Mar 30, 2026 that may be closed by this pull request
…ArchivedList, StaffList, and VolunteerList for improved user interaction
Copy link
Copy Markdown
Collaborator

@Hydrohaven Hydrohaven left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, will fix new navbar and app.tsx changes on main myself + integrating backend logic for interests (areas of practice)

@Hydrohaven
Copy link
Copy Markdown
Collaborator

nvm not lgtm unless brendan is done working

brelieu05 added 15 commits April 7, 2026 10:35
…tice in VolunteerList and VolunteerProfilePanel for consistency
…pe and update VolunteerList to display event dates
…ofilePanel with editing and saving functionality, including visual indicators for edit mode and save status
…onfidentiality status with visual indicators
…r type with additional fields for affiliated employer, law school year, state bar certificate, and state bar number
…Panel to prioritize roles array over legacy role field
…pabilities and save functionality, allowing for dynamic updates of staff information
…rProfilePanel with role management and editing capabilities, allowing for dynamic updates of volunteer roles and additional profile fields
…d volunteers in VolunteerManagementView, enhancing search functionality and pagination handling
…areas of practice with improved data handling and remove unused TagInput component
…eation with role-based handling and additional fields for enhanced volunteer management
…iew and update deletion logic for staff and volunteers to handle Firebase user cleanup
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

14 issues found across 18 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="server/routes/admins.js">

<violation number="1" location="server/routes/admins.js:34">
P1: Orphaned Firebase user on unique-constraint recovery. When the `INSERT INTO users` hits a `23505` and the inner catch recovers by reusing the existing user ID, the Firebase account created just above is never deleted. This leaks a Firebase Auth account on every duplicate-email call.</violation>
</file>

<file name="client/src/components/volunteerManagement/StaffProfilePanel.tsx">

<violation number="1" location="client/src/components/volunteerManagement/StaffProfilePanel.tsx:58">
P1: Phone number edits are silently lost. The form allows editing `phoneNumber`, but `handleSave` never includes it in the PUT request body or the `onSaved` callback, so the change is discarded on save.</violation>
</file>

<file name="client/src/components/volunteerManagement/StaffList.tsx">

<violation number="1" location="client/src/components/volunteerManagement/StaffList.tsx:39">
P2: The async fetch inside `useEffect` has no error handling. If `/admins/staff` returns an error, the rejection is unhandled. Wrap in try/catch to prevent an unhandled promise rejection and surface the error to the user.</violation>

<violation number="2" location="client/src/components/volunteerManagement/StaffList.tsx:110">
P2: Select-all checkbox appears checked on an empty page. `[].every(...)` returns `true` (vacuous truth), so when `pageSlice` is empty but `sortedStaff` is not, the checkbox shows as checked. Add a `pageSlice.length > 0` guard.</violation>
</file>

<file name="client/src/components/volunteerManagement/ProfilePanelShell.tsx">

<violation number="1" location="client/src/components/volunteerManagement/ProfilePanelShell.tsx:20">
P2: `ProfileField` declares `type`, `options`, `isEditing`, and `registerProps` in its interface but never uses them. In a brand-new shared component this creates a misleading API — callers may expect these props to be functional. Remove the unused props and the now-unnecessary `UseFormRegisterReturn` import.</violation>
</file>

<file name="client/src/types/volunteer.ts">

<violation number="1" location="client/src/types/volunteer.ts:13">
P2: `isSignedConfidentiality` is typed as `string` but the `is`-prefix and every usage site treat it as a boolean. Type it as `boolean` so TypeScript can enforce correct assignments and comparisons.</violation>
</file>

<file name="client/src/components/volunteerManagement/AddProfileView.tsx">

<violation number="1" location="client/src/components/volunteerManagement/AddProfileView.tsx:165">
P2: N+1 fetch: `backend.get("/areas-of-practice")` is called inside the `for` loop, making one redundant network request per interest. Fetch the list once before the loop and reuse it.</violation>
</file>

<file name="client/src/components/volunteerManagement/VolunteerProfilePanel.tsx">

<violation number="1" location="client/src/components/volunteerManagement/VolunteerProfilePanel.tsx:185">
P1: `handleSave` has no error handling. If any API call fails mid-way, subsequent saves are skipped, the user gets no feedback, and the data is left partially persisted. Wrap the body in a try/catch that shows an error toast and avoids flipping `isEditing`/`isSaved` on failure.</violation>
</file>

<file name="server/routes/volunteers.js">

<violation number="1" location="server/routes/volunteers.js:254">
P1: The volunteer and user deletes are not wrapped in a transaction. If `DELETE FROM users` fails (e.g., the user is also an admin, which has a FK to `users` without CASCADE), the volunteer is already gone. Use `db.tx()` (pg-promise transaction) to make both deletes atomic.</violation>

<violation number="2" location="server/routes/volunteers.js:258">
P2: Silently swallowing the Firebase `deleteUser` error with `.catch(() => {})` means an orphaned Firebase account could remain active with no log trail. At minimum, log the error so failures are discoverable.</violation>
</file>

<file name="client/src/components/volunteerManagement/ArchivedProfilePanel.tsx">

<violation number="1" location="client/src/components/volunteerManagement/ArchivedProfilePanel.tsx:140">
P2: Wrap `handleSave` in try-catch to handle backend failures. Currently, if any of the `Promise.all` requests fail, the rejection propagates out of the `onClick` handler unhandled — the user sees no error feedback. `enterEditMode` already uses try-catch for its backend call; `handleSave` should do the same.</violation>
</file>

<file name="client/src/components/volunteerManagement/ArchivedList.tsx">

<violation number="1" location="client/src/components/volunteerManagement/ArchivedList.tsx:160">
P1: After merging volunteers and staff into one list, `selectedId` and `checkedIds` use the raw numeric `id` for matching. Since volunteer and staff records come from different tables, their IDs can collide — causing the wrong rows to be highlighted or checked. Use `listKey` (which includes the source prefix) instead of `id` for selection and checkbox tracking.</violation>
</file>

<file name="client/src/components/volunteerManagement/VolunteerManagementView.tsx">

<violation number="1" location="client/src/components/volunteerManagement/VolunteerManagementView.tsx:214">
P1: Delete on the archived tab is broken: the `else` branch handles both "volunteers" and "archived" tabs identically. For archived items it calls the wrong endpoint (always `/volunteers/`), removes from the wrong state array (`volunteers` instead of `archivedVolunteers`), and checks the wrong selected item. Add an `activeTab === "archived"` branch that uses the archived item's `source` to pick the endpoint, removes from `archivedVolunteers`, and resets `selectedArchivedVolunteer`.</violation>

<violation number="2" location="client/src/components/volunteerManagement/VolunteerManagementView.tsx:305">
P1: Unarchive optimistic update is incomplete: items are removed from `archivedVolunteers` but never restored to `volunteers` or `staffMembers`. They vanish from the UI until the next full data fetch. Mirror the archive logic by pushing unarchived items back into their source list based on `v.source`.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread server/routes/admins.js
Comment thread client/src/components/volunteerManagement/StaffProfilePanel.tsx
Comment thread client/src/components/volunteerManagement/VolunteerProfilePanel.tsx
Comment thread server/routes/volunteers.js Outdated
Comment thread client/src/components/volunteerManagement/ArchivedList.tsx Outdated
Comment thread client/src/components/volunteerManagement/ProfilePanelShell.tsx
Comment thread client/src/types/volunteer.ts Outdated
Comment thread client/src/components/volunteerManagement/AddProfileView.tsx Outdated
Comment thread server/routes/volunteers.js Outdated
Comment thread client/src/components/volunteerManagement/ArchivedProfilePanel.tsx
…th improved error handling, role-based UI elements, and optimized data fetching for archived profiles
…lunteer archiving, ensuring data integrity on failure; update foreign key constraints to restrict deletions
…eView, restricting access to supervisors only
@brelieu05 brelieu05 requested a review from Hydrohaven April 8, 2026 06:24
…teerManagementView using FilterState, enhancing search functionality with roles, interests, and languages
@brelieu05
Copy link
Copy Markdown
Collaborator Author

everything should be functional, but i had to assume some assumptions and questions to ask. lmk if i was wrong about any my assumptions 🤓 👍

Example:

  • Assumption: Add Profile Button only shows when user is supervisor
    • The add profile is only shown for staff members to create other staff members? because volunteers are only created through login/create account flow?
  • Assumption: Supervisors can make other supervisors
  • Assumption: Volunteers can have multiple roles.
    • I saw multiple volunteers have multiple roles? but in figma it shows only one role per volunteer
  • idk when Confidential Form is verified? i just check it on the backend but idk where it changes?
  • Question: Any interests can be created in Volunteer Management but these changes also show on the Create Account Flow, so if I make a interest tag called "Test", it will also appear in the Create Account Flow. In either or both the Create Account Flow and/or Volunteer Management, should it be hard-coded list instead?

…ions based on user role, enhancing role selection for volunteer profiles
…ew to reflect more relevant language proficiency levels, improving user experience during profile creation
@brelieu05
Copy link
Copy Markdown
Collaborator Author

@Hydrohaven

  • Removed search icon from Affiliated Employer/Education
  • Allowed Staff to add Volunteer
  • Matched Proficiency Levels

…include staff, and streamline VolunteerToolbar by removing role-based button visibility
@brelieu05
Copy link
Copy Markdown
Collaborator Author

brelieu05 commented Apr 16, 2026

@Hydrohaven

  • Added cascade delete for volunteers + users, and also deletes user from firebase
  • Volunteers are created through a staff member -> Volunteers log in for the first time -> Firebase UID is generated for them

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.

[FIX] Migrate Volunteer Management Hi-fi page to Chakra V3

2 participants