Skip to content

feat: add members modal #86

@kevinrutledge

Description

@kevinrutledge

What needs to be built?

A dialog modal for viewing and managing group members. Displays the group name, member count, a search input, and a scrollable list of members with avatars, names, and checkboxes. The group owner is labeled "(owner)" and always appears first. Opens when the user clicks the "+" button in the edit modal or "View All" in the detail view modal.

Design reference

Figma — Paso Food Co-Op

Documentation

Existing patterns:

Official docs:

Technical notes

Create the component at src/components/groups/add-members-modal.tsx.

Modal layout:

  • Header:
    • Group name as title (bold)
    • "members (N)" subtitle showing current count
  • Search input: Text input with Search icon, placeholder "Search or add members". Filters the member list client-side by name (case-insensitive substring match).
  • Member list (scrollable, max height ~400px):
    • Each row: Avatar (initials + color) + member name + checkbox (right side)
    • First row: owner with "(owner)" label after name
    • Owner checkbox is always checked and disabled (cannot remove the owner)
    • Checked = member is in the group, unchecked = not in the group
    • Toggling a checkbox calls onSelectionChange
  • Footer: "Save" button (Paso Brown fill) — calls onConfirm
  • Close: X button
interface MemberRow {
  memberId: number;
  ownername: string;
  isOwner: boolean;
  isSelected: boolean;
}

interface AddMembersModalProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  groupName: string;
  members: MemberRow[];
  onSelectionChange: (memberId: number, selected: boolean) => void;
  onConfirm: () => void;
  isSubmitting?: boolean;
}

The parent (tech lead) provides the full member list with selection state. The modal handles local search filtering but delegates selection changes to the parent via onSelectionChange. This keeps the modal stateless regarding member selection — the parent manages the source of truth.

Search behavior: Filter the members array by ownername matching the search input. Owner always stays visible regardless of search term. Clear search when modal closes.

Acceptance criteria

  • Component created at src/components/groups/add-members-modal.tsx
  • Uses shadcn Dialog for modal overlay
  • Group name displays as title, "members (N)" as subtitle
  • Search input with Search icon and "Search or add members" placeholder
  • Search filters member list by name (case-insensitive)
  • Member list is scrollable with a max height (~400px)
  • Each member row: avatar (initials + color) + name + checkbox
  • Owner row shows "(owner)" label and checkbox is checked + disabled
  • Owner always appears first regardless of search filter
  • onSelectionChange(memberId, selected) fires when a checkbox is toggled
  • "Save" button with Paso Brown fill calls onConfirm
  • Save button disabled and shows loading when isSubmitting is true
  • Search resets when modal closes
  • X close button dismisses the modal
  • Exported as named export
  • npm run build passes

Metadata

Metadata

Assignees

Labels

featureNew functionality or enhancement

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions