Skip to content

feat: groups home page with authenticated layout shell #87

@kevinrutledge

Description

@kevinrutledge

What needs to be built?

The Groups home page at /groups and the authenticated layout shell that all protected pages share. This issue replaces the existing header-based layout with a new sidebar + top bar layout, creates the groups page with a card grid and all group modals wired to server actions, and establishes the layout pattern that the Home page and all placeholder pages inherit.

This issue is blocked until all 8 developer component issues are merged.

Design reference

Figma — Paso Food Co-Op

Image

Documentation

Existing patterns:

Developer components (merged before this starts):

  • src/components/layout/sidebar.tsx — Sidebar navigation
  • src/components/layout/top-bar.tsx — Top bar with logo, search, avatar
  • src/components/groups/entity-card.tsx — Group/add cards
  • src/components/groups/group-detail-view-modal.tsx — Read-only detail
  • src/components/groups/group-edit-modal.tsx — Edit form
  • src/components/groups/create-group-modal.tsx — Create form
  • src/components/groups/delete-group-modal.tsx — Delete confirmation
  • src/components/groups/add-members-modal.tsx — Member management

Official docs:

Technical notes

Part 1: Authenticated layout shell

Replace src/app/(protected)/layout.tsx with the new sidebar + top bar layout. The top bar spans full width at the top (logo, search, action button, bell, avatar). Below it, the sidebar sits on the left with nav items, and the main content area fills the remaining space on the right.

  • Server component that calls getSessionWithName()
  • Passes userName and userRole to <TopBar>
  • Renders <Sidebar> on the left
  • Content area fills remaining space with scroll
  • Update src/config/navigation.ts to add Messages /messages, Events /events, Settings /settings routes

Part 2: Groups page

Create src/app/(protected)/groups/page.tsx:

Data fetching (server component):

  • Call verifySession() to get session
  • If member: getGroupsByOwner(ownerid) — shows "My Groups"
  • If admin: getAllGroups() — shows all groups with "Groups" title
  • Pass data to a client component wrapper that manages modal state

Client component (groups content):

  • Render 3-column card grid using <EntityCard> components
  • Last position: <EntityCard variant="add"> card
  • Manage modal state: which modal is open, which group is selected
  • Modal flow:
    • Click card → open detail view modal → fetch enriched group data
    • Detail view → "Edit" → open edit modal
    • Edit → "Delete" → open delete confirmation
    • Edit → "+" → open add members modal
    • Edit → "Save Changes" → call updateContactGroup action
    • Delete confirm → call deleteContactGroup action
    • Add card click → open create group modal
    • Create submit → call createContactGroup action

Top bar action button: Pass actionLabel="+ New Group" and onActionClick to open the create modal.

Part 3: Wire server actions

Each modal callback maps to a server action:

  • Create modal onSubmitcreateContactGroup(formData)
  • Edit modal onSaveupdateContactGroup(groupId, formData)
  • Delete modal onConfirmdeleteContactGroup(groupId)
  • Add members onConfirmaddMembers({ groupId, members })

Handle loading states (isSubmitting, isDeleting), success (close modal, refresh data), and errors (toast via Sonner).

Acceptance criteria

  • Authenticated layout at src/app/(protected)/layout.tsx replaced with sidebar + top bar structure
  • getSessionWithName() called in layout, data passed to TopBar
  • Sidebar and TopBar render on all protected pages
  • navigation.ts updated with Messages, Events, Settings routes
  • Groups page at src/app/(protected)/groups/page.tsx
  • Members see "My Groups" (own groups only), admins see "Groups" (all)
  • 3-column card grid with entity cards
  • "+" add card in last position opens create modal
  • TopBar action button ("+ New Group") opens create modal
  • Click group card → detail view modal with correct group data
  • Detail view "Edit" → edit modal with pre-filled data
  • Edit "Delete" → delete confirmation modal
  • Edit "+" → add members modal with full member list and current selections
  • Edit "Save Changes" → calls updateContactGroup, closes on success, shows toast
  • Delete "Confirm" → calls deleteContactGroup, closes modal, removes card, shows toast
  • Create "Create Group" → calls createContactGroup, closes on success, new card appears, shows toast
  • Add members "Save" → calls addMembers/removeMember as needed, updates member list
  • Error states handled (toast on failure, button re-enabled)
  • npm run build passes
  • npm run test 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