Skip to content

Commit 5b692c8

Browse files
committed
refactor: rename InvitationController to WorkshopInvitationController
- Inline InvitationControllerConcerns into the controller - Rename controller to WorkshopInvitationController for clarity - Add dual routes for backwards compatibility (/invitation and /workshop_invitation) - Rename views from app/views/invitation to app/views/workshop_invitation - Add .worktrees/ to .gitignore
1 parent 8136ebd commit 5b692c8

9 files changed

Lines changed: 123 additions & 117 deletions

File tree

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,5 @@ vendor/bundle
5959
yarn-debug.log*
6060
.yarn-integrity
6161

62-
# Git worktrees
63-
.worktrees
62+
# Worktrees
63+
.worktrees/

app/controllers/concerns/invitation_controller_concerns.rb

Lines changed: 0 additions & 73 deletions
This file was deleted.

app/controllers/invitation_controller.rb

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
class WorkshopInvitationController < ApplicationController
2+
include WorkshopInvitationConcerns
3+
4+
# NOTE: This controller handles workshop invitations (WorkshopInvitation model).
5+
# It provides accept/reject RSVP actions for workshop attendees via token-based links.
6+
# Routes: /invitation/:token (legacy) and /workshop_invitation/:token
7+
8+
def show
9+
@announcements = @invitation.member.announcements.active
10+
@tutorial_titles = Tutorial.all_titles
11+
12+
@workshop = WorkshopPresenter.decorate(@invitation.workshop)
13+
14+
render plain: @workshop.attendees_csv if request.format.csv?
15+
end
16+
17+
def update
18+
@invitation.assign_attributes(invitation_params.merge!(attending: true, rsvp_time: Time.zone.now))
19+
return back_with_message(@invitation.errors.full_messages) unless @invitation.valid?
20+
21+
@invitation.update(invitation_params)
22+
back_with_message(t('messages.invitations.updated_details'))
23+
end
24+
25+
# Inline accept from InvitationControllerConcerns
26+
def accept
27+
user = current_user || @invitation.member
28+
workshop = @invitation.workshop
29+
return back_with_message(t('messages.already_rsvped')) if @invitation.attending?
30+
31+
@invitation.assign_attributes(invitation_params.merge!(attending: true, rsvp_time: Time.zone.now))
32+
return back_with_message(@invitation.errors.full_messages) unless @invitation.valid?
33+
34+
if user.has_existing_RSVP_on(workshop.date_and_time)
35+
return back_with_message(t('messages.invitations.rsvped_to_other_workshop'))
36+
end
37+
38+
return back_with_message(t('messages.already_invited')) if attending_or_waitlisted?(workshop, user)
39+
40+
@workshop = WorkshopPresenter.decorate(@invitation.workshop)
41+
if available_spaces?(@workshop, @invitation)
42+
@invitation.update(invitation_params.merge!(attending: true, rsvp_time: Time.zone.now))
43+
@workshop.send_attending_email(@invitation)
44+
45+
back_with_message(t('messages.accepted_invitation', name: @invitation.member.name))
46+
else
47+
back_with_message(t('messages.no_available_seats'))
48+
end
49+
end
50+
51+
# Inline reject from InvitationControllerConcerns
52+
def reject
53+
@workshop = WorkshopPresenter.decorate(@invitation.workshop)
54+
if @invitation.workshop.date_and_time - 3.5.hours >= Time.zone.now
55+
if @invitation.attending.eql? false
56+
redirect_back(fallback_location: invitation_path(@invitation),
57+
notice: t('messages.not_attending_already'))
58+
else
59+
@invitation.update_attribute(:attending, false)
60+
61+
next_spot = WaitingList.next_spot(@invitation.workshop, @invitation.role)
62+
63+
if next_spot.present?
64+
invitation = next_spot.invitation
65+
next_spot.destroy
66+
invitation.update(attending: true, rsvp_time: Time.zone.now, automated_rsvp: true)
67+
@workshop.send_attending_email(invitation, true)
68+
end
69+
70+
redirect_back(
71+
fallback_location: invitation_path(@invitation),
72+
notice: t('messages.rejected_invitation', name: @invitation.member.name)
73+
)
74+
end
75+
else
76+
redirect_back(
77+
fallback_location: invitation_path(@invitation),
78+
notice: 'You can only change your RSVP status up to 3.5 hours before the workshop'
79+
)
80+
end
81+
end
82+
83+
private
84+
85+
def invitation_params
86+
if params.key?(:workshop_invitation)
87+
params.require(:workshop_invitation).permit(:tutorial, :note)
88+
else
89+
{}
90+
end
91+
end
92+
93+
def available_spaces?(workshop, invitation)
94+
(invitation.role.eql?('Student') && workshop.student_spaces?) ||
95+
(invitation.role.eql?('Coach') && workshop.coach_spaces?)
96+
end
97+
98+
# Inline from InvitationControllerConcerns
99+
def attending_or_waitlisted?(workshop, user)
100+
workshop.attendee?(user) || workshop.waitlisted?(user)
101+
end
102+
103+
def token
104+
params[:id]
105+
end
106+
end
File renamed without changes.
File renamed without changes.
File renamed without changes.

app/views/invitation/show.html.haml renamed to app/views/workshop_invitation/show.html.haml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,15 @@
8989
= f.input :note, required: false, input_html: { rows: 3, maxlength: 100 }
9090
= f.button :button, 'Attend', class: 'btn btn-primary w-100 mb-0'
9191
- else
92-
= render partial: 'invitation/waiting_list', locals: { invitation: @invitation }
92+
= render partial: 'workshop_invitation/waiting_list', locals: { invitation: @invitation }
9393
- else
9494
- if @workshop.student_spaces?
9595
= simple_form_for @invitation, url: :accept_invitation, method: :post do |f|
9696
= f.input :tutorial, collection: @tutorial_titles, include_blank: true
9797
= f.input :note, required: false, input_html: { rows: 3, maxlength: 100 }, hint: 'Anything else we should know?', placeholder: 'e.g. I need help understanding selectors'
9898
= f.button :button, 'Attend', class: 'btn btn-primary w-100 mb-0'
9999
- else
100-
= render partial: 'invitation/waiting_list', locals: { invitation: @invitation }
100+
= render partial: 'workshop_invitation/waiting_list', locals: { invitation: @invitation }
101101
.card-footer.bg-transparent
102102
Read our #{link_to "attendance policy", attendance_policy_path}.
103103

config/routes.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,19 @@
3232

3333
get 'unsubscribe/:token' => 'members#unsubscribe', as: :unsubscribe
3434

35-
resources :invitation, only: [:show, :update] do
35+
# Old route - kept for backwards compatibility (existing invitation links in emails)
36+
resources :invitation, only: %i[show update], controller: 'workshop_invitation' do
37+
member do
38+
post 'accept'
39+
get 'accept'
40+
get 'reject'
41+
end
42+
43+
resource :waiting_list, only: %i[create destroy]
44+
end
45+
46+
# New route - cleaner URLs
47+
resources :workshop_invitation, only: %i[show update] do
3648
member do
3749
post 'accept'
3850
get 'accept'

0 commit comments

Comments
 (0)