module Public class TournamentMatchesController < WebBaseController before_action :require_login! before_action :set_tournament def create Tournaments::ScheduleMatch.call(tournament: @tournament, attrs: match_params) redirect_to public_tournament_path(@tournament, tab: "calendario"), notice: t("flash.tournaments.match_scheduled") rescue Tournaments::EntitlementError => e redirect_to public_club_billing_path(@club), alert: e.message rescue ActiveRecord::RecordInvalid => e redirect_to public_tournament_path(@tournament, tab: "calendario"), alert: e.record.errors.full_messages.join(", ") end def update Tournaments::Entitlements.new(@club).assert_writable! match = @tournament.matches.find(params[:match_id]) attrs = match_params if match.result_recorded? attrs = attrs.except(:home_participant_id, :away_participant_id) end match.update!(attrs) schedule_changed = match.previous_changes.keys.intersect?(%w[scheduled_at court location]) recorded = record_result_if_present!(match) notice = if recorded && !schedule_changed t("flash.tournaments.result_saved") else t("flash.tournaments.match_updated") end redirect_to public_tournament_path(@tournament, tab: hub_tab), notice: notice rescue Tournaments::EntitlementError => e redirect_to public_club_billing_path(@club), alert: e.message rescue ActiveRecord::RecordInvalid => e redirect_to public_tournament_path(@tournament, tab: "calendario"), alert: e.record.errors.full_messages.join(", ") end def swap match = @tournament.matches.find(params[:match_id]) Tournaments::SwapSides.call(match: match) respond_to do |format| format.json { render json: { ok: true, matchup_label: match.reload.matchup_label } } format.html { redirect_to public_tournament_path(@tournament, tab: "calendario"), notice: t("flash.tournaments.sides_swapped") } end rescue Tournaments::EntitlementError => e respond_to do |format| format.json { render json: { ok: false, error: e.message }, status: :unprocessable_entity } format.html { redirect_to public_club_billing_path(@club), alert: e.message } end rescue Tournaments::SwapSides::LiveBroadcastError => e respond_to do |format| format.json { render json: { ok: false, error: e.message }, status: :unprocessable_entity } format.html { redirect_to public_tournament_path(@tournament, tab: "calendario"), alert: e.message } end end def destroy Tournaments::Entitlements.new(@club).assert_writable! match = @tournament.matches.find(params[:match_id]) unless match.deletable? redirect_to public_tournament_path(@tournament, tab: "calendario"), alert: t("flash.matches.close_live_before_delete") return end match.destroy! redirect_to public_tournament_path(@tournament, tab: "calendario"), notice: t("flash.tournaments.match_deleted") rescue Tournaments::EntitlementError => e redirect_to public_club_billing_path(@club), alert: e.message end private def set_tournament @tournament = Tournament.find(params[:id]) @club = @tournament.club require_club_owner!(@club) end def record_result_if_present!(match) home = params[:home_score] away = params[:away_score] return false if home.blank? || away.blank? Tournaments::RecordResult.call(match: match, home_score: home, away_score: away, source: "manual") true end def match_params p = params.require(:match).permit( :home_participant_id, :away_participant_id, :tournament_group_id, :tournament_round_id, :court, :location, :scheduled_at ) %i[home_participant_id away_participant_id].each do |key| p[key] = p[key].presence if p.key?(key) end p[:scheduled_at] = parse_scheduled_at(p[:scheduled_at]) if p[:scheduled_at].present? p end def parse_scheduled_at(value) raw = value.to_s.strip return nil if raw.blank? Time.zone.strptime(raw, "%Y-%m-%dT%H:%M") rescue ArgumentError Time.zone.parse(raw) end def hub_tab params[:tab].to_s.presence_in(%w[squadre struttura calendario dirette tabellone]) || "calendario" end end end