alumni_lookup

Phase 19: Alumni Champions Signup v2.0

Status: 🔄 In Progress (19.1–19.6 shipped; 19.7–19.8 planned) Priority: High Spec: docs/planning/champion-flow/SPEC.md Domain: alumnichampions.com Date Started: 2026-06-08


Overview

Rebuilds the public Champion signup flow that was retired in Phase 17.3. The new flow lives at alumnichampions.com/sign-up as a server-side multi-step wizard under a new public/ controller namespace, cleanly separated from both the staff (champions/) and portal (cp/) namespaces.

Key additions vs. v1:


Sub-Phase Status

Sub-phase Name Status
19.1 Foundation: Schema, Routes, Controller Shell ✅ Complete
19.2 Personal Info Flow (Steps 1–3) ✅ Complete
19.3 Quiz Flow + Role Selection + Light Interests ✅ Complete
19.4 Full Affinities, Submission + Mailer ✅ Complete
19.5 Confirmation Page + Staff Queue Integration ✅ Complete
19.6 UX Revision Pass (post-feedback) ✅ Complete
19.7 Congrats/Profile Page + Flow Reorder ✅ Complete
19.8 Interests Redesign (Spectrum Quiz) ✅ Complete
19.9 Signup Admin Dashboard, District Translation, Spam Guard ✅ Complete (v1.0.67)

Phase 19.1 — Completion Summary

Shipped: 2026-06-08

Deliverables

Process Note

Phase prep (sub-phase interview, planning summary, model handoff) was skipped for 19.1 due to a process error. All subsequent sub-phases must go through the full prep checkpoint before implementation begins.


Phase 19.2 — Completion Summary

Shipped: 2026-06-08

Deliverables

Spec Deviations (approved during planning)

  1. Graduation year is free text so users can provide multiple years.
  2. Belmont experience is collected as one free-text field (belmont_background) instead of normalized college/major selectors.
  3. Where You Are is profession-only; role selection is deliberately moved later in the flow.
  4. Interests and Role stubs are present to keep testing aligned with the intended order while full implementations remain in 19.3/19.4.

Deferred

Gotcha Captured

form_with url: (no model) + fields_for :scope renders field names as [scope][field] (leading bracket), which does not round-trip through params.require(:scope) from the rendered form. Fixed by using form_with model: signup, scope: :champion_signup.


Phase 19.3 — Completion Summary

Shipped: 2026-06-08

Deliverables

Flow (current)

who_you_are → belmont_experience → affinities (Interests) → where_you_are (Job) → role hub → [optional: question1–7 → quiz_results → role] → confirmation

Spec Deviations (approved during planning)

  1. Role hub is the Role-stage entry point; the quiz is an optional path via CTA (“Start at Role”).
  2. Quiz results route back to the role hub to confirm (“show results, then role”) rather than finalizing on the results page.
  3. Light Interests implemented now (checkboxes + note) instead of deferring all affinities to 19.4.
  4. “Skip for now” was restored after UX review to keep role optional at signup completion while preserving direct-pick and quiz paths.

Deferred to 19.4

Full affinity browse/search (affinity_codes, affinity_other) with expanded belonging_note prompt, submission mailer, staff-queue source tagging.


Phase 19.4 — Planning Checkpoint (2026-06-09)

Confirmed Scope

Explicitly Deferred

Questions Resolved

  1. Flow final step Keep role as the final completion step; do not reorder the wizard to end on affinities.
  2. Affinities depth Use full affinity browse/search UX for student activities, but without lifestage/belonging-categories capture.
  3. Field scope for affinities step Collect affinity_codes/affinity_other plus an expanded belonging_note; do not collect lifestage_interest or belonging_categories.
  4. Mailer dispatch mode Use background delivery (deliver_later) for welcome/admin notifications.
  5. Staff scope timing Source badge/filter changes will ship in 19.4 instead of waiting for 19.5.

What Was Implemented (19.4)


Phase 19.5 — Planning Checkpoint (2026-06-09)

Confirmed Scope

Staff Queue Filter Expansion (approved)

Confirmation Page Decisions

  1. No-role CTA guard Show a follow-up CTA only when a valid signed signup token is present.
  2. Role branch depth Show the full role activity list (not a shortened subset).

Explicitly Deferred / Removed

Questions Resolved

  1. How broad should 19.5 be? Broader pass approved in addition to baseline 19.5 requirements.
  2. What staff filters should be added now? Role status, BUID link status, affinities presence, recency buckets, contactability, and specific affinity.
  3. How should unknown affinity codes render on staff show? Show mapped affinity names when available; otherwise display raw codes.

What Was Implemented (19.5)


Phase 19.6 — Completion Summary

Shipped: 2026-06-09

Deliverables

Schema Change


Phase 19.7 — Planning Checkpoint (2026-06-24)

Why

Completion currently feels gated behind the full flow (Belmont Experience → Affinities → Where You Are → Role), but ChampionSignup#calculate_status already marks a signup “completed” (status 5) the moment email + graduation_year + zip_code are present — which happens at step 1 (who_you_are). The flow/UI/email timing just hasn’t caught up to that. This sub-phase moves the experienced completion point up to match the data model’s completion point, and turns the post-completion page into a returnable profile rather than a one-time confirmation screen.

Confirmed Scope

Questions Resolved

  1. Where does “completion” move to? Step 1 (who_you_are) — already true at the data layer; this sub-phase makes the experience match it.
  2. Is the Congrats page a one-time screen or a returnable profile? Returnable profile — same view serves both purposes, with adaptive copy.
  3. Profile link lifetime? On-demand/short-lived only (:profile_access, ~72h), regenerated per request. No permanent link.
  4. Welcome email timing? Immediate at step 1. (Nudge deferred — see below.)
  5. Education record visibility? Only shown for high-confidence (BUID-linked) matches.
  6. What happens after an optional step finishes? Returns to the profile/Congrats page, not chained to the next optional step automatically.
  7. Hub access (2026-06-25)? Require session OR valid :profile_access token; otherwise redirect to the landing “email me a link” prompt.
  8. Admin email timing (2026-06-25)? Both welcome + admin notification fire at step 1.
  9. Interests step rename (2026-06-25)? Deferred to 19.8.

Explicitly Deferred

Migration

None for 19.7. Token mechanism is stateless (signed_id); no new columns.

What Was Implemented (19.7)

Shipped: 2026-06-25

Deferred from 19.7 (logged to BACKLOG)

Ready to implement? Confirmed — proceed once the model handoff to the implementation model occurs.


Phase 19.8 — Planning Checkpoint (2026-06-24)

Why

The current quiz crowns a single role (“You are a Connection Advisor”), but ChampionQuizService.role_counts already computes a full per-area breakdown from the same 7 answers — it’s just not displayed that way. Moving to a spectrum display is largely a results-screen change, reusing existing quiz content and scoring logic. Staff also need the same spectrum visibility (and the ability to filter on it), which requires persisting the breakdown rather than only computing it for the public results screen.

Confirmed Scope

Questions Resolved

  1. Quiz input mechanic? Keep the existing multiple-choice questions; only the results screen changes.
  2. Direct pick-a-role path? Removed — quiz-only.
  3. Naming on results screen? Plain-language name + existing role title shown together.
  4. Does staff need this too? Yes — both viewing the breakdown and filtering by area/threshold, which requires persisting interest_scores rather than computing on the fly.
  5. Split staff work into its own sub-phase? No — bundled into 19.8.

Explicitly Deferred

Migration

Interview Addendum (2026-06-25)

Re-confirmed scope at the start of implementation planning. Four decisions refine/override the points above:

  1. Score format — percentages (0–100). interest_scores stores { role_key => percentage }, each area’s share of the answered questions, rounded to whole numbers. Not raw 0–7 counts. Public bars and the staff threshold both read percentages, so the staff queue filter is “area ≥ N%” (not “≥ N count”). ChampionQuizService already exposes role_counts; add a sibling method (e.g. interest_spectrum(answers)) that returns the percentage map — do not alter role_counts / generate_results / calculate_primary_role, which the Cp portal still depends on.
  2. Interests-stage entry is conditional, quiz-driven. Replaces the role hub: if the signup has already completed the quiz, the stage shows their interest graph (spectrum) with a “Retake the quiz” option; if not, it prompts them to take the quiz. Direct pick-a-role is gone. A low-emphasis “Skip for now” link is retained (consistent with the 19.3 decision keeping role/interests optional at signup completion) unless overridden.
  3. Cp authenticated portal quiz is unchanged. Cp::ChampionRolesHelper keeps the single-winner experience. 19.8 touches only the public signup results screen + staff admin. New service methods must be additive.
  4. Plain-language area names — use drafts (added as area_name on ChampionRoleService::ROLES):
    • Connection Advisor → Making Connections
    • Digital Ambassador → Sharing Stories
    • Community Builder → Bringing People Together
    • Giving Advocate → Supporting Causes

    Displayed as “Making Connections (Connection Advisor)”. Copy can be tuned later.

result_role still persisted as the top-scoring area (existing first-of-tied tie-break retained) for backward compatibility. Backfill computes percentages from answers; records with no answers are left {}.

Ready to implement? Confirmed — proceed once the model handoff to the implementation model occurs.

What Was Implemented (19.8)

Implementation Deviations from the Plan

  1. quiz_results kept as a distinct surface (not collapsed into the hub). After the final question the user sees a celebratory spectrum reveal (“Where your interests lean”) with “Save and continue” → hub; the Interests landing reuses the same _interest_spectrum partial when revisited. Lower flow churn, matches the “graph if answered / prompt if not” behavior.
  2. Step key stays role internally (param only, not user-visible) to avoid route/hub churn; the partial and copy are fully redesigned.
  3. interest_scores and the spectrum are v2-only. Legacy records store answers as {"q0" => "word"} (not letters), so they are excluded from scoring, backfill, and the staff breakdown/filter.

Post-Implementation Revisions (2026-06-25)

Follow-up tweaks from a UX/QA pass after the first build:

  1. Dropped the parenthetical role titles. The reveal and spectrum bars now show only the plain-language area name (e.g., “Bringing People Together”), not “(Community Builder)”. _interest_spectrum updated; area_label retained for the staff filter dropdown.
  2. Role icons replace the seal. The reveal header and each spectrum bar now use role_icon_svg instead of the full circular seal, for a lighter look.
  3. Staff show falls back to computed scores. ChampionSignupsController#show now computes the spectrum from answers when interest_scores is blank (any letter-valued quiz, keyed "0".."6" or legacy "q0".."q6" — scoring only counts values), so pre-backfill quiz-takers still render the full breakdown. The staff card now reuses the shared _interest_spectrum partial plus a “Leans most toward” header for parity with the public reveal.
  4. Fixed the staff “Select” assign-alumni link. It used link_to … method: :patch + data-confirm, which silently did a GET after @rails/ujs was removed (the PATCH-only route then 404’d). Switched to data: { turbo_method: :patch, turbo_confirm: … }.
  5. Backfilled existing v2 records so the staff Interest Area / Min % filter returns rows (the filter code was already correct; the records simply had no stored scores).

Post-Implementation Revisions (2026-06-26)

Follow-up welcome email rewrite, Champions branding pass, and a dev-environment bug fix found in the same session:

  1. Welcome email rewritten to a fixed letter format (“Dear [name],” → magic-of-Champions copy → the “connect you with the right opportunities” profile-link card → three Bruin/social action items → “— The Alumni Team”), with the Champions logo in the header band. Replaces the per-role-personalized copy from the prior commit’s redesign.
  2. Champions branding wired up on alumnichampions.com: favicons + the PWA manifest (manifest-champions.json — existed but was never linked from the layout) now use the -champions icon set; meta-image-champions.png is the OG/Twitter image on the landing flow and congrats hub; the site header uses the white Champions lockup. Hero/congrats-hub logo placement is mid-revision, owned directly by the user as of this writing — not yet on a Champions-specific lockup.
  3. Bug fix, found while wiring the email logo: the dev Puma server is SSL-only (Procfile.dev), but 7 places across Cp::/ChampionSignupMailer and Cp::Champion hardcoded protocol: "http" for dev.* hosts — those URLs connected but hung instead of erroring, so the breakage was invisible until someone actually loaded one. All switched to https. A separate bug in the same sweep: two staff-notification mailers pointed at local.test, which has no DNS record at all — repointed to dev.alumnilookup.com:3000.
  4. Cleanup: removed two untracked, unreferenced image files that had been dropped into public/ outside of any commit.
  5. See docs/CHANGELOG.md [Unreleased] for the full file list and test counts.