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
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Controller } from "@hotwired/stimulus"

// Drives the CE-credit box on the registration form. Colors the "Requested"
// toggle to signal save state: amber while the choice is pending (changed but
// not yet saved), the continuing-education theme color once it matches the
// stored "on" value, neutral gray when stored as off. While "Requested" is on it
// Drives the CE-credit box on the registration form. Mounted on the <section>
// so it can tint the whole card to signal save state: amber while the choice is
// pending (changed but not yet saved), the continuing-education theme color once
// it matches the stored "on" value, neutral gray when stored as off — the
// "Requested" toggle and the card share that color. While "Requested" is on it
// reveals the CE details (license number + hours) and keeps the "Provided" badge
// and amount-owed total ($rate × hours) in sync as the admin edits them.
export default class extends Controller {
Expand All @@ -22,6 +23,13 @@ export default class extends Controller {
this.trackTarget.classList.toggle("bg-teal-600", checked && !pending)
this.trackTarget.classList.toggle("bg-gray-200", !checked && !pending)

this.element.classList.toggle("bg-amber-50", pending)
this.element.classList.toggle("border-amber-200", pending)
this.element.classList.toggle("bg-teal-50", checked && !pending)
this.element.classList.toggle("border-teal-200", checked && !pending)
this.element.classList.toggle("bg-white", !checked && !pending)
this.element.classList.toggle("border-gray-200", !checked && !pending)

if (this.hasDetailsTarget) this.detailsTarget.classList.toggle("hidden", !checked)

this.updateLicenseBadge()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Controller } from "@hotwired/stimulus"

// Colors the "Requested" toggle to signal save state: amber while the choice is
// pending (changed but not yet saved with the registration form), the
// scholarship theme color once it matches the stored "on" value, and neutral
// gray when stored as off.
// Colors the "Requested" toggle and its whole card to signal save state: amber
// while the choice is pending (changed but not yet saved with the registration
// form), the scholarship theme color once it matches the stored "on" value, and
// neutral gray when stored as off. Mounted on the <section> so this.element is
// the card to tint. When a scholarship has already been awarded the toggle is
// gone — there's no checkbox to read, so we leave the server-rendered tint.
export default class extends Controller {
static targets = ["checkbox", "track"]
static values = { initial: Boolean }
Expand All @@ -13,11 +15,20 @@ export default class extends Controller {
}

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: Controller moved from the <label>/inner div up to the <section> so it can tint the whole card. This hasCheckboxTarget guard matters because an already-awarded scholarship renders no toggle — the controller still mounts, so without the guard refresh() would throw and clobber the server-rendered tint.

refresh() {
if (!this.hasCheckboxTarget) return

const checked = this.checkboxTarget.checked
const pending = checked !== this.initialValue

this.trackTarget.classList.toggle("bg-amber-500", pending)
this.trackTarget.classList.toggle("bg-fuchsia-600", checked && !pending)
this.trackTarget.classList.toggle("bg-gray-200", !checked && !pending)

this.element.classList.toggle("bg-amber-50", pending)
this.element.classList.toggle("border-amber-200", pending)
this.element.classList.toggle("bg-fuchsia-50", checked && !pending)
this.element.classList.toggle("border-fuchsia-200", checked && !pending)
this.element.classList.toggle("bg-white", !checked && !pending)
this.element.classList.toggle("border-gray-200", !checked && !pending)
}
}
10 changes: 5 additions & 5 deletions app/views/event_registrations/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -214,18 +214,18 @@
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. ---- %>
<section class="overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm">
<section class="overflow-hidden rounded-xl border shadow-sm transition-colors <%= f.object.ce_credit_requested ? "border-teal-200 bg-teal-50" : "border-gray-200 bg-white" %>"
data-controller="ce-credit-requested"
data-ce-credit-requested-initial-value="<%= f.object.ce_credit_requested %>"
data-ce-credit-requested-rate-value="<%= EventRegistration::CE_HOURLY_RATE_DOLLARS %>">
<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">
<i class="fa-solid fa-certificate"></i>
</span>
<h2 class="text-sm font-semibold text-gray-700">CE credits</h2>
</div>

<div class="space-y-3 p-4"
data-controller="ce-credit-requested"
data-ce-credit-requested-initial-value="<%= f.object.ce_credit_requested %>"
data-ce-credit-requested-rate-value="<%= EventRegistration::CE_HOURLY_RATE_DOLLARS %>">
<div class="space-y-3 p-4">
<label class="flex items-center gap-2.5 cursor-pointer">
<input type="hidden" name="event_registration[ce_credit_requested]" value="0" autocomplete="off">
<input type="checkbox"
Expand Down
9 changes: 5 additions & 4 deletions app/views/event_registrations/_scholarship.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
not create or destroy an award on its own. Awarding is a deliberate action
via "Add scholarship". On save, the controller cleans up an unrequested
scholarship only when it is an empty stub (no amount, tasks incomplete). ---- %>
<section class="overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm">
<% scholarship_active = scholarship.present? || event_registration.scholarship_requested %>
<section class="overflow-hidden rounded-xl border shadow-sm transition-colors <%= scholarship_active ? "border-fuchsia-200 bg-fuchsia-50" : "border-gray-200 bg-white" %>"
data-controller="scholarship-requested"
data-scholarship-requested-initial-value="<%= event_registration.scholarship_requested %>">
<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(:scholarships, intensity: 100) %> <%= DomainTheme.text_class_for(:scholarships, intensity: 600) %>">
<i class="fa-solid fa-graduation-cap"></i>
Expand All @@ -12,9 +15,7 @@

<div class="space-y-3 p-4">
<% unless scholarship %>
<label class="flex items-center gap-2.5 cursor-pointer"
data-controller="scholarship-requested"
data-scholarship-requested-initial-value="<%= event_registration.scholarship_requested %>">
<label class="flex items-center gap-2.5 cursor-pointer">
<input type="hidden" name="event_registration[scholarship_requested]" value="0" autocomplete="off">
<input type="checkbox"
name="event_registration[scholarship_requested]"
Expand Down