Skip to content

Casadesign - DRAFT DO NOT MERGE#7051

Draft
giacoelho wants to merge 32 commits into
mainfrom
casadesign
Draft

Casadesign - DRAFT DO NOT MERGE#7051
giacoelho wants to merge 32 commits into
mainfrom
casadesign

Conversation

@giacoelho

Copy link
Copy Markdown
Collaborator

This is a work in progress. Will flag when it is ready to merge.

gia and others added 12 commits July 9, 2026 17:49
Introduce Tailwind v4 alongside the existing Bootstrap stack so the UI can be
modernized page-by-page without breaking current views.

- Add tailwindcss + @tailwindcss/cli (v4), build:tailwind[:dev] npm scripts,
  and a `tw` process in Procfile.dev. Output lands in app/assets/builds, which
  Sprockets already serves via the manifest's link_directory.
- Add app/assets/stylesheets/tailwind.css: CSS-first design system (Inter font
  + an indigo "brand" palette) — the visual direction for the redesign.
- New Tailwind-only layout casa_auth.html.erb (split brand panel + form),
  used by both the user and all-casa sign-in controllers.
- Redesign devise/sessions/new.html.erb in a clean, modern Stripe/Airbnb style
  and wire up remember-me properly.

Scoped to sign-in only; every other page keeps the Bootstrap `application`
layout untouched. First step of an incremental migration.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Approved font direction: swap the design-system typeface and the auth
layout's webfont link from Inter to Figtree (warmer humanist sans).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- design.md: living design-system doc (Tailwind v4 approach, Figtree type scale,
  color tokens, icon-tile pattern, component + empty-state specs, app-shell spec,
  migration checklist). Codifies the icon-tile treatment (icons on a soft colored
  background) for stat/status icons and reserves initial-avatars for people only.
- CLAUDE.md: point to design.md and record the casadesign commit/push-per-checkpoint
  workflow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New Tailwind-only layout: left sidebar with Pundit-guarded nav mirroring the
existing routes, plus a top bar (notifications, profile menu, sign out). Coexists
with the Bootstrap `application` layout — redesigned authenticated pages opt in via
`layout "casa_app"`. Icons via Bootstrap Icons CDN + Figtree (per design.md).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Supervisors now land on a real dashboard (DashboardController#show renders it in the
casa_app shell) instead of the Bootstrap volunteers table:

- SupervisorDashboard service builds per-volunteer follow-up status + summary stats
  from the supervisor's assigned volunteers.
- View: KPI cards, a "Needs your attention" list (icon-tile treatment per design
  feedback — replaces the ringed avatars), and a roster with color-coded
  contact-status pills.
- Empty states handled: no volunteers -> welcome + CTAs; nobody behind -> all
  caught up. The full volunteer management table remains at /volunteers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Feedback from design review:
- Avatar initials strip honorific prefixes (Mrs./Mr./…) and use first + last name
  only, via a shared `avatar_initials` helper (removed the duplicate in the service).
- Top-bar profile menu is triggered by the avatar alone; the name lives in the
  dropdown, not the trigger.
- Page header is the page name ("Dashboard") + <title>, not a greeting.

Accessibility (WCAG AA targets):
- Skip-to-content link, landmark labels, aria-labels on icon-only controls,
  aria-current on the active nav item, table scope + sr-only caption, visible
  focus rings, contrast bumps (slate-400 -> 500/600), role=status/alert on flash.

Responsive:
- Sidebar becomes an off-canvas drawer below lg with an accessible toggle
  (button + aria-expanded, Escape/backdrop to close) and a responsive grid/padding.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Names now render as first + last only (no Mr./Mrs./...) wherever a person is shown
in the redesign — the shell sidebar/profile menu and the supervisor dashboard
(names and aria-labels), plus the avatar initials.

- New `NamePresentation.strip_honorific` + a `display_person(user)` view helper.
- Presentation-only: the stored `display_name` is left untouched. (An attempted
  `User#display_name` override was reverted — a security spec requires display_name
  to round-trip raw input unchanged, e.g. dangerous strings.)
- Documented in design.md + CLAUDE.md so it's applied on every page going forward.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The bottom-of-sidebar user block (avatar + name + role) duplicated the identity
already shown by the top-right avatar account menu, and was non-interactive. Drop
it; the top-right menu is the single source for identity + account actions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "CV" placeholder brand mark wasn't a value-add at 36px (the org name already
identifies the chapter) and using the real org logo there would add image/variant
infrastructure for little gain. Show the org name alone in the sidebar header; the
full logo stays for contexts with room (sign-in, court reports). design.md updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring the rest of the auth flow in line with the redesigned sign-in:
- Forgot password (passwords/new), reset password (passwords/edit), and
  accept-invitation (invitations/edit) rebuilt in Tailwind, matching the sign-in's
  inputs/buttons/error styling. CASA's email-or-phone reset is preserved.
- Users::PasswordsController uses `layout "casa_auth"`; the invitation-accept action
  renders in casa_auth (admin invite `new`/`create` untouched).
- casa_auth `<title>` is now driven by `content_for(:page_title)`; each page sets its
  own title (Sign in / Reset your password / Choose a new password / Accept your invitation).

Verified all three render 200 in the new layout (accept-invitation via a valid token).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Apply the honorific-free naming rule to the existing Bootstrap UI, not just the
redesign:
- 37 `.display_name` person-name sites across ~20 legacy views now render via the
  `formatted_name` helper (org names, form-value symbols, and the checkbox-id slug
  line were intentionally excluded).
- The 4 DataTables (volunteer, supervisor, case-contact, reimbursement) strip
  honorifics on their Ruby name outputs (display_name + supervisor_name); SQL
  select/order strings are untouched.
- Added a `formatted_name(name)` string helper alongside `display_person`, both
  backed by `NamePresentation`.

Verified /supervisors, /volunteers, /casa_cases render 200 with zero honorifics;
datatable classes load clean; standardrb + rendering green. Docs updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The header helper text becomes a short single sentence with no em-dash; the org
name already appears in the sidebar header, so it's no longer repeated here.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added dependencies Touches dependency files javascript Touches JavaScript code ruby Touches Ruby code erb Touches ERB templates labels Jul 9, 2026
@giacoelho giacoelho marked this pull request as draft July 9, 2026 23:01
gia and others added 3 commits July 10, 2026 15:34
DashboardController#show now renders the casadesign supervisor dashboard
(SupervisorDashboard + casa_app layout) for supervisors, but the request
spec still asserted the old redirect to the volunteers overview and was
failing on the branch. Assert the dashboard renders and lists an assigned
volunteer instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…app shell

First page-by-page migration off the legacy Bootstrap UI, following design.md.
The notifications page is linked straight from the new shell (top-bar bell +
account menu), so it was the most visible remaining Bootstrap seam.

- Render NotificationsController#index in the casa_app layout.
- Restyle the index, NotificationComponent, and patch-notes partial onto the
  design system: card list, leading icon tiles, unread dot, and a cold-start
  empty state. Switch Font Awesome (fas fa-*) to Bootstrap Icons (bi-*), which
  is the icon set actually loaded on Tailwind pages.
- Move the specs off Bootstrap-class selectors onto semantic data-* hooks
  (data-notification-list-item, data-read / data-unread-dot) without weakening
  behavior coverage. All notification/patch-note ordering, counts, and empty
  states remain asserted.

Verified: component, view, request (renders the full casa_app layout), and
system specs all pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… backlog

- design.md: reframe as the permanent source of truth to refer to for all UI
  work. Add a "Design decisions (rationale)" log capturing the why behind the
  system (Tailwind-alongside-Bootstrap, layout opt-in, indigo/slate, Figtree,
  bi-* icons, icon-tile-vs-avatar, org-name-only sidebar, presentation-only
  honorific stripping, triage dashboards, empty-state taxonomy, a11y bar,
  build/output), a repeatable "Migrating a page" playbook, and a migration
  status that points at the backlog.
