Skip to content

#617 Move Recent Activity Into A Global Activity Panel - #771

Merged
cielbellerose merged 4 commits into
devfrom
617-move-recent-activity-into-a-global-activity-panel
Sep 24, 2026
Merged

cielbellerose merged 4 commits into
devfrom
617-move-recent-activity-into-a-global-activity-panel

Conversation

@cielbellerose

Copy link
Copy Markdown
Collaborator

Closes #617

Summary

  • Moves "Recent activity" out of all three dashboards and into a Sheet reachable from every authenticated page — top-right of the sidebar header on desktop, immediately left of the hamburger menu on mobile.
  • getActivityGroups(userId, isAdmin) (prisma/data/activity.ts, cache()d) composes the caller's own submitted-application activity with a reviewer group (managed positions for a manager, all published positions for an admin), self-filtering out the viewer's own application from the reviewer group so it never shows twice.
  • No schema change, no unread state, no badge, no mark-as-read — the panel is derived entirely from data the app already computes.

Changes

  • lib/types.ts — ActivityScope, ActivityGroups.
  • lib/constants.ts — ACTIVITY_FEED_COPY (description/empty copy per scope), ACTIVITY_MINE_TITLE.
  • prisma/data/activity.ts (new) — getActivityGroups, composing getMyRecentActivity and getRecentApplications in parallel, with the self-filter and sentence mapping moved here from activity-feed.tsx.
  • components/features/activity-feed.tsx — replaced the two dashboard-only wrappers (ApplicantActivityFeed, ReviewerActivityFeed) with a single async ActivityFeed, a bare ActivityFeedList, a private ActivityFeedGroup, and an exported ActivityFeedListSkeleton.
  • components/features/activity-panel.tsx (new, client) — the Sheet trigger + content, opening from the right so it never reads as the same surface as MobileNav's left-side menu drawer.
  • components/layouts/app-shell.tsx — derives scope, builds the panel node once when signed in, passes it to both Sidebar and MobileNav.
  • components/layouts/sidebar.tsx / mobile-nav.tsx — new activityPanel prop, rendered top-right of each h-14 header.
  • components/features/user-dashboard.tsx, manager-dashboard.tsx, admin-dashboard.tsx — removed the activity-feed Suspense block and its import.
  • components/ui/section-card.tsx — removed the now-unused 'timeline' skeleton row shape (its markup lives in ActivityFeedListSkeleton now).
  • tests/db/authorization.test.ts — new getActivityGroups composition and scoping describe block.
  • docs/WORKFLOWS.md — new XC-10 Activity panel entry (+ TOC link); AP-1 and PM-1 updated to drop the activity feed and link XC-10; AD intro notes the all scope.

