Aggiunge i tornei con hub, pagina pubblica e tabellone per semifinali e finali.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-05 15:05:57 +02:00
co-authored by Cursor
parent d52434fb2e
commit a1f4c24a43
124 changed files with 6979 additions and 91 deletions
@@ -0,0 +1,106 @@
# frozen_string_literal: true
class CreateTournaments < ActiveRecord::Migration[7.2]
def change
add_column :teams, :internal_kind, :string
add_index :teams, [:club_id, :internal_kind]
create_table :tournaments, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.references :club, type: :uuid, null: false, foreign_key: true
t.references :broadcast_team, type: :uuid, foreign_key: { to_table: :teams }
t.string :name, null: false
t.string :slug, null: false
t.string :sport_key, null: false
t.string :venue
t.jsonb :courts, null: false, default: []
t.date :starts_on, null: false
t.date :ends_on, null: false
t.string :format_kind, null: false, default: "mixed"
t.string :status, null: false, default: "draft"
t.text :description
t.integer :knockout_size
t.jsonb :scoring_settings, null: false, default: {}
t.timestamps
end
add_index :tournaments, :slug, unique: true
add_index :tournaments, [:club_id, :status]
create_table :tournament_groups, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.references :tournament, type: :uuid, null: false, foreign_key: true
t.string :name, null: false
t.integer :position, null: false, default: 0
t.timestamps
end
create_table :tournament_rounds, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.references :tournament, type: :uuid, null: false, foreign_key: true
t.string :kind, null: false
t.string :name, null: false
t.integer :position, null: false, default: 0
t.timestamps
end
create_table :tournament_participants, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.references :tournament, type: :uuid, null: false, foreign_key: true
t.references :group, type: :uuid, foreign_key: { to_table: :tournament_groups }
t.references :source_team, type: :uuid, foreign_key: { to_table: :teams }
t.string :name, null: false
t.string :primary_color
t.string :secondary_color
t.string :logo_url
t.integer :seed
t.integer :position, null: false, default: 0
t.timestamps
end
add_index :tournament_participants, [:tournament_id, :name]
create_table :tournament_broadcast_invitations, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.references :tournament, type: :uuid, null: false, foreign_key: true
t.string :email, null: false
t.string :token_digest, null: false
t.string :scope_kind, null: false, default: "matches"
t.jsonb :match_ids, null: false, default: []
t.string :court
t.date :on_date
t.datetime :expires_at, null: false
t.datetime :accepted_at
t.references :accepted_by, type: :uuid, foreign_key: { to_table: :users }
t.timestamps
end
add_index :tournament_broadcast_invitations, :token_digest, unique: true
add_index :tournament_broadcast_invitations, [:tournament_id, :email]
add_reference :matches, :tournament, type: :uuid, foreign_key: true
add_reference :matches, :home_participant, type: :uuid, foreign_key: { to_table: :tournament_participants }
add_reference :matches, :away_participant, type: :uuid, foreign_key: { to_table: :tournament_participants }
add_reference :matches, :tournament_group, type: :uuid, foreign_key: true
add_reference :matches, :tournament_round, type: :uuid, foreign_key: true
add_column :matches, :court, :string
add_column :matches, :home_score, :integer
add_column :matches, :away_score, :integer
add_column :matches, :result_status, :string
add_column :matches, :result_source, :string
add_column :matches, :result_data, :jsonb, null: false, default: {}
add_column :matches, :winner_participant_id, :uuid
add_column :matches, :home_source_kind, :string
add_column :matches, :away_source_kind, :string
add_column :matches, :home_source_match_id, :uuid
add_column :matches, :away_source_match_id, :uuid
add_column :matches, :home_source_group_id, :uuid
add_column :matches, :away_source_group_id, :uuid
add_column :matches, :home_source_rank, :integer
add_column :matches, :away_source_rank, :integer
add_index :matches, [:tournament_id, :scheduled_at]
add_index :matches, [:tournament_id, :court]
create_table :tournament_broadcast_assignments, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.references :tournament, type: :uuid, null: false, foreign_key: true
t.references :match, type: :uuid, null: false, foreign_key: true
t.references :user, type: :uuid, null: false, foreign_key: true
t.references :invitation, type: :uuid, foreign_key: { to_table: :tournament_broadcast_invitations }
t.timestamps
end
add_index :tournament_broadcast_assignments, [:match_id, :user_id], unique: true,
name: "index_tournament_assignments_on_match_and_user"
end
end
@@ -0,0 +1,8 @@
# frozen_string_literal: true
class AddNoteAndEmailHtmlToTournamentInvitations < ActiveRecord::Migration[7.2]
def change
add_column :tournament_broadcast_invitations, :note, :text
add_column :tournament_broadcast_invitations, :email_html, :text
end
end
@@ -0,0 +1,10 @@
# frozen_string_literal: true
class AddInviteDraftToTournaments < ActiveRecord::Migration[7.2]
def change
add_column :tournaments, :invite_draft_html, :text
add_column :tournaments, :invite_draft_note, :text
add_column :tournaments, :invite_draft_email, :string
add_column :tournaments, :invite_draft_saved_at, :datetime
end
end
+147 -1
View File
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.2].define(version: 2026_08_31_193000) do
ActiveRecord::Schema[7.2].define(version: 2026_09_04_143000) do
# These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto"
enable_extension "plpgsql"
@@ -278,7 +278,34 @@ ActiveRecord::Schema[7.2].define(version: 2026_08_31_193000) do
t.jsonb "scoring_rules", default: {}, null: false
t.string "opponent_primary_color"
t.string "overlay_kind"
t.uuid "tournament_id"
t.uuid "home_participant_id"
t.uuid "away_participant_id"
t.uuid "tournament_group_id"
t.uuid "tournament_round_id"
t.string "court"
t.integer "home_score"
t.integer "away_score"
t.string "result_status"
t.string "result_source"
t.jsonb "result_data", default: {}, null: false
t.uuid "winner_participant_id"
t.string "home_source_kind"
t.string "away_source_kind"
t.uuid "home_source_match_id"
t.uuid "away_source_match_id"
t.uuid "home_source_group_id"
t.uuid "away_source_group_id"
t.integer "home_source_rank"
t.integer "away_source_rank"
t.index ["away_participant_id"], name: "index_matches_on_away_participant_id"
t.index ["home_participant_id"], name: "index_matches_on_home_participant_id"
t.index ["team_id"], name: "index_matches_on_team_id"
t.index ["tournament_group_id"], name: "index_matches_on_tournament_group_id"
t.index ["tournament_id", "court"], name: "index_matches_on_tournament_id_and_court"
t.index ["tournament_id", "scheduled_at"], name: "index_matches_on_tournament_id_and_scheduled_at"
t.index ["tournament_id"], name: "index_matches_on_tournament_id"
t.index ["tournament_round_id"], name: "index_matches_on_tournament_round_id"
end
create_table "ops_incidents", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
@@ -558,10 +585,111 @@ ActiveRecord::Schema[7.2].define(version: 2026_08_31_193000) do
t.text "description"
t.string "slug", null: false
t.boolean "roster_public", default: false, null: false
t.string "internal_kind"
t.index ["club_id", "internal_kind"], name: "index_teams_on_club_id_and_internal_kind"
t.index ["club_id"], name: "index_teams_on_club_id"
t.index ["slug"], name: "index_teams_on_slug", unique: true
end
create_table "tournament_broadcast_assignments", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "tournament_id", null: false
t.uuid "match_id", null: false
t.uuid "user_id", null: false
t.uuid "invitation_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["invitation_id"], name: "index_tournament_broadcast_assignments_on_invitation_id"
t.index ["match_id", "user_id"], name: "index_tournament_assignments_on_match_and_user", unique: true
t.index ["match_id"], name: "index_tournament_broadcast_assignments_on_match_id"
t.index ["tournament_id"], name: "index_tournament_broadcast_assignments_on_tournament_id"
t.index ["user_id"], name: "index_tournament_broadcast_assignments_on_user_id"
end
create_table "tournament_broadcast_invitations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "tournament_id", null: false
t.string "email", null: false
t.string "token_digest", null: false
t.string "scope_kind", default: "matches", null: false
t.jsonb "match_ids", default: [], null: false
t.string "court"
t.date "on_date"
t.datetime "expires_at", null: false
t.datetime "accepted_at"
t.uuid "accepted_by_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "note"
t.text "email_html"
t.index ["accepted_by_id"], name: "index_tournament_broadcast_invitations_on_accepted_by_id"
t.index ["token_digest"], name: "index_tournament_broadcast_invitations_on_token_digest", unique: true
t.index ["tournament_id", "email"], name: "idx_on_tournament_id_email_3759dfe34b"
t.index ["tournament_id"], name: "index_tournament_broadcast_invitations_on_tournament_id"
end
create_table "tournament_groups", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "tournament_id", null: false
t.string "name", null: false
t.integer "position", default: 0, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["tournament_id"], name: "index_tournament_groups_on_tournament_id"
end
create_table "tournament_participants", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "tournament_id", null: false
t.uuid "group_id"
t.uuid "source_team_id"
t.string "name", null: false
t.string "primary_color"
t.string "secondary_color"
t.string "logo_url"
t.integer "seed"
t.integer "position", default: 0, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["group_id"], name: "index_tournament_participants_on_group_id"
t.index ["source_team_id"], name: "index_tournament_participants_on_source_team_id"
t.index ["tournament_id", "name"], name: "index_tournament_participants_on_tournament_id_and_name"
t.index ["tournament_id"], name: "index_tournament_participants_on_tournament_id"
end
create_table "tournament_rounds", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "tournament_id", null: false
t.string "kind", null: false
t.string "name", null: false
t.integer "position", default: 0, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["tournament_id"], name: "index_tournament_rounds_on_tournament_id"
end
create_table "tournaments", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "club_id", null: false
t.uuid "broadcast_team_id"
t.string "name", null: false
t.string "slug", null: false
t.string "sport_key", null: false
t.string "venue"
t.jsonb "courts", default: [], null: false
t.date "starts_on", null: false
t.date "ends_on", null: false
t.string "format_kind", default: "mixed", null: false
t.string "status", default: "draft", null: false
t.text "description"
t.integer "knockout_size"
t.jsonb "scoring_settings", default: {}, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "invite_draft_html"
t.text "invite_draft_note"
t.string "invite_draft_email"
t.datetime "invite_draft_saved_at"
t.index ["broadcast_team_id"], name: "index_tournaments_on_broadcast_team_id"
t.index ["club_id", "status"], name: "index_tournaments_on_club_id_and_status"
t.index ["club_id"], name: "index_tournaments_on_club_id"
t.index ["slug"], name: "index_tournaments_on_slug", unique: true
end
create_table "user_teams", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "user_id", null: false
t.uuid "team_id", null: false
@@ -617,6 +745,11 @@ ActiveRecord::Schema[7.2].define(version: 2026_08_31_193000) do
add_foreign_key "club_memberships", "users"
add_foreign_key "device_states", "stream_sessions"
add_foreign_key "matches", "teams"
add_foreign_key "matches", "tournament_groups"
add_foreign_key "matches", "tournament_participants", column: "away_participant_id"
add_foreign_key "matches", "tournament_participants", column: "home_participant_id"
add_foreign_key "matches", "tournament_rounds"
add_foreign_key "matches", "tournaments"
add_foreign_key "recordings", "stream_sessions"
add_foreign_key "recordings", "teams"
add_foreign_key "score_states", "stream_sessions"
@@ -636,6 +769,19 @@ ActiveRecord::Schema[7.2].define(version: 2026_08_31_193000) do
add_foreign_key "team_invitations", "teams"
add_foreign_key "team_roster_members", "teams"
add_foreign_key "teams", "clubs"
add_foreign_key "tournament_broadcast_assignments", "matches"
add_foreign_key "tournament_broadcast_assignments", "tournament_broadcast_invitations", column: "invitation_id"
add_foreign_key "tournament_broadcast_assignments", "tournaments"
add_foreign_key "tournament_broadcast_assignments", "users"
add_foreign_key "tournament_broadcast_invitations", "tournaments"
add_foreign_key "tournament_broadcast_invitations", "users", column: "accepted_by_id"
add_foreign_key "tournament_groups", "tournaments"
add_foreign_key "tournament_participants", "teams", column: "source_team_id"
add_foreign_key "tournament_participants", "tournament_groups", column: "group_id"
add_foreign_key "tournament_participants", "tournaments"
add_foreign_key "tournament_rounds", "tournaments"
add_foreign_key "tournaments", "clubs"
add_foreign_key "tournaments", "teams", column: "broadcast_team_id"
add_foreign_key "user_teams", "teams"
add_foreign_key "user_teams", "users"
add_foreign_key "youtube_credentials", "clubs"