What needs to be built?
A page at /messages/compose that renders the compose message form. After a successful send, the form is replaced with the message sent confirmation. The page fetches the groups and members lists for the recipient dropdowns and handles calling the appropriate send action (group message or blast).
Design reference
The compose form was designed as a modal but renders as a full page. Update heading font and layout to match existing page patterns.
Figma link: https://www.figma.com/design/O8reTcdtMARvnTzCtlsvmp/Paso-Food-Co-Op?node-id=407-4433&p=f&t=wZjCheHOOyiYBbH4-0
Documentation
Existing patterns:
Component dependencies (must be merged first):
src/components/messages/compose-message-form.tsx - compose form
src/components/messages/message-sent-confirmation.tsx - success state
Official docs:
Technical notes
Create new route files:
src/app/(protected)/messages/compose/page.tsx (server component)
src/app/(protected)/messages/compose/compose-content.tsx (client component)
Server component (page.tsx):
- Fetch all groups using
getAllGroups()
- Fetch all members using
getAllMembers()
- Pass to
ComposeContent
Client component (compose-content.tsx):
- Manages two states: composing and sent
- Composing state: renders
ComposeMessageForm with groups and members
- When
onSend fires, calls sendGroupMessageAction() or sendBlastMessageAction() based on whether "All" was selected
- Sent state: replaces the form with
MessageSentConfirmation
- "Track RSVPs" navigates to
/events (or relevant tracking)
- "Delivery Status" navigates to
/messages and opens the view modal for the sent message
revalidatePath("/messages") after successful send
Acceptance criteria
What needs to be built?
A page at
/messages/composethat renders the compose message form. After a successful send, the form is replaced with the message sent confirmation. The page fetches the groups and members lists for the recipient dropdowns and handles calling the appropriate send action (group message or blast).Design reference
The compose form was designed as a modal but renders as a full page. Update heading font and layout to match existing page patterns.
Figma link: https://www.figma.com/design/O8reTcdtMARvnTzCtlsvmp/Paso-Food-Co-Op?node-id=407-4433&p=f&t=wZjCheHOOyiYBbH4-0
Documentation
Existing patterns:
src/app/(protected)/groups/page.tsx- server component + client content patternsrc/actions/contact-group.ts-sendGroupMessageAction(),sendBlastMessageAction()src/services/contact-group.ts-getAllGroups()for group listsrc/lib/api/member-api.ts-getAllMembers()for member listComponent dependencies (must be merged first):
src/components/messages/compose-message-form.tsx- compose formsrc/components/messages/message-sent-confirmation.tsx- success stateOfficial docs:
Technical notes
Create new route files:
src/app/(protected)/messages/compose/page.tsx(server component)src/app/(protected)/messages/compose/compose-content.tsx(client component)Server component (
page.tsx):getAllGroups()getAllMembers()ComposeContentClient component (
compose-content.tsx):ComposeMessageFormwith groups and membersonSendfires, callssendGroupMessageAction()orsendBlastMessageAction()based on whether "All" was selectedMessageSentConfirmation/events(or relevant tracking)/messagesand opens the view modal for the sent messagerevalidatePath("/messages")after successful sendAcceptance criteria
src/app/(protected)/messages/compose/page.tsxrevalidatePathcalled after successful sendnpm run buildpassesnpm run lintpasses