Testing plan

  • Signed out, open /positions: no activity trigger at any width.
  • Applicant, desktop (1280px): trigger sits at the right of the sidebar logo bar; panel opens from the right; one flat list (no group heading) showing only your own applications with public status labels and relative times.
  • A user with no submitted applications and no managed positions sees the empty state: "No recent activity" / "Updates to your applications will show up here."
  • Manager of position A only, who has also applied to position B: groups read "Your applications" (the B application) then "Positions you manage" (A's applications only).
  • Manager who has never applied: only "Positions you manage" shows.
  • Manager with no applications anywhere and quiet positions: empty state shows the managed copy.
  • Admin who has applied somewhere: "Your applications" shows the admin's own application; "All positions" lists applications across all published positions, excluding their own and anything on draft/deleted positions.
  • Mobile (375px): header cluster reads [activity] [menu]; the activity sheet opens right, the menu sheet opens left; each closes independently.
  • Keyboard only: Tab to the trigger, press Enter — focus traps in the sheet; Escape closes it and returns focus to the trigger.
  • 768px and both themes: no header overflow, no title/close-button overlap.
  • / for all three personas: no "Recent Activity" card on any dashboard.
  • A non-dashboard page (e.g. /profile, /manage/applications): the trigger is present and the panel works.
  • getActivityGroups db tests: applicant-only, neither-role, draft-only, manager-only, manager-who-applied (self-filter + public status), admin-who-applied (self-filter + draft/deleted exclusion) — added to tests/db/authorization.test.ts.

Automated checks

  • npm run prettier:check — pass
  • npm run eslint:check — pass
  • npm run tsc:check — pass
  • npm run test:unit — 439 passed (2 pre-existing, unrelated suites fail on import because this sandboxed worktree has no DATABASE_URL/reachable Postgres — port 5432 is already bound by an unrelated container, so npm run db:start cannot bind it either). The new tests/db/authorization.test.ts cases could not be run locally in this environment; they'll run in CI, which has its own Postgres service.

Notes

  • Scope decision, per the issue: no unread state, no Notification model, no /notifications page — this relocates and improves access to information the app already computes.
  • The activity panel lives in the shared layout, so it refreshes on a hard load, router.refresh(), or any revalidating server action — not on a plain client-side link navigation. Documented in the new XC-10 entry.

🤖 Generated with Claude Code

@cielbellerose cielbellerose added the claude Will be worked on by Claude label Sep 24, 2026
@cielbellerose cielbellerose self-assigned this Sep 24, 2026
@vercel

vercel Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
aplio Ready Ready Preview Sep 24, 2026 7:24pm UTC

@cielbellerose cielbellerose added ready for review PR ready for review agent reviewing Review agent working (in-flight) and removed ready for review PR ready for review agent labels Sep 24, 2026

@cielbellerose cielbellerose left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — Cycle 1 · needs revision

2 open — 1 🟠 Medium, 1 🟡 Low (see inline)

Comment thread components/features/activity-feed.tsx Outdated
Comment thread components/layouts/app-shell.tsx Outdated
@cielbellerose cielbellerose added needs revision Review found issues that need fixing revising Revise agent working (in-flight) and removed reviewing Review agent working (in-flight) needs revision Review found issues that need fixing labels Sep 24, 2026
@cielbellerose

Copy link
Copy Markdown
Collaborator Author

Revision — Cycle 1

fixed R1-M1, R1-L1 · 4552659

@cielbellerose cielbellerose added ready for review PR ready for review agent and removed revising Revise agent working (in-flight) labels Sep 24, 2026
@cielbellerose cielbellerose added reviewing Review agent working (in-flight) and removed ready for review PR ready for review agent labels Sep 24, 2026

@cielbellerose cielbellerose left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — Cycle 2 · approved

0 open

@cielbellerose cielbellerose added approved Review passed, ready to merge and removed reviewing Review agent working (in-flight) labels Sep 24, 2026

@cielbellerose cielbellerose left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — Cycle 3 · needs revision

2 open — operator feedback after approval (from the Vercel preview)

R3-M1 (Medium, UX) — the panel's empty state has no horizontal padding.
The "No recent activity" empty state ("Updates to your applications and new applications to the positions you manage will show up here.") runs to the edges of the Sheet. SheetContent is p-0, and the roomy SectionCardEmpty in components/ui/section-card.tsx has only py-10, no horizontal padding. Add horizontal padding in the panel, for example px-6 on the empty-state wrapper in ActivityFeed / the panel's scroll body, so the text wraps inside the panel with comfortable margins at every width.

  • Keep the fix scoped to the panel. Don't change SectionCardEmpty's shared styles, which other cards rely on.
  • Check the compact error fallback ("Couldn't load recent activity.") lines up with the new padding.

R3-M2 (Medium, UX) — remove the description under the panel title.
The header should show only the title Recent activity. Remove the visible SheetDescription from components/features/activity-panel.tsx, and drop the now-unused description prop plus the ACTIVITY_FEED_COPY[*].description entries in lib/constants.ts, along with any call site in app-shell.tsx / sidebar.tsx / mobile-nav.tsx.

  • Radix Dialog warns in the console when a DialogContent has no description. Pass aria-describedby={undefined} on SheetContent (the Radix-sanctioned opt-out) rather than keeping a hidden description.
  • Keep emptyDescription; it's still used by the empty state.
  • Update docs/WORKFLOWS.md XC-10 if it mentions the header description.

@cielbellerose cielbellerose added needs revision Review found issues that need fixing revising Revise agent working (in-flight) and removed approved Review passed, ready to merge needs revision Review found issues that need fixing labels Sep 24, 2026
@cielbellerose

Copy link
Copy Markdown
Collaborator Author

Revision — Cycle 3

fixed R3-M1, R3-M2 · e9f4be5

@cielbellerose cielbellerose added ready for review PR ready for review agent reviewing Review agent working (in-flight) and removed revising Revise agent working (in-flight) ready for review PR ready for review agent labels Sep 24, 2026

@cielbellerose cielbellerose left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — Cycle 4 · needs revision

1 open — 1 🟠 Medium (see inline)

Comment thread components/features/activity-feed.tsx
@cielbellerose cielbellerose added needs revision Review found issues that need fixing and removed reviewing Review agent working (in-flight) labels Sep 24, 2026
@cielbellerose

Copy link
Copy Markdown
Collaborator Author

Operator decision — R4-M1 (won't fix, by design)

The try/catch in ActivityFeed (components/features/activity-feed.tsx) is a deliberate, operator-approved exception to docs/ENGINEERING.md §4, and it stays.

  • The feed renders from AppShell, above every route's error boundary. Throwing would replace every page with the global error screen because of one secondary widget's query. That is the concern R1-L1 raised, and the fix that addressed it is this try/catch.
  • On failure the panel shows the compact "Couldn't load recent activity." message and logs the error. Nothing else is affected.
  • This overrides the Move Recent Activity Into A Global Activity Panel #617 plan's line "a feed query throw goes to the global boundary".

Future reviews should not re-flag this pattern for this component.

@cielbellerose cielbellerose added approved Review passed, ready to merge and removed needs revision Review found issues that need fixing labels Sep 24, 2026

@cielbellerose cielbellerose left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — Cycle 5 · needs revision

1 open — operator feedback after approval (from the Vercel preview)

R5-M1 (Medium, UX) — activity messages are cut off at two lines.
components/features/activity-feed.tsx:30 clamps each activity sentence with line-clamp-2. On mobile, and in the narrow side sheet on desktop, normal-length messages get truncated, so the user can't read the full update. Change it to line-clamp-3 at every width, which fits nearly all messages in full.

  • Don't add responsive clamp variants: the panel is narrow at every breakpoint.
  • Update ActivityFeedGroupSkeleton / ActivityFeedListSkeleton only if their row height assumes two lines. Otherwise leave them alone.
  • No other changes. In particular, leave the activity button's hover colour as it is (operator decision).

@cielbellerose cielbellerose added needs revision Review found issues that need fixing revising Revise agent working (in-flight) and removed approved Review passed, ready to merge needs revision Review found issues that need fixing labels Sep 24, 2026
cielbellerose and others added 4 commits September 24, 2026 15:21
Relocates the dashboard "Recent activity" card into a Sheet reachable
from every authenticated page (sidebar on desktop, mobile-nav on
mobile), so activity isn't tied to standing on the dashboard.
getActivityGroups composes the caller's own applications with a
reviewer group scoped to managed/all positions, self-filtered so a
reviewer's own application never appears twice.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Match the activity skeleton to the resolved two-heading layout for
reviewer scopes, and fall back to a muted message instead of the
global error boundary when the feed's fetch throws.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@cielbellerose
cielbellerose force-pushed the 617-move-recent-activity-into-a-global-activity-panel branch from e9f4be5 to 6578536 Compare September 24, 2026 19:23
@cielbellerose

Copy link
Copy Markdown
Collaborator Author

Revision — Cycle 5

fixed R5-M1 · 6578536

@cielbellerose cielbellerose added ready for review PR ready for review agent and removed revising Revise agent working (in-flight) labels Sep 24, 2026
@cielbellerose cielbellerose added reviewing Review agent working (in-flight) and removed ready for review PR ready for review agent labels Sep 24, 2026

@cielbellerose cielbellerose left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — Cycle 6 · approved

0 open

@cielbellerose cielbellerose added approved Review passed, ready to merge and removed reviewing Review agent working (in-flight) labels Sep 24, 2026
@cielbellerose
cielbellerose merged commit f41496d into dev Sep 24, 2026
14 of 19 checks passed
@cielbellerose
cielbellerose deleted the 617-move-recent-activity-into-a-global-activity-panel branch September 24, 2026 19:50

This branch was successfully deployed

1 active deployment
Preview — 65785362 Deployed Sep 24, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Review passed, ready to merge claude Will be worked on by Claude

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move Recent Activity Into A Global Activity Panel

1 participant