- design-todo.md: new prioritized, phased backlog (the "what's left") for the
  page-by-page migration off Bootstrap, plus cross-cutting infra and known
  pre-existing debt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the 🧪 Tests Tests label Jul 10, 2026
gia and others added 6 commits July 10, 2026 15:54
Second app-shell leaf page (linked from the account menu). Rebuilds the whole
edit-profile screen on the design system while preserving every behavior.

- Render UsersController in the casa_app layout.
- Rewrite edit.html.erb into cards: details, account, security, communication
  preferences, plus the volunteer languages table — using the documented input,
  button, and checkbox patterns.
- Replace the Bootstrap collapse accordions (Change Password / Change Email)
  with a small `disclosure` Stimulus controller (real <button> trigger, toggles
  a hidden panel, syncs aria-expanded) instead of relying on Bootstrap JS.
- Add a reusable Tailwind `shared/_form_errors` partial (the legacy
  `shared/_error_messages` stays for Bootstrap pages); it keeps the
  `@custom_error_header` hook so "... this password change ..." still renders.
- Preserve all field labels, ids, and JS-hook classes
  (toggle-email/sms-notifications, save-preference, password-new/-confirmation,
  submit-password, current_password_email, toggle-sms-notification-event) so
  require_communication_preference.js and password_confirmation.js keep working.

Verified: users request spec + the full edit system spec pass (79 examples);
erb-lint, standardrb, and StandardJS clean; JS bundle builds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rofile done

Add the two components introduced by the edit-profile migration (the Tailwind
form-error summary and the disclosure/collapsible-panel pattern) to design.md,
and tick edit profile in both the design.md status and design-todo.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rd subtitle

- Add a role badge (current_role as a brand-tinted pill) to the casa_app account
  menu header, under name + email — the one place identity metadata lives, and a
  parity with the role line the legacy header used to show. Industry-standard
  placement for a multi-role internal tool (keeps the sidebar/top-bar chrome clean).
- Supervisor dashboard subtitle -> "Track volunteer progress at a glance."
- Document the role badge in design.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The person-badge icon added no signal, so remove it. Colour the pill by role
using the design system's non-semantic accent tints — Volunteer = sky (blue),
Supervisor = violet (purple), Casa Admin = amber — so roles read apart at a
glance; unknown roles fall back to slate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…pt WCAG AA

- Drop the shouty `uppercase` transform from all design-system labels (account
  details, dashboard + languages table headers, patch-note category, auth "or"
  divider); render them sentence case. Sentence-case isolated copy ("My
  languages", "Learning hours this year").
- Bump muted label text from slate-400 (fails AA) to slate-500/600 for contrast.
- Redesign the form-error summary (shared/_form_errors): a role="alert" card with
  a leading icon and a tidy bulleted list instead of the plain block; keeps the
  heading text + #error_explanation so specs and behavior are unchanged.
- design.md: add Sentence case + Accessibility (WCAG 2.1 AA) as standing
  conventions, and fix the muted-text token. design-todo: track the app-wide
  interactive-label sentence-case pass and a slate-400 contrast audit.

Interactive button/field labels shared across pages (Update Profile, Change
Password, field labels) are spec-coupled across users/volunteers/all-casa-admin
and a shared example, so they're deferred to a holistic pass (tracked).

Verified: 109 examples across the touched pages pass; erb-lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per design feedback: one sentence, no bullets, dashboard-style icon tile.
- shared/_form_errors now renders "Unable to save: <messages via to_sentence>"
  inside a rose danger icon tile (bg-rose-100 text-rose-600, bi-exclamation-
  triangle) matching the dashboard, dropping the old heading + bulleted list.
- Update edit_spec assertions from the Rails "N errors prohibited this X from
  being saved:" text to "Unable to save".
- design.md: refresh the Form errors component note.

Verified: 79 users edit + request examples pass; erb-lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gia and others added 11 commits July 10, 2026 17:53
Volunteers with 2+ active cases now land on a triage dashboard instead of the
Bootstrap cases index; the single-active-case fast-path to "log a contact" is
unchanged.

- VolunteerDashboard service + dashboard/volunteer.html.erb: KPIs (active cases,
  cases needing a contact in 14+ days, hours logged 30d), a "needs your
  attention" list, and a "your cases" table with status pills + "log a contact"
  CTAs. Per-case last-contact is batched into one query.
- Shell parity: render org announcement banners in the casa_app shell
  (layouts/_casa_banner), and make the dismiss controller also add Tailwind's
  `hidden` class so the banner hides in both layouts.
- Specs: volunteer dashboard now renders (not redirects) in the request spec;
  re-point the legacy sidebar-dropdown navigation in the case_contacts and
  other_duties system specs to visit paths directly, since those dropdowns
  aren't in the new shell.

Verified: affected request + system specs pass in deterministic order; erb-lint,
standardrb, StandardJS clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Admins now land on an org triage dashboard instead of redirecting to the
supervisors page.

- AdminDashboard service + dashboard/admin.html.erb: chapter KPIs (active
  volunteers, active cases, unassigned cases, cases needing a contact) and a
  "needs your attention" list of unassigned active cases each with an "assign a
  volunteer" CTA; a cold-start state for brand-new chapters. Queries are
  aggregate/batched (active cases + one grouped contact lookup + counts) to stay
  cheap at org scale — no per-case/per-volunteer queries.
- dashboard request spec: admin renders the dashboard (not a redirect).

Verified: dashboard request spec + the admin visit-root system specs
(banners/new, casa_cases/new, court_dates/edit) pass; erb-lint + standardrb clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The last row butted against the card's rounded bottom corner (unlike the top,
which the header border defines). Add pb-2 to the card so the final row clears
the corner, keeping every row a uniform height rather than singling out the last
one. Documented the table-in-card pattern in design.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…orners

Same treatment as the dashboard tables. The notifications list has no header, so
its first and last rows both butt against the card's rounded corners — add py-2
(both sides) so they clear. Generalized the table-in-card note in design.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…wind skin

Phase 3 groundwork. Rather than reimplement the server-side DataTables (search,
sort, paginate, filters, state save, column toggles), skin them: add a
DataTables Tailwind layer to tailwind.css that restyles the generated chrome
(search box, page-length select, info text, pagination) and the table shell.
Because tailwind.css only loads on the casadesign shell, the skin can't touch
the legacy Bootstrap tables.

Documented the decision + a Data tables component note in design.md, and the
per-page plan in design-todo: cases index first (ERB-rendered rows, most
tractable); server-side tables additionally need the dashboard.js columns.render
output moved from Bootstrap markup + lni icons to Tailwind + bi-*.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
First Phase 3 datatable page. The cases index (volunteer "My Cases" + admin /
supervisor roster) now renders on the casa_app shell.

- Rebuild the view + table in Tailwind; the DataTables skin styles the
  search/pagination chrome. Render in casa_app with @active_nav = "cases".
- Replace the Bootstrap dropdown filters + column-picker modal with `dropdown`
  popovers (new Stimulus controller: toggle + close on outside-click/Escape),
  preserving every JS hook (.casa-case-filters, .status-options, #visibleColumns,
  .toggle-visibility, data-value/data-column) so dashboard.js filtering + column
  toggles keep working. The column picker stays outside .casa-case-filters so the
  filter-redraw handler doesn't bind to it.
- Skin: pad the DataTables controls to line up with px-4 cells.
- Action-button + column-header labels stay Title Case (spec-coupled across the
  new-case / case-group / bulk-court-date flows) — sentence-casing those belongs
  to the tracked interactive-label pass.

Verified: casa_cases/index (filters + links), dashboard/show (volunteer + admin),
casa_cases request spec, additional_index, casa_cases/new, case_groups all pass.
bulk_court_dates/new is a pre-existing flake (fails on the clean branch too).
erb-lint + StandardJS clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ataTables)

