Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/policies/event_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ def google_analytics?
:autoshow_pre_date_text,
:autoshow_registration_close,
:public_registration_enabled,
:ce_credits_eligible,
:signed_in_one_click_enabled,
:autoshow_registration_details,
:hint_dates,
Expand Down
19 changes: 16 additions & 3 deletions app/views/event_registrations/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,21 @@
</div>
</div>

<%# ---- Organizations, scholarship, and continuing education — one row ---- %>
<%# ---- Organizations, scholarship, and continuing education — one row.
Scholarship only applies to paid events; CE credits only to events the
organizer flagged as eligible. Organizations fills whatever the hidden
boxes leave behind: it starts at two of four columns and absorbs one
more column for each box that's hidden. ---- %>
<% paid_event = f.object.event.cost_cents.to_i.positive? %>
<% show_scholarship = paid_event %>
<% show_ce = f.object.event.ce_credits_eligible? %>
<% org_span = 2 + (show_scholarship ? 0 : 1) + (show_ce ? 0 : 1) %>
<% org_span_class = { 2 => "sm:col-span-2", 3 => "sm:col-span-3", 4 => "sm:col-span-4" }.fetch(org_span) %>

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.

🤖 From Claude: The span is mapped to literal class strings (sm:col-span-2/3/4) rather than interpolated (sm:col-span-#{org_span}) so Tailwind's content scanner actually compiles them — interpolated class names wouldn't be generated.

<% active_orgs = f.object.registrant.affiliations.select { |a| !a.inactive? && (a.end_date.nil? || a.end_date >= Date.current) }.map(&:organization).compact.uniq.sort_by(&:name) %>
<% connected_org_ids = f.object.organizations.map(&:id) %>
<% addable_orgs = active_orgs.reject { |org| connected_org_ids.include?(org.id) } %>
<div class="grid grid-cols-1 gap-6 sm:grid-cols-4">
<section class="overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm sm:col-span-2">
<section class="overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm <%= org_span_class %>">
<div class="flex items-center gap-3 border-b border-gray-100 px-4 py-3">
<span class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg <%= DomainTheme.bg_class_for(:organizations, intensity: 100) %> <%= DomainTheme.text_class_for(:organizations, intensity: 600) %>">
<i class="fa-solid fa-building"></i>
Expand Down Expand Up @@ -208,12 +217,15 @@
</div>
</section>

<%= render "scholarship", event_registration: f.object, scholarship: f.object.scholarships.first %>
<% if show_scholarship %>
<%= render "scholarship", event_registration: f.object, scholarship: f.object.scholarships.first %>
<% end %>

<%# ---- CE credits — toggled "Requested" flag, plus the registrant's CE
details (license number + requested hours) and what they owe at the
default hourly rate, recomputed live by the ce-credit-requested
controller. The details collapse when CE isn't requested. ---- %>
<% if show_ce %>
<section class="overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm">
<div class="flex items-center gap-3 border-b border-gray-100 px-4 py-3">
<span class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gray-100 text-gray-500">
Expand Down Expand Up @@ -274,6 +286,7 @@
</div>
</div>
</section>
<% end %>
</div>

<% if f.object.payment_unresolved? %>
Expand Down
7 changes: 7 additions & 0 deletions app/views/events/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,13 @@
<p class="text-red-500 text-sm mt-1">Cost
<%= f.object.errors[:cost].join(", ") %></p>
<% end %>

<div class="mt-3">
<%= f.input :ce_credits_eligible,
as: :boolean,
label: "Eligible for continuing education credits",
hint: "When unchecked, the CE credits box is hidden on registrations." %>
</div>
</div>

<div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class AddCeCreditsEligibleToEvents < ActiveRecord::Migration[8.1]
def up
add_column :events, :ce_credits_eligible, :boolean, default: true, null: false
end

def down
remove_column :events, :ce_credits_eligible, if_exists: true
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[8.1].define(version: 2026_06_21_213947) do
ActiveRecord::Schema[8.1].define(version: 2026_06_22_120000) do
create_table "action_text_mentions", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.bigint "action_text_rich_text_id", null: false
t.datetime "created_at", null: false
Expand Down Expand Up @@ -517,6 +517,7 @@
t.boolean "autoshow_title", default: true, null: false
t.boolean "autoshow_videoconference_label", default: true, null: false
t.boolean "autoshow_videoconference_link", default: true, null: false
t.boolean "ce_credits_eligible", default: true, null: false
t.text "ce_hours_details"
t.string "ce_hours_details_label", default: "CE hours", null: false
t.integer "cost_cents"
Expand Down
6 changes: 6 additions & 0 deletions spec/models/event_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
it { should validate_numericality_of(:cost_cents).is_greater_than_or_equal_to(0).allow_nil }
end

describe "ce_credits_eligible" do
it "defaults to true" do
expect(build(:event).ce_credits_eligible).to be true
end
end

describe "destroying with form submissions" do
it "is blocked and keeps the submission when the event has one" do
event = create(:event)
Expand Down
41 changes: 41 additions & 0 deletions spec/system/event_registration_edit_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,47 @@
end
end

describe "conditional Organizations / scholarship / CE boxes" do
it "shows scholarship and CE boxes for a paid, CE-eligible event with organizations at half width" do
sign_in(admin)
visit edit_event_registration_path(registration)

expect(page).to have_css("h2", text: "Scholarship")
expect(page).to have_css("h2", text: "CE credits")
expect(page).to have_css("section.sm\\:col-span-2", text: "Registration organizations")
end

it "hides the scholarship box for a free event and widens organizations" do
event.update!(cost_cents: 0)
sign_in(admin)
visit edit_event_registration_path(registration)

expect(page).to have_no_css("h2", text: "Scholarship")
expect(page).to have_css("h2", text: "CE credits")
expect(page).to have_css("section.sm\\:col-span-3", text: "Registration organizations")
end

it "hides the CE box when the event is not CE-eligible and widens organizations" do
event.update!(ce_credits_eligible: false)
sign_in(admin)
visit edit_event_registration_path(registration)

expect(page).to have_css("h2", text: "Scholarship")
expect(page).to have_no_css("h2", text: "CE credits")
expect(page).to have_css("section.sm\\:col-span-3", text: "Registration organizations")
end

it "fills the full row with organizations for a free, non-CE-eligible event" do
event.update!(cost_cents: 0, ce_credits_eligible: false)
sign_in(admin)
visit edit_event_registration_path(registration)

expect(page).to have_no_css("h2", text: "Scholarship")
expect(page).to have_no_css("h2", text: "CE credits")
expect(page).to have_css("section.sm\\:col-span-4", text: "Registration organizations")
end
end

describe "delete button" do
it "deletes the registration" do
sign_in(admin)
Expand Down