From a3413b2e27da48d5ddb836b1eb26e76b9d2289e2 Mon Sep 17 00:00:00 2001 From: Katya Sarmiento <5871075+Kitkatnik@users.noreply.github.com> Date: Sun, 26 Apr 2026 01:18:11 -0400 Subject: [PATCH 1/2] Filter schedule by kind; restyle day-nav and headers to match brand site Adds a Kind filter (All / Talk / Lightning / Embassy / Activity) to both the public Schedule page and the admin Schedule Items page, backed by a junk-safe `by_kind` scope that returns all rows when the URL param is missing or unknown. Filter state lives in the query string so filtered URLs are shareable. Day section visuals now mirror blueridgeruby.com/schedule: combined "Wednesday, April 29th" heading with ordinal sup, 4px navy item-table top-border, and plain underlined day-nav links (no pills). Kind filter keeps a pill treatment because its active/inactive state is meaningful. --- app/assets/stylesheets/application.css | 86 +++++++++++------- .../admin/schedule_items_controller.rb | 3 +- app/controllers/schedule_controller.rb | 5 +- app/models/schedule_item.rb | 4 + app/views/admin/schedule_items/index.html.erb | 89 ++++++++++--------- app/views/schedule/_day.html.erb | 15 ++-- app/views/schedule/index.html.erb | 27 ++++-- app/views/shared/_kind_filter.html.erb | 19 ++++ 8 files changed, 156 insertions(+), 92 deletions(-) create mode 100644 app/views/shared/_kind_filter.html.erb diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 9eb53b6..e92e934 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -347,71 +347,91 @@ hr { .day-nav { display: flex; justify-content: center; + column-gap: 1rem; + margin: 0 0 2.5rem; +} + +.day-nav a { + padding: 0.5rem; + color: #2672B5; + font-weight: 500; + text-decoration: underline; +} + + +/* ---------- Kind filter pills ----------------------------- */ + +.kind-filter { + display: flex; + justify-content: center; + align-items: center; flex-wrap: wrap; gap: 0.5rem; - margin: 1rem 0 3rem; + margin: 1rem 0 2rem; } -.day-nav a { +.kind-filter__label { + font-size: 0.95rem; + font-weight: 500; + color: #7a8189; + margin-right: 0.25rem; +} + +.kind-filter__btn { display: inline-block; padding: 0.375rem 1rem; border: 1px solid #d9dee1; border-radius: 999px; + background-color: transparent; color: #2672B5; font-weight: 500; font-size: 0.95rem; - transition: background-color 0.15s ease, border-color 0.15s ease; + transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; } -.day-nav a:hover { +.kind-filter__btn:hover { background-color: #f4f7fa; border-color: #2672B5; opacity: 1; } - -/* ---------- Schedule day sections ------------------------- */ - -.schedule-day { - padding-top: 2rem; - border-top: 1px solid #d9dee1; +.kind-filter__btn--active { + background-color: #0C2866; + border-color: #0C2866; + color: #ffffff; } -.schedule-day + .schedule-day { - margin-top: 3rem; +.kind-filter__btn--active:hover { + background-color: #0C2866; + border-color: #0C2866; + color: #ffffff; } -.schedule-day__header { - display: flex; - flex-direction: column; - gap: 0.25rem; - margin-bottom: 1.5rem; -} -@media (min-width: 640px) { - .schedule-day__header { - flex-direction: row; - align-items: baseline; - gap: 1rem; - } +/* ---------- Schedule day sections (blueridgeruby.com style) -- */ + +.schedule-day { + margin-bottom: 5rem; } -.schedule-day__label { +.schedule-day__heading { font-size: 1.75rem; font-weight: 500; color: #0C2866; - line-height: 1.1; + text-align: center; + line-height: 1.2; + margin-bottom: 1rem; } -.schedule-day__date { - font-size: 1.125rem; - color: #404040; +.schedule-day__heading sup { + font-size: 0.6em; + vertical-align: super; + margin-left: 0.05em; } -.schedule-day__subtitle { - font-size: 0.95rem; - color: #7a8189; - font-style: italic; +.schedule-day__items { + border-top: 4px solid #0C2866; + padding-top: 0.25rem; } diff --git a/app/controllers/admin/schedule_items_controller.rb b/app/controllers/admin/schedule_items_controller.rb index 02e6ff0..25371d6 100644 --- a/app/controllers/admin/schedule_items_controller.rb +++ b/app/controllers/admin/schedule_items_controller.rb @@ -3,7 +3,8 @@ class ScheduleItemsController < AdminController before_action :set_schedule_item, only: %i[edit update destroy] def index - @schedule_items = ScheduleItem.ordered + @selected_kind = ScheduleItem.kinds.key?(params[:kind].to_s) ? params[:kind] : nil + @schedule_items = ScheduleItem.by_kind(@selected_kind).ordered end def new diff --git a/app/controllers/schedule_controller.rb b/app/controllers/schedule_controller.rb index a4bddab..b7f6c48 100644 --- a/app/controllers/schedule_controller.rb +++ b/app/controllers/schedule_controller.rb @@ -1,6 +1,7 @@ class ScheduleController < ApplicationController def index - @items_by_day = ScheduleItem.public_items.ordered.group_by(&:day) - @planned_ids = current_user.plan_items.pluck(:schedule_item_id).to_set + @selected_kind = ScheduleItem.kinds.key?(params[:kind].to_s) ? params[:kind] : nil + @items_by_day = ScheduleItem.public_items.by_kind(@selected_kind).ordered.group_by(&:day) + @planned_ids = current_user.plan_items.pluck(:schedule_item_id).to_set end end diff --git a/app/models/schedule_item.rb b/app/models/schedule_item.rb index 72922b5..c277424 100644 --- a/app/models/schedule_item.rb +++ b/app/models/schedule_item.rb @@ -32,6 +32,10 @@ class ScheduleItem < ApplicationRecord :sort_time ) } + # Junk-safe: returns all rows when kind is blank or unknown. + scope :by_kind, ->(kind) { + kind.present? && kinds.key?(kind.to_s) ? where(kind: kind) : all + } # Creators always get auto-added to their own plan — whether the item is # private (only they see it) or public (others can RSVP). The rationale: diff --git a/app/views/admin/schedule_items/index.html.erb b/app/views/admin/schedule_items/index.html.erb index 130bf51..6f44d52 100644 --- a/app/views/admin/schedule_items/index.html.erb +++ b/app/views/admin/schedule_items/index.html.erb @@ -5,45 +5,54 @@ <%= link_to "Add item", new_admin_schedule_item_path, class: "btn btn-red" %> -
| Day | -Time | -Info | -Kind | -Public? | -Host | -- |
|---|
| <%= ScheduleItem::DAY_META.dig(item.day, :label) || item.day %> | -<%= item.time_label %> | -
- <%= item.title %>
- <% if item.location.present? %>
- <%= item.location %>
- <% end %>
- <% if item.description.present? %>
- <%= item.description %>
- <% end %>
- |
- <%= item.kind.humanize %> | -<%= item.is_public? ? "Public" : "Private" %> | -<%= item.host.presence || "—" %> | -
-
- <%= link_to "Edit", edit_admin_schedule_item_path(item), class: "btn btn-muted" %>
- <%= button_to "Delete", admin_schedule_item_path(item),
- method: :delete,
- data: { turbo_confirm: "Delete '#{item.title}'? RSVPs will also be removed." },
- class: "btn btn-red" %>
-
- |
+ Day | +Time | +Info | +Kind | +Public? | +Host | +
|---|