Skip to content

Default registrants to active; show counts and event date#1590

Merged
maebeale merged 4 commits into
mainfrom
maebeale/registrant-active-inactive-counts
Jun 8, 2026
Merged

Default registrants to active; show counts and event date#1590
maebeale merged 4 commits into
mainfrom
maebeale/registrant-active-inactive-counts

Conversation

@maebeale

@maebeale maebeale commented Jun 7, 2026

Copy link
Copy Markdown
Collaborator

What is the goal of this PR and why is this important?

  • Admins managing an event need to focus on registrants who are actually attending, not those who cancelled or no-showed.
  • Previously the registrants list showed every registrant regardless of status, burying the active roster.
  • This defaults the page to the active filter, surfaces both active and inactive counts so admins can switch at a glance, and adds at-a-glance context (active count in the heading + the event's date) so admins don't have to bounce back to the dashboard. It also tightens the table layout and polishes some microcopy.

How did you approach the change?

Active/inactive filtering

  • Added an inactive scope to EventRegistration (mirrors the existing active scope; reuses INACTIVE_STATUSES = cancelled, no_show).
  • EventsController#registrants now computes @active_count / @inactive_count from the filtered base scope (so counts reflect the current search/filters) and defaults to the active filter when no status_filter param is given.
  • An explicit attendance_status selection still takes precedence over the active/inactive grouping, preserving the dashboard drill-down behavior.
  • Two-tab segmented control (Active (N) / Inactive (M)) in the results header; tabs do a full-page nav so the search form's hidden status_filter field stays in sync.

Page context

  • Heading now shows the active count — Registrants (N) — and the event's date_range (the same decorator method the dashboard uses) appears beside the title.

Table layout & copy polish

  • Shortened column headers (Organization(s) → Organization, Payment status → Payment, Attendance status → Attendance) and relabeled the column toggle to "User confirmation".
  • Gave the Organization column the flexible width (w-full) and raised its truncation so org names are readable; trimmed the oversized Name column to compensate.
  • Each organization name now links to its profile (organization_path).
  • Kept payment badges on one line (whitespace-nowrap) so "$N due" doesn't wrap.
  • Centered the status columns (Scholarship / Payment / Attendance) — header and pill together — so they read as a distinct status band between the left-aligned text columns and the right-aligned Edit action.
  • Reworded the comment hint "Reason you're making a note" → "Reason for this note".

UI Testing Checklist

  • Registrants page loads with the Active tab selected by default, showing only active registrants
  • Heading shows Registrants (N) with the active count, plus event title + date range
  • Active/inactive counts are accurate and update with search/filters
  • Clicking Inactive shows only cancelled/no-show registrants; an explicit attendance status still wins
  • Organization column is roomy, names link to the org profile, payment badges don't wrap
  • Status column headers and pills are centered together

Anything else to add?

  • Rebased onto main, which renamed the manage action/route/partials to registrants and split the dev seeds into db/seeds/dev/*; conflicts resolved to keep both main's new filters and this branch's active/inactive logic.
  • Request specs cover: counts rendering, the active default, the inactive filter, attendance_status precedence, the heading count, and the event date.
  • date_range is weekday-prefixed (e.g. "Tue, Jun 2, 2026") to match the dashboard; flagging in case a bare date is preferred.

🤖 Generated with Claude Code

@maebeale maebeale marked this pull request as ready for review June 7, 2026 03:51
scope = scope.keyword(params[:keyword]) if params[:keyword].present?
scope = scope.attendance_status(params[:attendance_status]) if params[:attendance_status].present?

@active_count = scope.active.count

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.

Counts are computed from the keyword-filtered scope before the active/inactive grouping is applied, so both tab counts always reflect the current search rather than only the visible tab.

scope = scope.attendance_status(params[:attendance_status])
else
@status_filter = params[:status_filter].presence || "active"
scope = scope.inactive if @status_filter == "inactive"

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.

An explicit attendance_status takes precedence over the active/inactive default, preserving the existing dropdown drill-down. Absent that param, we default to the active filter.

<nav class="inline-flex rounded-lg bg-gray-100 p-0.5 text-sm font-medium" aria-label="Attendance filter">
<%= link_to manage_event_path(@event, status_filter: "active", keyword: params[:keyword].presence),
data: { turbo_frame: "_top" },
class: "px-3 py-1 rounded-md transition-colors #{current_filter == "active" ? "bg-white text-gray-800 shadow-sm" : "text-gray-500 hover:text-gray-700"}" do %>

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.

Tabs use turbo_frame: "_top" (full-page nav) intentionally: the search form lives outside the manage_results frame, so a frame-only swap would leave the form's hidden status_filter stale and out of sync with the visible tab.

autocomplete: "off",
class: "flex flex-col md:flex-row md:flex-wrap md:items-end gap-4 mb-6" do %>

<%= hidden_field_tag :status_filter, params[:status_filter].presence || "active" %>

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.

Hidden field keeps the selected tab when the keyword/status search form is submitted (which updates only the results frame).

maebeale and others added 2 commits June 8, 2026 13:10
Admins managing an event need to focus on people who are actually
coming. Showing cancelled/no-show registrants by default buries the
active roster, so the list now defaults to the active filter and
surfaces both counts as tabs to switch between them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Admins land on the registrants page to gauge turnout, so the heading now
carries the active count (matching the active tab default) and the event's
date range sits beside the title, sparing a trip back to the dashboard to
confirm which event and when.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@maebeale maebeale force-pushed the maebeale/registrant-active-inactive-counts branch from 5f8018f to af580c5 Compare June 8, 2026 17:38
@maebeale maebeale changed the title Default manage registrants to active, show active/inactive counts Default registrants to active; show counts and event date Jun 8, 2026
maebeale and others added 2 commits June 8, 2026 13:54
The registrants table was cramped: long column headers ate horizontal
space and organization names were truncated to 10 chars with no way to
reach the org. Shorten the headers, give the org column room and link
each org to its page, and keep payment badges on one line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
"Reason you're making a note" reads awkwardly; "Reason for this note" is
tighter and matches the surrounding microcopy tone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@maebeale maebeale merged commit 1f283a6 into main Jun 8, 2026
3 checks passed
@maebeale maebeale deleted the maebeale/registrant-active-inactive-counts branch June 8, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant