diff --git a/lib/cesium_cup/tournament/match.ex b/lib/cesium_cup/tournament/match.ex
index 8801a82..5da6397 100644
--- a/lib/cesium_cup/tournament/match.ex
+++ b/lib/cesium_cup/tournament/match.ex
@@ -11,7 +11,7 @@ defmodule CesiumCup.Tournament.Match do
@required_fields ~w(date)a
- @optional_fields ~w(home_team_id away_team_id group_id elimination_round_id state group_round)a
+ @optional_fields ~w(home_team_id away_team_id group_id elimination_round_index elimination_round_id state group_round)a
@states ~w(upcoming first_half halftime second_half finished)a
@@ -27,6 +27,7 @@ defmodule CesiumCup.Tournament.Match do
field :group_round, :integer
+ field :elimination_round_index, :integer
belongs_to :elimination_round, EliminationRound
has_many :events, Event
diff --git a/lib/cesium_cup_web/components/bracket.ex b/lib/cesium_cup_web/components/bracket.ex
new file mode 100644
index 0000000..ad5ddc6
--- /dev/null
+++ b/lib/cesium_cup_web/components/bracket.ex
@@ -0,0 +1,69 @@
+defmodule CesiumCupWeb.Components.Bracket do
+ @moduledoc """
+ The knockout stage bracket component
+ """
+ use Phoenix.LiveComponent
+
+ alias CesiumCup.Tournament
+ alias CesiumCupWeb.Router.Helpers, as: Routes
+
+ def render(assigns) do
+ ~H"""
+
+ <%= if @current_round > 0 do %>
+
+
+ <.live_component module={CesiumCupWeb.Components.Bracket} id={"bracket-#{2 * @index + 1}"} index={2 * @index + 1} current_round={@current_round - 1} number_rounds={@number_rounds} matches={@matches} />
+ <.live_component module={CesiumCupWeb.Components.Bracket} id={"bracket-#{2 * @index + 2}"} index={2 * @index + 2} current_round={@current_round - 1} number_rounds={@number_rounds} matches={@matches} />
+
+ <% match = Enum.find(@matches, &(&1.elimination_round_index == @index)) %>
+ <%= live_redirect to: Routes.match_show_path(@socket, :show, match) do %>
+
+
+
+
+ <%= if match.home_team do %>
+ <%= match.home_team.name %>
+ <% else %>
+ TBD
+ <% end %>
+
+
+
+ <%= if not is_nil(match.home_team_id) and match.state != :upcoming do %>
+ <%= get_home_team_score(match.id) %>
+ <% end %>
+
+
+
+
+ <%= if match.away_team do %>
+ <%= match.away_team.name %>
+ <% else %>
+ TBD
+ <% end %>
+
+
+
+ <%= if not is_nil(match.home_team_id) and match.state != :upcoming do %>
+ <%= get_away_team_score(match.id) %>
+ <% end %>
+
+
+
+
+ <% end %>
+
+ <% end %>
+
+ """
+ end
+
+ defp get_home_team_score(match_id) do
+ Tournament.get_home_team_score(match_id)
+ end
+
+ defp get_away_team_score(match_id) do
+ Tournament.get_away_team_score(match_id)
+ end
+end
diff --git a/lib/cesium_cup_web/live/home_live/index.ex b/lib/cesium_cup_web/live/home_live/index.ex
index a6aee01..bfed38f 100644
--- a/lib/cesium_cup_web/live/home_live/index.ex
+++ b/lib/cesium_cup_web/live/home_live/index.ex
@@ -41,6 +41,11 @@ defmodule CesiumCupWeb.HomeLive.Index do
|> Enum.sort(&(Date.compare(&1.date, &2.date) in [:lt, :eq]))
end
+ defp list_knockout_stage_matches do
+ Tournament.list_matches(preloads: [:home_team, :away_team])
+ |> Enum.filter(&is_nil(&1.group_round))
+ end
+
defp list_groups do
Tournament.list_groups(preloads: [:teams])
end
diff --git a/lib/cesium_cup_web/live/home_live/index.html.heex b/lib/cesium_cup_web/live/home_live/index.html.heex
index 5f5c1a4..a6c45e2 100644
--- a/lib/cesium_cup_web/live/home_live/index.html.heex
+++ b/lib/cesium_cup_web/live/home_live/index.html.heex
@@ -68,12 +68,17 @@
else
"border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300"
end} whitespace-nowrap py-4 px-1 border-b-4 font-medium text-md") %>
+ <%= live_patch("Knockout Stage", to: "?tab=knockout_stage", class: "#{if @tab == "knockout_stage" do
+ "border-quinary text-gray-900"
+ else
+ "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300"
+ end} whitespace-nowrap py-4 px-1 border-b-4 font-medium text-md") %>
<%= for round <- @elimination_rounds do %>
<%= live_patch(round.name, to: "?tab=#{round.name}", class: "#{if @tab == round.name do
"border-quinary text-gray-900"
else
"border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300"
- end} whitespace-nowrap py-4 px-1 border-b-4 font-medium text-md") %>
+ end} show lg:hidden whitespace-nowrap py-4 px-1 border-b-4 font-medium text-md") %>
<% end %>
@@ -197,52 +202,58 @@
<% else %>
-
-
-
-
-
-
- <%= for match <- Enum.sort(@selected_elimination_round.matches, &(Date.compare(&1.date, &2.date) in [:lt, :eq])) do %>
-
-
- <%= display_date(match.date) %>
- |
-
- <%= if match.home_team_id do %>
- <%= live_redirect to: Routes.team_show_path(@socket, :show, get_team(match.home_team_id)) do %>
- <%= get_team(match.home_team_id).name %>
- <% end %>
- <% else %>
- TBD
- <% end %>
- |
-
- <%= live_redirect to: Routes.match_show_path(@socket, :show, match) do %>
- <%= if match.state != :upcoming do %>
- <%= get_home_team_score(match.id) %> - <%= get_away_team_score(match.id) %>
+ <%= if @tab != "knockout_stage" do %>
+
+
+
+
+
+
+ <%= for match <- Enum.sort(@selected_elimination_round.matches, &(Date.compare(&1.date, &2.date) in [:lt, :eq])) do %>
+
+
+ <%= display_date(match.date) %>
+ |
+
+ <%= if match.home_team_id do %>
+ <%= live_redirect to: Routes.team_show_path(@socket, :show, get_team(match.home_team_id)) do %>
+ <%= get_team(match.home_team_id).name %>
+ <% end %>
<% else %>
- <%= display_time(match.date) %>
+ TBD
<% end %>
- <% end %>
- |
-
- <%= if match.away_team_id do %>
- <%= live_redirect to: Routes.team_show_path(@socket, :show, get_team(match.away_team_id)) do %>
- <%= get_team(match.away_team_id).name %>
+ |
+
+ <%= live_redirect to: Routes.match_show_path(@socket, :show, match) do %>
+ <%= if match.state != :upcoming do %>
+ <%= get_home_team_score(match.id) %> - <%= get_away_team_score(match.id) %>
+ <% else %>
+ <%= display_time(match.date) %>
+ <% end %>
<% end %>
- <% else %>
- TBD
- <% end %>
- |
-
- <% end %>
-
-
+ |
+
+ <%= if match.away_team_id do %>
+ <%= live_redirect to: Routes.team_show_path(@socket, :show, get_team(match.away_team_id)) do %>
+ <%= get_team(match.away_team_id).name %>
+ <% end %>
+ <% else %>
+ TBD
+ <% end %>
+ |
+
+ <% end %>
+
+
+
-
+ <% else %>
+
+ <.live_component module={CesiumCupWeb.Components.Bracket} id="bracket" index={0} current_round={length(@elimination_rounds)} number_rounds={length(@elimination_rounds)} matches={list_knockout_stage_matches()} />
+
+ <% end %>
<% end %>
diff --git a/lib/cesium_cup_web/live/match_live/form_component.html.heex b/lib/cesium_cup_web/live/match_live/form_component.html.heex
index d807511..da9c58b 100644
--- a/lib/cesium_cup_web/live/match_live/form_component.html.heex
+++ b/lib/cesium_cup_web/live/match_live/form_component.html.heex
@@ -27,6 +27,12 @@
<%= error_tag(f, :group_id) %>
+
+ <%= label(f, :elimination_round_index) %>
+ <%= number_input(f, :elimination_round_index) %>
+ <%= error_tag(f, :elimination_round_index) %>
+
+
<%= label(f, :elimination_round_id) %>
<%= select(f, :elimination_round_id, Enum.map(@elimination_rounds, &{&1.name, &1.id}), prompt: "Choose a Elimination Round", selected: f.data.group_id) %>
diff --git a/priv/repo/migrations/20221210233254_create_matches.exs b/priv/repo/migrations/20221210233254_create_matches.exs
index c4a58ac..03e2c7b 100644
--- a/priv/repo/migrations/20221210233254_create_matches.exs
+++ b/priv/repo/migrations/20221210233254_create_matches.exs
@@ -12,6 +12,8 @@ defmodule CesiumCup.Repo.Migrations.CreateMatches do
add :home_team_id, references(:teams, on_delete: :nothing, type: :binary_id)
add :away_team_id, references(:teams, on_delete: :nothing, type: :binary_id)
+ add :elimination_round_index, :integer
+
add :elimination_round_id,
references(:elimination_rounds, on_delete: :nothing, type: :binary_id)
diff --git a/priv/repo/seeds/schedule.exs b/priv/repo/seeds/schedule.exs
index c9cb4cf..ce55c6e 100644
--- a/priv/repo/seeds/schedule.exs
+++ b/priv/repo/seeds/schedule.exs
@@ -221,36 +221,43 @@ defmodule CesiumCup.Repo.Seeds.Schedule do
%{
date: ~N[2023-12-02 15:00:00],
state: :upcoming,
+ elimination_round_index: 3,
elimination_round_id: get_elimination_round_id("Quarter-Finals")
},
%{
date: ~N[2023-12-03 15:00:00],
state: :upcoming,
+ elimination_round_index: 4,
elimination_round_id: get_elimination_round_id("Quarter-Finals")
},
%{
date: ~N[2023-12-04 15:00:00],
state: :upcoming,
+ elimination_round_index: 5,
elimination_round_id: get_elimination_round_id("Quarter-Finals")
},
%{
date: ~N[2023-12-05 15:00:00],
state: :upcoming,
+ elimination_round_index: 6,
elimination_round_id: get_elimination_round_id("Quarter-Finals")
},
%{
date: ~N[2023-12-06 16:00:00],
state: :upcoming,
+ elimination_round_index: 1,
elimination_round_id: get_elimination_round_id("Semi-Finals")
},
%{
date: ~N[2023-12-07 16:00:00],
state: :upcoming,
+ elimination_round_index: 2,
elimination_round_id: get_elimination_round_id("Semi-Finals")
},
%{
date: ~N[2023-12-10 20:00:00],
state: :upcoming,
+ elimination_round_index: 0,
elimination_round_id: get_elimination_round_id("Final")
}
]