Skip to content

Commit b10d3e7

Browse files
committed
Add cancelled/abandoned event status
1 parent 7ce31ff commit b10d3e7

File tree

16 files changed

+423
-16
lines changed

16 files changed

+423
-16
lines changed

app/controllers/courses_controller.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def show
2020
@location = Location.find_by!(slug: params[:slug])
2121
@locations = Location.all.order(:name)
2222
@next_event = Event.not_finalised.where("date >= ?", Date.today).order(:date).first
23+
@abandoned_event = Event.where(status: "abandoned", location: @location).where("date >= ?", Date.today).order(:date).first
2324
@latest_event = @location.latest_event
2425
@current_year_events = @location.events.where("strftime('%Y', date) = ?", Date.today.year.to_s).order(:date)
2526
end

app/controllers/events_controller.rb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ class EventsController < ApplicationController
44
skip_before_action :require_admin!, only: [ :index, :show, :show_latest ]
55
allow_unauthenticated_access(only: [ :index, :show, :show_latest ])
66

7-
before_action :set_event, only: [ :show, :edit, :update, :destroy, :edit_results, :activate, :deactivate ]
7+
before_action :set_event, only: [ :show, :edit, :update, :destroy, :edit_results, :activate, :deactivate, :abandon, :archive ]
88

99
def index
1010
if Current.user&.admin?
1111
@events = Event.order(number: :desc).includes(:results)
1212
else
13-
@events = Event.where(status: "finalised").order(number: :desc).includes(:results)
13+
@events = Event.where(status: [ "finalised", "abandoned", "cancelled" ]).order(number: :desc).includes(:results)
1414
end
1515
end
1616

@@ -77,13 +77,23 @@ def deactivate
7777
redirect_to dashboard_path, notice: "Event #{@event} deactivated! Finish position claiming is now disabled."
7878
end
7979

80+
def abandon
81+
@event.abandon!
82+
redirect_to dashboard_path, notice: "Event #{@event} has been cancelled."
83+
end
84+
85+
def archive
86+
@event.archive_as_cancelled!
87+
redirect_to dashboard_path, notice: "Event #{@event} has been archived."
88+
end
89+
8090
private
8191

8292
def set_event
8393
@event = Event.find_by number: params[:number]
8494
end
8595

8696
def event_params
87-
params.expect(event: [ :number, :date, :location_id, :description, :status, :facebook_url, :strava_url ])
97+
params.expect(event: [ :number, :date, :location_id, :description, :status, :facebook_url, :strava_url, :cancellation_reason ])
8898
end
8999
end

app/controllers/static_pages_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def admin_dashboard
1212
end
1313

1414
def home
15-
@upcoming_events = Event.not_finalised.includes(:location).where("date >= ?", Date.today).order(:date).limit(3)
15+
@upcoming_events = Event.upcoming_for_home.includes(:location).where("date >= ?", Date.today).order(:date).limit(3)
1616
@statistics = Event.home_statistics
1717

1818
if authenticated? && (active_event = @upcoming_events.find(&:active?))

app/models/event.rb

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
class Event < ApplicationRecord
22
include HomeStatistics
33

4-
enum :status, { draft: "draft", in_progress: "in_progress", finalised: "finalised" }
4+
enum :status, { draft: "draft", in_progress: "in_progress", finalised: "finalised", abandoned: "abandoned", cancelled: "cancelled" }
55

66
after_update :send_results_emails_if_finalised
77
after_update :invalidate_statistics_cache_if_finalised
@@ -15,7 +15,9 @@ class Event < ApplicationRecord
1515
has_many :check_ins
1616
has_many :checked_in_users, through: :check_ins, source: :user
1717

18-
scope :not_finalised, -> { where.not(status: "finalised") }
18+
scope :not_finalised, -> { where.not(status: [ "finalised", "abandoned", "cancelled" ]) }
19+
scope :upcoming_for_home, -> { where.not(status: [ "finalised", "cancelled" ]) }
20+
scope :public_visible, -> { where(status: [ "in_progress", "finalised", "abandoned", "cancelled" ]) }
1921

