Skip to content

feat: view message modal with expandable recipient status #131

@kevinrutledge

Description

@kevinrutledge

What needs to be built?

A modal that displays a sent message's details: recipient group, delivery timestamp, recipient avatar stack, and message body. The avatar stack has a chevron that expands to reveal a Members/Status table showing each recipient's delivery status (Received or Pending). The modal is triggered from the "View" link in the message history table.

Design reference

Image Image

Figma link: https://www.figma.com/design/O8reTcdtMARvnTzCtlsvmp/Paso-Food-Co-Op?node-id=407-4433&p=f&t=wZjCheHOOyiYBbH4-0

Documentation

Existing patterns:

Official docs:

Technical notes

Create the component at src/components/messages/view-message-modal.tsx.

Collapsed layout:

  • X close button (top-right, from DialogClose)
  • "View Message" heading in Angkor font
  • "To: [group name]" text (use "All Members" for blast messages)
  • "Delivered: [timestamp]" formatted as "M/D/YYYY H:MM:SS AM PST"
  • People icon + avatar stack (up to 6 circular avatars, photo when available with initials fallback) + "+N" overflow count + right chevron (>)
  • Message body in a rounded card with light gray background
  • "Close" brown button bottom-right

Expanded layout (chevron clicked):

  • Chevron rotates to down arrow
  • Rounded card expands below the avatar row showing a Members/Status table
  • Each row: circular avatar (photo when available, initials fallback) + member name + status badge
  • Status badges: green border "Received" or orange border "Pending"
  • Scrollable list with max height
  • Message body card moves below the expanded section
interface ViewMessageModalProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  message: {
    id: number;
    subject: string;
    body: string;
    sentAt: Date;
    groupName: string | null;
    isBlast: boolean;
  };
  recipients: Array<{
    memberId: number;
    memberName: string;
    status: "sent" | "pending" | "failed";
    photoUrl?: string | null;
  }>;
}

The parent page fetches message detail and recipients, passes them as props. The modal manages the expanded/collapsed state internally.

Acceptance criteria

  • Component created at src/components/messages/view-message-modal.tsx
  • "View Message" heading in Angkor font
  • Displays "To: [group name]" (or "All Members" for blast)
  • Displays formatted delivery timestamp
  • Avatar stack shows up to 6 recipient circular avatars (photo when available, initials fallback) with "+N" overflow
  • Right chevron toggles expanded/collapsed state
  • Expanded state shows Members/Status table with avatar, name, and status badge
  • Status badges: green "Received" (when service returns sent), orange "Pending" (when service returns pending)
  • Scrollable recipient list with max height
  • Message body in rounded card with light gray background
  • X close button and "Close" brown button both dismiss the modal
  • Uses shadcn Dialog and Avatar primitives
  • Exported as named export
  • Preview rendered on your team page (/team/[yourname]) with hardcoded data showing both collapsed and expanded states
  • Screenshot of the rendered preview posted in the PR
  • npm run build passes

Metadata

Metadata

Assignees

No one assigned

    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