Reverses the "theme jQuery DataTables" approach — theming couldn't match the
dashboard tables or meet WCAG (its generated chrome fights the design system).
The cases index is now a hand-built Tailwind table matching the dashboard, with
server-side filtering + Pagy pagination.

- Controller: server-side filters (status [default active], assignment,
  transition-aged, prefix) + Pagy; drop the client-side DataTables path.
- View: bespoke table (readable headers, empty-state row, card + inset), a clear
  filter bar of selects that submit on change (new auto-submit Stimulus
  controller), and a reusable shared/_pagination partial (Pagy -> "Showing X-Y of
  Z" + page controls; WCAG nav/aria-current/rel). Consistent action buttons.
- Remove the now-dead DataTables Tailwind skin and the dropdown controller (its
  popover filters are replaced by selects).
- Rewrite the coupled specs (index + additional_index) for server-side filtering.
- design.md / design-todo: reverse the decision; document bespoke tables +
  pagination as the pattern.

Dropped for v1 (follow-ups): column-visibility picker, sortable headers. Action /
header labels stay Title Case (spec-coupled).

Verified: cases index / additional_index / request specs, dashboard/show, and the
new-case + case-group nav flows all pass; erb-lint, standardrb, StandardJS clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ransition

Review feedback on the cases index:
- Filter selects: `appearance-none` + a positioned `bi-chevron-down` so the
  dropdown chevron has proper right padding (was the cramped native arrow).
- Row action: the stranded far-right "Edit" text link is now a compact
  right-aligned pencil icon button (aria-labelled), matching the dashboard roster.
- Transition Aged Youth: drop the whimsical 🦋/🐛 emoji (butterfly = aged,
  caterpillar = not) for a clean indicator — a violet "Yes" pill / muted "No".
  Scoped to the new UI; the shared decorator keeps the emoji on unmigrated legacy
  pages. Documented in design.md.
- Blank hearing-type / judge cells show a muted em-dash instead of empty.

Verified: cases index / additional_index / dashboard-show specs pass; erb-lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
An icon-only pencil wasn't clear enough. Restore a visible "Edit" label as a
compact bordered button; keep the per-row aria-label ("Edit <case number>") so
the accessible name stays unique and descriptive (WCAG 2.4.4 / 2.5.3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cases index carried "Hearing Type" and "Judge" columns, but migration
20230729213608 (2023) removed hearing_type_id/judge_id from casa_cases and moved
that data onto court dates — so those two columns had rendered blank for every
case since. Drop them and show a single, meaningful "Next court date" instead:

- CasaCaseDecorator#formatted_next_court_date picks the earliest upcoming court
  date from the case's (preloaded) court_dates and formats it (:full); blanks
  render a muted em-dash.
- Controller preloads :court_dates (dropping the dead :hearing_type/:judge
  eager-load) — instrumented the request to confirm a single court_dates query
  for the whole page (no N+1).
- Sentence-cased the (now index-owned) column headers.
- Decorator unit specs cover upcoming/none/past-only; additional_index_spec updated.

design.md + design-todo.md: record the finding, add a stakeholder question (is
next court date the right roster column, or the upcoming hearing's type/judge?),
and flag the vestigial CasaCase#hearing_type/#judge associations for eventual
removal (still referenced by supervisors/index + legacy pages).

Verified: casa_cases index / additional_index / request + decorator specs
(97 examples) pass; erb-lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Edit action had been rebuilt as a *secondary* button (bordered white +
shadow) — too much emphasis for a control that repeats on every row and competes
with the brand-coloured case-number link. Make it tertiary/ghost: no border,
fill, or shadow; neutral slate-600 ink (>= AA under visible text, unlike the
slate-400 icon-only variant); leading pencil icon; subtle slate-100 hover wash.
Give the trailing actions cell an extra end gutter (pr-6) so the control clears
the card edge without skewing the button's own padding.

Documented the Tertiary (ghost) variant in design.md.

Verified: casa_cases index / additional_index specs pass; erb-lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Touches dependency files erb Touches ERB templates javascript Touches JavaScript code ruby Touches Ruby code 🧪 Tests Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant