Files
MatchLiveTv/backend/app/controllers/api/v1/matches_controller.rb
Emiliano Frascaro 01b7a3c96b Fix hub diretta: considera solo l'ultima sessione, non idle orfane.
Dopo «Termina trasmissione» la partita restava visibile se esisteva una vecchia sessione idle precedente a quella ended; l'hub e l'app usano ora lo stato dell'ultima sessione.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 21:58:01 +02:00

138 lines
4.4 KiB
Ruby

module Api
module V1
class MatchesController < BaseController
include Api::UrlHelper
include BrandingAttachments
before_action :set_team, only: %i[index create]
before_action :set_match, only: %i[show update destroy]
def index
matches = @team.matches
.includes(:team, :stream_sessions)
.order(Arel.sql("scheduled_at ASC NULLS LAST"), created_at: :desc)
.select(&:coach_hub_visible?)
render json: matches.map { |m| match_json(m) }
end
def create
attrs = match_params.to_h
attrs["sport_key"] = @team.sport_key if attrs["sport_key"].blank?
normalize_scoring_rules!(attrs)
match = @team.matches.create!(attrs)
attach_opponent_logo(match)
render json: match_json(match), status: :created
end
def show
render json: match_json(@match, detail: true)
end
def update
attrs = match_params.to_h
normalize_scoring_rules!(attrs)
normalize_opponent_color!(attrs)
@match.update!(attrs)
attach_opponent_logo(@match)
render json: match_json(@match)
end
def destroy
active = active_session_for(@match)
if active&.resumable?
return render json: {
error: "Chiudi la diretta prima di eliminare questa partita"
}, status: :unprocessable_entity
end
@match.destroy!
head :no_content
end
private
def set_team
@team = current_user.streamable_teams.find { |t| t.id == params[:team_id] }
raise ActiveRecord::RecordNotFound unless @team
end
def set_match
team_ids = current_user.streamable_teams.map(&:id)
@match = Match.includes(:team).where(team_id: team_ids).find(params[:id])
end
def match_params
p = params.require(:match).permit(
:opponent_name, :location, :scheduled_at, :sport, :sport_key, :sets_to_win,
:category, :opponent_primary_color, :overlay_kind,
scoring_rules: {}
)
if p[:sport].present? && p[:sport_key].blank?
p[:sport_key] = p.delete(:sport)
end
p
end
def normalize_scoring_rules!(attrs)
return unless attrs.key?("scoring_rules")
rules = attrs["scoring_rules"]
attrs["scoring_rules"] = {} if rules.blank?
if attrs["sets_to_win"].present? && attrs["scoring_rules"].is_a?(Hash)
attrs["scoring_rules"]["sets_to_win"] ||= attrs["sets_to_win"]
end
end
def normalize_opponent_color!(attrs)
return unless attrs.key?("opponent_primary_color")
attrs["opponent_primary_color"] = normalize_hex_color(
attrs["opponent_primary_color"],
Match::DEFAULT_OPPONENT_COLOR
)
end
def attach_opponent_logo(match)
file = params[:opponent_logo_file]
match.opponent_logo_file.attach(file) if file.present?
end
def match_json(match, detail: false)
active = active_session_for(match)
team = match.team
{
id: match.id,
team_id: match.team_id,
team_name: team.name,
opponent_name: match.opponent_name,
location: match.location,
scheduled_at: match.scheduled_at,
sport: match.sport_key,
sport_key: match.sport_key,
sport_label: match.sport_label,
board_type: match.effective_board_type,
overlay_kind: match.overlay_kind,
effective_overlay_kind: match.effective_overlay_kind,
sets_to_win: match.sets_to_win,
scoring_rules: match.scoring_rules.presence,
effective_scoring_rules: match.effective_scoring_rules,
category: match.category,
home_primary_color: team.effective_primary_color,
home_secondary_color: team.effective_secondary_color,
home_logo_url: api_absolute_url(team.effective_logo_url),
opponent_primary_color: match.effective_opponent_primary_color,
opponent_logo_url: api_absolute_url(match.opponent_logo_url),
active_session_id: active&.id,
active_session_status: active&.status,
stream_completed: match.stream_completed?,
coach_hub_visible: match.coach_hub_visible?
}
end
def active_session_for(match)
match.active_stream_session
end
end
end
end