2022
validates :date, presence: true
2123
validates :number, numericality: { only_integer: true, greater_than: 0 }
@@ -51,6 +53,7 @@ def active?
5153
end
5254

5355
def activate!
56+
raise "Cannot activate an abandoned or cancelled event" if abandoned? || cancelled?
5457
Event.transaction do
5558
Event.where(status: "in_progress").where.not(id: id).update_all(status: "draft")
5659
update!(status: "in_progress")
@@ -61,6 +64,16 @@ def deactivate!
6164
update!(status: "draft")
6265
end
6366

67+
def abandon!
68+
raise "Cannot abandon a finalised event" if finalised?
69+
update!(status: "abandoned")
70+
end
71+
72+
def archive_as_cancelled!
73+
raise "Can only archive abandoned events" unless abandoned?
74+
update!(status: "cancelled")
75+
end
76+
6477
private
6578

6679
def send_results_emails_if_finalised

app/views/courses/show.html.erb

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,27 @@
4545
</div>
4646
</div>
4747
<div class="mt-1 text-3xl font-semibold tracking-tight text-primary"><%= event.date.strftime("%-d %B") %></div>
48+
<% elsif event.abandoned? || event.cancelled? %>
49+
<div class="mt-1 text-3xl font-semibold tracking-tight text-red-500 line-through"><%= event.date.strftime("%-d %B") %></div>
50+
<div class="text-sm text-red-600 mt-1">Cancelled</div>
51+
<% elsif event.finalised? %>
52+
<div class="mt-1 text-3xl font-semibold tracking-tight text-gray-500 line-through"><%= event.date.strftime("%-d %B") %></div>
4853
<% else %>
49-
<div class="mt-1 text-3xl font-semibold tracking-tight <%= event.finalised? ? 'text-gray-500 line-through' : 'text-gray-900' %>"><%= event.date.strftime("%-d %B") %></div>
54+
<div class="mt-1 text-3xl font-semibold tracking-tight text-gray-900"><%= event.date.strftime("%-d %B") %></div>
5055
<% end %>
5156
</div>
5257
<% end %>
5358
</div>
5459
</div>
5560

56-
<% if active_event = Event.find_by(status: "in_progress", location: @location) %>
61+
<% if @abandoned_event %>
62+
<div class="mt-8 p-6 bg-red-50 border-2 border-red-500 rounded-lg text-center">
63+
<h2 class="text-3xl font-bold text-red-600 mb-2">Event Cancelled</h2>
64+
<p class="text-xl text-red-800">
65+
The <%= @abandoned_event.date.strftime("%-d %B") %> event has been cancelled<%= ": #{@abandoned_event.cancellation_reason}" if @abandoned_event.cancellation_reason.present? %>.
66+
</p>
67+
</div>
68+
<% elsif active_event = Event.find_by(status: "in_progress", location: @location) %>
5769
<div class="mt-8 text-center">
5870
<% if authenticated? && active_event.check_ins.exists?(user: Current.session.user) %>
5971
<%= link_to "Check Others In", check_in_path(CheckIn.token_for_event(active_event.number)), class: "inline-flex items-center justify-center px-6 py-3 rounded-full border border-primary whitespace-nowrap text-base font-medium text-primary hover:bg-primary-bg" %>

app/views/events/_form.html.erb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,22 @@
5656
<%= form.radio_button :status, 'finalised', class: "h-4 w-4 border-gray-400 focus:outline-blue-600" %>
5757
<%= form.label :status_finalised, "Finalised (Results ready)", class: "ml-2" %>
5858
</div>
59+
<div class="flex items-center gap-2">
60+
<%= form.radio_button :status, 'abandoned', class: "h-4 w-4 border-gray-400 focus:outline-blue-600" %>
61+
<%= form.label :status_abandoned, "Abandoned (Cancelled, still shown on home page)", class: "ml-2" %>
62+
</div>
63+
<div class="flex items-center gap-2">
64+
<%= form.radio_button :status, 'cancelled', class: "h-4 w-4 border-gray-400 focus:outline-blue-600" %>
65+
<%= form.label :status_cancelled, "Cancelled (Archived, removed from home page)", class: "ml-2" %>
66+
</div>
5967
</div>
6068
</div>
6169

