Skip to content

Commit 4d0d957

Browse files
committed
feat: implement Schedules and VOD Reviews management
- Add Schedules controller with event management - Implement filtering by event type, status, and date - Add VodReviewsController for VOD management - Add VodTimestampsController for timestamp annotations - Include filtering and nested resource handling
1 parent 2f622fa commit 4d0d957

3 files changed

Lines changed: 370 additions & 0 deletions

File tree

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
class Api::V1::SchedulesController < Api::V1::BaseController
2+
before_action :set_schedule, only: [:show, :update, :destroy]
3+
4+
def index
5+
schedules = organization_scoped(Schedule).includes(:match)
6+
7+
# Apply filters
8+
schedules = schedules.where(event_type: params[:event_type]) if params[:event_type].present?
9+
schedules = schedules.where(status: params[:status]) if params[:status].present?
10+
11+
# Date range filter
12+
if params[:start_date].present? && params[:end_date].present?
13+
schedules = schedules.where(start_time: params[:start_date]..params[:end_date])
14+
elsif params[:upcoming] == 'true'
15+
schedules = schedules.where('start_time >= ?', Time.current)
16+
elsif params[:past] == 'true'
17+
schedules = schedules.where('end_time < ?', Time.current)
18+
end
19+
20+
# Today's events
21+
if params[:today] == 'true'
22+
schedules = schedules.where(start_time: Time.current.beginning_of_day..Time.current.end_of_day)
23+
end
24+
25+
# This week's events
26+
if params[:this_week] == 'true'
27+
schedules = schedules.where(start_time: Time.current.beginning_of_week..Time.current.end_of_week)
28+
end
29+
30+
# Sorting
31+
sort_order = params[:sort_order] || 'asc'
32+
schedules = schedules.order("start_time #{sort_order}")
33+
34+
# Pagination
35+
result = paginate(schedules)
36+
37+
render_success({
38+
schedules: ScheduleSerializer.render_as_hash(result[:data]),
39+
pagination: result[:pagination]
40+
})
41+
end
42+
43+
def show
44+
render_success({
45+
schedule: ScheduleSerializer.render_as_hash(@schedule)
46+
})
47+
end
48+
49+
def create
50+
schedule = organization_scoped(Schedule).new(schedule_params)
51+
schedule.organization = current_organization
52+
53+
if schedule.save
54+
log_user_action(
55+
action: 'create',
56+
entity_type: 'Schedule',
57+
entity_id: schedule.id,
58+
new_values: schedule.attributes
59+
)
60+
61+
render_created({
62+
schedule: ScheduleSerializer.render_as_hash(schedule)
63+
}, message: 'Event scheduled successfully')
64+
else
65+
render_error(
66+
message: 'Failed to create schedule',
67+
code: 'VALIDATION_ERROR',
68+
status: :unprocessable_entity,
69+
details: schedule.errors.as_json
70+
)
71+
end
72+
end
73+
74+
def update
75+
old_values = @schedule.attributes.dup
76+
77+
if @schedule.update(schedule_params)
78+
log_user_action(
79+
action: 'update',
80+
entity_type: 'Schedule',
81+
entity_id: @schedule.id,
82+
old_values: old_values,
83+
new_values: @schedule.attributes
84+
)
85+
86+
render_updated({
87+
schedule: ScheduleSerializer.render_as_hash(@schedule)
88+
})
89+
else
90+
render_error(
91+
message: 'Failed to update schedule',
92+
code: 'VALIDATION_ERROR',
93+
status: :unprocessable_entity,
94+
details: @schedule.errors.as_json
95+
)
96+
end
97+
end
98+
99+
def destroy
100+
if @schedule.destroy
101+
log_user_action(
102+
action: 'delete',
103+
entity_type: 'Schedule',
104+
entity_id: @schedule.id,
105+
old_values: @schedule.attributes
106+
)
107+
108+
render_deleted(message: 'Event deleted successfully')
109+
else
110+
render_error(
111+
message: 'Failed to delete schedule',
112+
code: 'DELETE_ERROR',
113+
status: :unprocessable_entity
114+
)
115+
end
116+
end
117+
118+
private
119+
120+
def set_schedule
121+
@schedule = organization_scoped(Schedule).find(params[:id])
122+
end
123+
124+
def schedule_params
125+
params.require(:schedule).permit(
126+
:event_type, :title, :description,
127+
:start_time, :end_time, :location, :is_online,
128+
:opponent_name, :tournament_name, :stage,
129+
:status, :notes, :match_id
130+
)
131+
end
132+
end
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
class Api::V1::VodReviewsController < Api::V1::BaseController
2+
before_action :set_vod_review, only: [:show, :update, :destroy]
3+
4+
def index
5+
vod_reviews = organization_scoped(VodReview).includes(:match, :reviewed_by)
6+
7+
# Apply filters
8+
vod_reviews = vod_reviews.where(status: params[:status]) if params[:status].present?
9+
vod_reviews = vod_reviews.where(vod_platform: params[:platform]) if params[:platform].present?
10+
11+
# Match filter
12+
vod_reviews = vod_reviews.where(match_id: params[:match_id]) if params[:match_id].present?
13+
14+
# Reviewed by filter
15+
vod_reviews = vod_reviews.where(reviewed_by_id: params[:reviewed_by_id]) if params[:reviewed_by_id].present?
16+
17+
# Search by title
18+
if params[:search].present?
19+
search_term = "%#{params[:search]}%"
20+
vod_reviews = vod_reviews.where('title ILIKE ?', search_term)
21+
end
22+
23+
# Sorting
24+
sort_by = params[:sort_by] || 'created_at'
25+
sort_order = params[:sort_order] || 'desc'
26+
vod_reviews = vod_reviews.order("#{sort_by} #{sort_order}")
27+
28+
# Pagination
29+
result = paginate(vod_reviews)
30+
31+
render_success({
32+
vod_reviews: VodReviewSerializer.render_as_hash(result[:data], include_timestamps_count: true),
33+
pagination: result[:pagination]
34+
})
35+
end
36+
37+
def show
38+
vod_review_data = VodReviewSerializer.render_as_hash(@vod_review)
39+
timestamps = VodTimestampSerializer.render_as_hash(
40+
@vod_review.vod_timestamps.includes(:target_player, :created_by).order(:timestamp_seconds)
41+
)
42+
43+
render_success({
44+
vod_review: vod_review_data,
45+
timestamps: timestamps
46+
})
47+
end
48+
49+
def create
50+
vod_review = organization_scoped(VodReview).new(vod_review_params)
51+
vod_review.organization = current_organization
52+
vod_review.reviewed_by = current_user
53+
54+
if vod_review.save
55+
log_user_action(
56+
action: 'create',
57+
entity_type: 'VodReview',
58+
entity_id: vod_review.id,
59+
new_values: vod_review.attributes
60+
)
61+
62+
render_created({
63+
vod_review: VodReviewSerializer.render_as_hash(vod_review)
64+
}, message: 'VOD review created successfully')
65+
else
66+
render_error(
67+
message: 'Failed to create VOD review',
68+
code: 'VALIDATION_ERROR',
69+
status: :unprocessable_entity,
70+
details: vod_review.errors.as_json
71+
)
72+
end
73+
end
74+
75+
def update
76+
old_values = @vod_review.attributes.dup
77+
78+
if @vod_review.update(vod_review_params)
79+
log_user_action(
80+
action: 'update',
81+
entity_type: 'VodReview',
82+
entity_id: @vod_review.id,
83+
old_values: old_values,
84+
new_values: @vod_review.attributes
85+
)
86+
87+
render_updated({
88+
vod_review: VodReviewSerializer.render_as_hash(@vod_review)
89+
})
90+
else
91+
render_error(
92+
message: 'Failed to update VOD review',
93+
code: 'VALIDATION_ERROR',
94+
status: :unprocessable_entity,
95+
details: @vod_review.errors.as_json
96+
)
97+
end
98+
end
99+
100+
def destroy
101+
if @vod_review.destroy
102+
log_user_action(
103+
action: 'delete',
104+
entity_type: 'VodReview',
105+
entity_id: @vod_review.id,
106+
old_values: @vod_review.attributes
107+
)
108+
109+
render_deleted(message: 'VOD review deleted successfully')
110+
else
111+
render_error(
112+
message: 'Failed to delete VOD review',
113+
code: 'DELETE_ERROR',
114+
status: :unprocessable_entity
115+
)
116+
end
117+
end
118+
119+
private
120+
121+
def set_vod_review
122+
@vod_review = organization_scoped(VodReview).find(params[:id])
123+
end
124+
125+
def vod_review_params
126+
params.require(:vod_review).permit(
127+
:title, :vod_url, :vod_platform, :game_start_timestamp,
128+
:status, :notes, :match_id
129+
)
130+
end
131+
end
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
class Api::V1::VodTimestampsController < Api::V1::BaseController
2+
before_action :set_vod_review, only: [:index, :create]
3+
before_action :set_vod_timestamp, only: [:update, :destroy]
4+
5+
def index
6+
timestamps = @vod_review.vod_timestamps
7+
.includes(:target_player, :created_by)
8+
.order(:timestamp_seconds)
9+
10+
# Apply filters
11+
timestamps = timestamps.where(category: params[:category]) if params[:category].present?
12+
timestamps = timestamps.where(importance: params[:importance]) if params[:importance].present?
13+
timestamps = timestamps.where(target_player_id: params[:player_id]) if params[:player_id].present?
14+
15+
render_success({
16+
timestamps: VodTimestampSerializer.render_as_hash(timestamps)
17+
})
18+
end
19+
20+
def create
21+
timestamp = @vod_review.vod_timestamps.new(vod_timestamp_params)
22+
timestamp.created_by = current_user
23+
24+
if timestamp.save
25+
log_user_action(
26+
action: 'create',
27+
entity_type: 'VodTimestamp',
28+
entity_id: timestamp.id,
29+
new_values: timestamp.attributes
30+
)
31+
32+
render_created({
33+
timestamp: VodTimestampSerializer.render_as_hash(timestamp)
34+
}, message: 'Timestamp added successfully')
35+
else
36+
render_error(
37+
message: 'Failed to create timestamp',
38+
code: 'VALIDATION_ERROR',
39+
status: :unprocessable_entity,
40+
details: timestamp.errors.as_json
41+
)
42+
end
43+
end
44+
45+
def update
46+
old_values = @timestamp.attributes.dup
47+
48+
if @timestamp.update(vod_timestamp_params)
49+
log_user_action(
50+
action: 'update',
51+
entity_type: 'VodTimestamp',
52+
entity_id: @timestamp.id,
53+
old_values: old_values,
54+
new_values: @timestamp.attributes
55+
)
56+
57+
render_updated({
58+
timestamp: VodTimestampSerializer.render_as_hash(@timestamp)
59+
})
60+
else
61+
render_error(
62+
message: 'Failed to update timestamp',
63+
code: 'VALIDATION_ERROR',
64+
status: :unprocessable_entity,
65+
details: @timestamp.errors.as_json
66+
)
67+
end
68+
end
69+
70+
def destroy
71+
if @timestamp.destroy
72+
log_user_action(
73+
action: 'delete',
74+
entity_type: 'VodTimestamp',
75+
entity_id: @timestamp.id,
76+
old_values: @timestamp.attributes
77+
)
78+
79+
render_deleted(message: 'Timestamp deleted successfully')
80+
else
81+
render_error(
82+
message: 'Failed to delete timestamp',
83+
code: 'DELETE_ERROR',
84+
status: :unprocessable_entity
85+
)
86+
end
87+
end
88+
89+
private
90+
91+
def set_vod_review
92+
@vod_review = organization_scoped(VodReview).find(params[:vod_review_id])
93+
end
94+
95+
def set_vod_timestamp
96+
@timestamp = VodTimestamp.joins(:vod_review)
97+
.where(vod_reviews: { organization: current_organization })
98+
.find(params[:id])
99+
end
100+
101+
def vod_timestamp_params
102+
params.require(:vod_timestamp).permit(
103+
:timestamp_seconds, :category, :importance,
104+
:title, :description, :target_player_id
105+
)
106+
end
107+
end

0 commit comments

Comments
 (0)