hir-94: per-recipient queue table on campaign detail#21
Open
jaredzwick wants to merge 2 commits intopypesdev:mainfrom
Open
hir-94: per-recipient queue table on campaign detail#21jaredzwick wants to merge 2 commits intopypesdev:mainfrom
jaredzwick wants to merge 2 commits intopypesdev:mainfrom
Conversation
A user could create a campaign but had no way to see it afterward — no listing, no detail view, no status, no sent/open/click counts. The GET /api/campaigns and GET /api/campaigns/:id endpoints already existed; only the UI was missing. - /dashboard/campaigns: lists campaigns with status badge, sent progress, reply count, created date. Empty-state CTA links to /dashboard/campaigns/new. - /dashboard/campaigns/[id]: shows status, send progress, opens / clicks / replies / bounces / unsubscribes / total recipients, plus optional queue stats (pending / sent / failed / bounced) when the API returns them. Includes a delete action with confirm prompt. - /dashboard/campaigns/new: on successful POST, router.push to the new campaign's detail page so the user lands somewhere meaningful. - src/lib/campaignStatus.ts: pure helpers (status badge label/tone, sent progress formatter with clamp + percent rounding) so render logic is unit-testable without mounting React. 15 vitest specs in tests/int/campaignStatus.int.spec.ts cover all known + unknown statuses, null/undefined/empty inputs, and the formatter's clamp / NaN / zero-total / rounding paths. No API route, schema, migration, or send-pipeline changes. tsc clean (error count went from 10 pre-existing on main to 0 — earlier merged PRs cleared them). Full test:int matches main baseline (only api.int.spec.ts still fails on missing PAYLOAD_SECRET, pre-existing). Co-Authored-By: Paperclip <noreply@paperclip.ing>
The campaign detail page surfaced aggregate counts but a user could not see which specific recipients were pending, sent, failed, or bounced. The most common post-create question — "did my emails actually go out?" — required a database query to answer. - GET /api/campaigns/:id/queue: paginated per-recipient queue rows. Owner-checked (loads the campaign first to verify userId), then delegates to the existing getQueueEntriesByCampaign helper. Limit defaults 100, max 500; offset honored. Returns the columns a UI table needs (status / attempts / scheduled / sent / errorMessage) and omits raw send_log internals. - /dashboard/campaigns/:id detail page: new "Recipients" section renders the queue rows in a table with status badge, attempts N/M, last-activity relative time, and a one-line error summary. - src/lib/queueRowSummary.ts: pure helpers (queue-status badge label/tone, summarizeError that trims to a single line + ellipsis, formatRelativeTime that takes a fixed `now` for testability). 29 vitest specs in tests/int/queueRowSummary.int.spec.ts cover every known + unknown queue status, error truncation (empty / multi-line / CRLF / over-max with rounded ellipsis / trailing-whitespace strip / custom max), and relative-time formatting (just-now band, past + future across m/h/d/w with rounding, ISO string input, NaN/null handling). Stacked on hir-94/campaign-list-detail (PR-pending). No schema, no migrations, no send-pipeline changes. tsc clean. test:int 139 passed (only pre-existing PAYLOAD_SECRET api.int.spec.ts fails). Co-Authored-By: Paperclip <noreply@paperclip.ing>
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The campaign detail page surfaced aggregate counts but a user could
not see which specific recipients were pending, sent, failed, or
bounced. The most common post-create question — "did my emails
actually go out?" — required a database query to answer.
Owner-checked (loads the campaign first to verify userId), then
delegates to the existing getQueueEntriesByCampaign helper. Limit
defaults 100, max 500; offset honored. Returns the columns a UI
table needs (status / attempts / scheduled / sent / errorMessage)
and omits raw send_log internals.
renders the queue rows in a table with status badge, attempts
N/M, last-activity relative time, and a one-line error summary.
label/tone, summarizeError that trims to a single line + ellipsis,
formatRelativeTime that takes a fixed
nowfor testability).29 vitest specs in tests/int/queueRowSummary.int.spec.ts cover every
known + unknown queue status, error truncation (empty / multi-line /
CRLF / over-max with rounded ellipsis / trailing-whitespace strip /
custom max), and relative-time formatting (just-now band, past +
future across m/h/d/w with rounding, ISO string input, NaN/null
handling).
Stacked on hir-94/campaign-list-detail (PR-pending). No schema, no
migrations, no send-pipeline changes. tsc clean. test:int 139
passed (only pre-existing PAYLOAD_SECRET api.int.spec.ts fails).
Co-Authored-By: Paperclip noreply@paperclip.ing
🤖 Generated with Claude Code