70+
<div class="my-5">
71+
<%= form.label :cancellation_reason, "Cancellation Reason (for abandoned/cancelled events)" %>
72+
<%= form.text_area :cancellation_reason, rows: 3, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": event.errors[:cancellation_reason].none?, "border-red-400 focus:outline-red-600": event.errors[:cancellation_reason].any?}], placeholder: "e.g., Due to heavy rain" %>
73+
</div>
74+
6275
<div class="inline">
6376
<%= form.submit class: "w-full sm:w-auto rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %>
6477
</div>

app/views/events/index.html.erb

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,32 @@
3939
<tbody class="divide-y divide-gray-200 bg-white">
4040
<% @events.each do |event| %>
4141
<tr class="hover:bg-brand-green/50">
42-
<td class="whitespace-nowrap pl-4 pr-3 py-5 text-2xl text-gray-700"><%= link_to "##{event.number}#{event.location}", event %></td>
42+
<td class="pl-4 pr-3 py-5 text-2xl text-gray-700">
43+
<%= link_to event do %>
44+
<div class="flex items-center gap-2">
45+
<span>#<%= event.number %><%= event.location %></span>
46+
<% if event.abandoned? %>
47+
<span class="inline-flex items-center rounded-md bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-red-600/20">CANCELLED</span>
48+
<% elsif event.cancelled? %>
49+
<span class="inline-flex items-center rounded-md bg-gray-50 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/20">CANCELLED</span>
50+
<% end %>
51+
</div>
52+
<% if (event.abandoned? || event.cancelled?) && event.cancellation_reason.present? %>
53+
<div class="text-sm text-gray-600 mt-1"><%= event.cancellation_reason %></div>
54+
<% end %>
55+
<% end %>
56+
</td>
4357
<td class="whitespace-nowrap px-3 py-5 text-2xl text-gray-700"><%= link_to l(event.date), event %></td>
44-
<td class="whitespace-nowrap px-3 py-5 text-2xl text-gray-700"><%= link_to (event.results.count + event.volunteers.count), event %></td>
45-
<td class="whitespace-nowrap pl-3 pr-4 py-5 text-2xl text-gray-700"><%= link_to event.results.order(Result.arel_table[:time].asc.nulls_last).first&.time_string || "N/A", event %></td>
58+
<td class="whitespace-nowrap px-3 py-5 text-2xl text-gray-700">
59+
<%= link_to event do %>
60+
<%= (event.abandoned? || event.cancelled?) ? "N/A" : (event.results.count + event.volunteers.count) %>
61+
<% end %>
62+
</td>
63+
<td class="whitespace-nowrap pl-3 pr-4 py-5 text-2xl text-gray-700">
64+
<%= link_to event do %>
65+
<%= (event.abandoned? || event.cancelled?) ? "N/A" : (event.results.order(Result.arel_table[:time].asc.nulls_last).first&.time_string || "N/A") %>
66+
<% end %>
67+
</td>
4668
</tr>
4769
<% end %>
4870
</tbody>

app/views/events/show.html.erb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@
2828
</li>
2929
</ol>
3030
</nav>
31+
<% if @event.abandoned? || @event.cancelled? %>
32+
<div class="mb-6 p-4 bg-red-50 border border-red-200 rounded-lg text-center">
33+
<p class="text-xl font-semibold text-red-700">This event was cancelled</p>
34+
<% if @event.cancellation_reason.present? %>
35+
<p class="mt-2 text-gray-700"><%= @event.cancellation_reason %></p>
36+
<% end %>
37+
</div>
38+
<% end %>
3139
<div class="text-center mb-8">
3240
<h1 class="text-4xl font-bold text-gray-900">
3341
<%= "Event ##{@event.number}#{l @event.date}#{@event.location}" %>

app/views/static_pages/admin_dashboard.html.erb

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,32 @@
218218
<% end %>
219219
</div>
220220
</div>
221-
<% else %>
221+
<% end %>
222+
223+
<% abandoned_events = Event.where(status: "abandoned").order(date: :asc) %>
224+
<% if abandoned_events.any? %>
225+
<div class="mt-8 mb-8">
226+
<h2 class="text-pretty text-3xl font-medium tracking-tight text-gray-950 mb-4">Cancelled Events Pending Archival</h2>
227+
<div class="bg-red-50 border border-red-200 rounded-lg p-4">
228+
<% abandoned_events.each do |event| %>
229+
<div class="flex items-center justify-between mb-3 last:mb-0">
230+
<div>
231+
<span class="text-lg font-medium text-gray-900"><%= link_to "#{event.location} - #{event.date}", event_path(event.number), class: "text-gray-900 hover:text-primary" %></span>
232+
<% if event.cancellation_reason.present? %>
233+
<p class="text-sm text-gray-600 mt-1"><%= event.cancellation_reason %></p>
234+
<% end %>
235+
</div>
236+
<div class="flex gap-2">
237+
<%= link_to "Edit", edit_admin_event_path(event.number), class: "justify-center rounded-md border border-transparent bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-blue-500 cursor-pointer" %>
238+
<%= button_to "Archive", archive_admin_event_path(event.number), method: :post, form: { data: { turbo_confirm: "Archive this event? It will be removed from the home page." }, class: "inline-block" }, class: "justify-center rounded-md border border-transparent bg-gray-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-gray-700 cursor-pointer" %>
239+
</div>
240+
</div>
241+
<% end %>
242+
</div>
243+
</div>
244+
<% end %>
245+
246+
<% unless @event %>
222247
<p class="text-gray-600 mt-8">No in-progress events. All events have been finalized!</p>
223248
<% end %>
224249
</div>

app/views/static_pages/home.html.erb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@
1313
<div class="relative -m-2 grid grid-cols-1 rounded-4xl max-lg:mx-auto max-lg:w-full max-lg:max-w-md overflow-hidden">
1414
<% if index == 0 %>
1515
<%= link_to course_path(event.location), class: "absolute top-0 right-0 w-16 h-16" do %>
16-
<div class="bg-primary absolute transform rotate-45 text-center text-white font-semibold py-1 right-[-40px] top-[32px] w-[170px]">
17-
Next Event
18-
</div>
16+
<% if event.abandoned? %>
17+
<div class="bg-red-600 absolute transform rotate-45 text-center text-white font-semibold py-1 right-[-40px] top-[32px] w-[170px]">
18+
CANCELLED
19+
</div>
20+
<% else %>
21+
<div class="bg-primary absolute transform rotate-45 text-center text-white font-semibold py-1 right-[-40px] top-[32px] w-[170px]">
22+
Next Event
23+
</div>
24+
<% end %>
1925
<% end %>
2026
<% end %>
2127
<div class="rounded-4xl bg-white p-10 pb-9 shadow-2xl ring-1 ring-black/25 ring-inset">
@@ -28,6 +34,9 @@
2834
<%= link_to course_path(event.location) do %>
2935
<div class="mt-8 text-5xl font-medium <%= index == 0 ? "text-primary" : "text-gray-950" %>"><%= event.date.strftime("%-d %b") %></div>
3036
<% end %>
37+
<% if event.abandoned? && event.cancellation_reason.present? %>
38+
<p class="mt-2 text-sm text-red-600"><%= event.cancellation_reason %></p>
39+
<% end %>
3140
<div class="mt-8 flex gap-2 flex-wrap">
3241
<% if index == 0 && !event.active? %>
3342
<%= link_to "Course Info", course_path(event.location), class: "inline-flex items-center justify-center px-4 py-[calc(theme(spacing.2)-1px)] rounded-full border border-transparent bg-primary shadow-md whitespace-nowrap text-base font-medium text-white hover:bg-primary-hover" %>

0 commit comments

Comments
 (0)