From 44d319fac5d064a6aaf43a989b0e6bcd7ad1716e Mon Sep 17 00:00:00 2001 From: gxnca Date: Fri, 26 Dec 2025 17:25:48 +0000 Subject: [PATCH 1/6] feat: confirmation modal --- lib/ares_web/components/core_components.ex | 95 ++++++++++++++++++++++ lib/ares_web/live/app/team-formation.ex | 68 +++++++++++++++- lib/ares_web/router.ex | 1 + 3 files changed, 162 insertions(+), 2 deletions(-) diff --git a/lib/ares_web/components/core_components.ex b/lib/ares_web/components/core_components.ex index 25f730e0..a27ff3e6 100644 --- a/lib/ares_web/components/core_components.ex +++ b/lib/ares_web/components/core_components.ex @@ -32,6 +32,77 @@ defmodule AresWeb.CoreComponents do alias Phoenix.HTML.Form alias Phoenix.LiveView.JS + @doc """ + Renders a modal. + + ## Examples + + <.modal id="confirm-modal"> + This is a modal. + + + JS commands may be passed to the `:on_cancel` to configure + the closing/cancel event, for example: + + <.modal id="confirm" on_cancel={JS.navigate(~p"/posts")}> + This is another modal. + + + """ + attr :id, :string, required: true + attr :show, :boolean, default: false + attr :wrapper_class, :string, default: "" + attr :on_cancel, JS, default: %JS{} + slot :inner_block, required: true + + def modal(assigns) do + ~H""" + + + <.modal + :if={@live_action == :join} + id="join-team-modal" + show + on_cancel={JS.patch(~p"/app/team-formation?#{[tab: @tab]}")} + > +
+
+ +
+
+

Join Team?

+

+ You are about to join {@selected_team.name}. Confirm that this is the team you want to participate with. +

+
+
+ + +
+
+ """ end @@ -308,6 +343,25 @@ defmodule AresWeb.AppLive.TeamFormation do |> assign_form(Teams.change_team(%Teams.Team{}, %{}))} end + @impl true + def handle_params(params, _url, socket) do + {:noreply, apply_action(socket, socket.assigns.live_action, params)} + end + + defp apply_action(socket, :index, params) do + tab = Map.get(params, "tab", "create") + + socket + |> assign(:tab, tab) + end + + defp apply_action(socket, :join, params) do + tab = Map.get(params, "tab", "join") + + socket + |> assign(:tab, tab) + end + @impl true def handle_event("save", %{"team" => team_params}, socket) do case Teams.create_and_join_team(socket.assigns.user, team_params) do @@ -347,6 +401,16 @@ defmodule AresWeb.AppLive.TeamFormation do end end + @impl true + def handle_event("open-join-modal", %{"team_code" => team_code}, socket) do + selected_team = Enum.find(socket.assigns.available_teams, &(&1.code == team_code)) + + {:noreply, + socket + |> assign(:selected_team, selected_team) + |> push_patch(to: ~p"/app/team-formation/join?#{[tab: socket.assigns.tab]}")} + end + @impl true def handle_event("join-team", %{"team_code" => team_code}, socket) do case Teams.add_user_to_team_by_code(socket.assigns.user, team_code) do diff --git a/lib/ares_web/router.ex b/lib/ares_web/router.ex index e8975ce1..40214611 100644 --- a/lib/ares_web/router.ex +++ b/lib/ares_web/router.ex @@ -55,6 +55,7 @@ defmodule AresWeb.Router do on_mount: [{AresWeb.UserAuth, :require_authenticated}] do live "/app/profile", AppLive.Profile, :index live "/app/team-formation", AppLive.TeamFormation, :index + live "/app/team-formation/join", AppLive.TeamFormation, :join live "/users/settings", UserLive.Settings, :edit live "/users/settings/confirm-email/:token", UserLive.Settings, :confirm_email end From 603fce30c06abc3e99e1afe11535b46e6894a484 Mon Sep 17 00:00:00 2001 From: gxnca Date: Sat, 27 Dec 2025 02:26:28 +0000 Subject: [PATCH 2/6] refactor: small changes --- lib/ares_web/components/navbar.ex | 14 ++++++++++++++ lib/ares_web/live/auth/settings.ex | 13 ++++++++++--- lib/ares_web/live/landing/faqs.html.heex | 8 ++++---- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/lib/ares_web/components/navbar.ex b/lib/ares_web/components/navbar.ex index bce758b1..9d568480 100644 --- a/lib/ares_web/components/navbar.ex +++ b/lib/ares_web/components/navbar.ex @@ -94,6 +94,12 @@ defmodule AresWeb.Components.Navbar do > View Profile + <.link + navigate="/users/settings" + class="block px-4 py-2 text-black hover:bg-gray-300 rounded-t-lg transition-colors" + > + Settings + <.link href="/users/log-out" method="delete" class="border-t border-gray-700">

Log out @@ -186,6 +192,14 @@ defmodule AresWeb.Components.Navbar do <% end %> <%= if @user do %> +

  • + <.link + navigate="/users/settings" + class="block w-full py-3 sm:py-4 text-center text-lg sm:text-xl hover:text-primary transition-colors" + > + Settings + +
  • <.link href="/users/log-out" diff --git a/lib/ares_web/live/auth/settings.ex b/lib/ares_web/live/auth/settings.ex index bf98f600..2f8accc0 100644 --- a/lib/ares_web/live/auth/settings.ex +++ b/lib/ares_web/live/auth/settings.ex @@ -11,12 +11,18 @@ defmodule AresWeb.UserLive.Settings do
    <.header> - Account Settings - <:subtitle>Manage your account email address and password settings +

    Account Settings

    +

    Manage your account email address and password settings

    - <.form for={@email_form} id="email_form" phx-submit="update_email" phx-change="validate_email"> + <.form + for={@email_form} + id="email_form" + phx-submit="update_email" + phx-change="validate_email" + class="font-inter" + > <.input field={@email_form[:email]} type="email" @@ -37,6 +43,7 @@ defmodule AresWeb.UserLive.Settings do phx-change="validate_password" phx-submit="update_password" phx-trigger-action={@trigger_submit} + class="font-inter" > + --%> -
    +<%!--

    Sponsors @@ -206,7 +206,7 @@

    - + --%>
    From f6a5e56f167d7ec37c94c1098a39d4f4341d02ab Mon Sep 17 00:00:00 2001 From: gxnca Date: Sat, 27 Dec 2025 04:16:48 +0000 Subject: [PATCH 4/6] refactor: small changes --- lib/ares_web/live/auth/settings.ex | 120 +++++++++++++++-------------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/lib/ares_web/live/auth/settings.ex b/lib/ares_web/live/auth/settings.ex index 2f8accc0..4ff216c4 100644 --- a/lib/ares_web/live/auth/settings.ex +++ b/lib/ares_web/live/auth/settings.ex @@ -9,66 +9,68 @@ defmodule AresWeb.UserLive.Settings do def render(assigns) do ~H""" -
    - <.header> -

    Account Settings

    -

    Manage your account email address and password settings

    - +
    +
    + <.header> +

    Account Settings

    +

    Manage your account email address and password settings

    + +
    + + <.form + for={@email_form} + id="email_form" + phx-submit="update_email" + phx-change="validate_email" + class="font-inter" + > + <.input + field={@email_form[:email]} + type="email" + label="Email" + autocomplete="username" + required + /> + <.button variant="primary" phx-disable-with="Changing...">Change Email + + +
    + + <.form + for={@password_form} + id="password_form" + action={~p"/users/update-password"} + method="post" + phx-change="validate_password" + phx-submit="update_password" + phx-trigger-action={@trigger_submit} + class="font-inter" + > + + <.input + field={@password_form[:password]} + type="password" + label="New password" + autocomplete="new-password" + required + /> + <.input + field={@password_form[:password_confirmation]} + type="password" + label="Confirm new password" + autocomplete="new-password" + /> + <.button variant="primary" phx-disable-with="Saving..."> + Save Password + +
    - - <.form - for={@email_form} - id="email_form" - phx-submit="update_email" - phx-change="validate_email" - class="font-inter" - > - <.input - field={@email_form[:email]} - type="email" - label="Email" - autocomplete="username" - required - /> - <.button variant="primary" phx-disable-with="Changing...">Change Email - - -
    - - <.form - for={@password_form} - id="password_form" - action={~p"/users/update-password"} - method="post" - phx-change="validate_password" - phx-submit="update_password" - phx-trigger-action={@trigger_submit} - class="font-inter" - > - - <.input - field={@password_form[:password]} - type="password" - label="New password" - autocomplete="new-password" - required - /> - <.input - field={@password_form[:password_confirmation]} - type="password" - label="Confirm new password" - autocomplete="new-password" - /> - <.button variant="primary" phx-disable-with="Saving..."> - Save Password - - """ end From bac87b7e0d53a938d4d69cab100572d88f25f7da Mon Sep 17 00:00:00 2001 From: Nuno Miguel Date: Sat, 27 Dec 2025 04:31:49 +0000 Subject: [PATCH 5/6] feat: disable unavailable pages and sections --- lib/ares_web/components/layouts/root.html.heex | 2 +- lib/ares_web/components/navbar.ex | 16 ++++++++-------- lib/ares_web/live/landing/home.html.heex | 4 ++-- lib/ares_web/router.ex | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/ares_web/components/layouts/root.html.heex b/lib/ares_web/components/layouts/root.html.heex index c983460c..141fd6b3 100644 --- a/lib/ares_web/components/layouts/root.html.heex +++ b/lib/ares_web/components/layouts/root.html.heex @@ -4,7 +4,7 @@ - <.live_title default="Ares" suffix=""> + <.live_title default="BugsByte" suffix=""> {assigns[:page_title]} diff --git a/lib/ares_web/components/navbar.ex b/lib/ares_web/components/navbar.ex index 8db0df8e..d311631a 100644 --- a/lib/ares_web/components/navbar.ex +++ b/lib/ares_web/components/navbar.ex @@ -55,14 +55,14 @@ defmodule AresWeb.Components.Navbar do Previous edition
  • -
  • + <%!--
  • <.link class="hover:text-primary transition-colors" navigate="/app/team-formation" > Teams -
  • + --%> <%= if @user && @user.is_admin do %>
  • <.link @@ -107,12 +107,12 @@ defmodule AresWeb.Components.Navbar do <% else %> - <.link + <%!-- <.link navigate="/register" class="rounded-full px-3 py-2 text-sm font-semibold text-white shadow-sm ring-1 ring-inset ring-white hover:ring-primary hover:text-primary transition-all" > Register - + --%> <% end %>
  • @@ -183,12 +183,12 @@ defmodule AresWeb.Components.Navbar do Profile <% else %> -
    Register - + --%> <% end %> <%= if @user do %> @@ -252,14 +252,14 @@ defmodule AresWeb.Components.Navbar do Previous edition -
  • + <%!--
  • <.link class="block py-3 sm:py-4 text-center text-lg sm:text-xl hover:text-primary transition-colors" navigate="/app/team-formation" > Team formation -
  • + --%> diff --git a/lib/ares_web/live/landing/home.html.heex b/lib/ares_web/live/landing/home.html.heex index 7c6fdc86..58f1d0b0 100644 --- a/lib/ares_web/live/landing/home.html.heex +++ b/lib/ares_web/live/landing/home.html.heex @@ -208,7 +208,7 @@ --%> -
    +<%!--

    Gallery @@ -232,4 +232,4 @@ <% end %>

    -
    + --%> diff --git a/lib/ares_web/router.ex b/lib/ares_web/router.ex index ddea5400..93e63886 100644 --- a/lib/ares_web/router.ex +++ b/lib/ares_web/router.ex @@ -75,7 +75,7 @@ defmodule AresWeb.Router do live_session :current_user, on_mount: [{AresWeb.UserAuth, :mount_current_scope}] do - live "/register", UserLive.Registration, :new + # live "/register", UserLive.Registration, :new live "/log-in", UserLive.Login, :new live "/log-in/:token", UserLive.Confirmation, :new end From adbb22e8593eba4c86868ffe2a12e558fdcf6e6b Mon Sep 17 00:00:00 2001 From: Nuno Miguel Date: Sat, 27 Dec 2025 05:03:52 +0000 Subject: [PATCH 6/6] chore: comment register route usages --- lib/ares_web/live/auth/login.ex | 2 +- test/ares_web/live/user_live/login_test.exs | 26 +-- .../live/user_live/registration_test.exs | 188 +++++++++--------- 3 files changed, 108 insertions(+), 108 deletions(-) diff --git a/lib/ares_web/live/auth/login.ex b/lib/ares_web/live/auth/login.ex index fec756e4..506090ed 100644 --- a/lib/ares_web/live/auth/login.ex +++ b/lib/ares_web/live/auth/login.ex @@ -17,7 +17,7 @@ defmodule AresWeb.UserLive.Login do <% else %>

    Don't have an account? <.link - navigate={~p"/register"} + navigate="/register" class="font-semibold text-primary hover:underline" phx-no-format >Register to participate now. diff --git a/test/ares_web/live/user_live/login_test.exs b/test/ares_web/live/user_live/login_test.exs index 2054181b..dde52e97 100644 --- a/test/ares_web/live/user_live/login_test.exs +++ b/test/ares_web/live/user_live/login_test.exs @@ -75,19 +75,19 @@ defmodule AresWeb.UserLive.LoginTest do end end - describe "login navigation" do - test "redirects to registration page when the Register button is clicked", %{conn: conn} do - {:ok, lv, _html} = live(conn, ~p"/log-in") - - {:ok, _login_live, login_html} = - lv - |> element("main a", "Register") - |> render_click() - |> follow_redirect(conn, ~p"/register") - - assert login_html =~ "Register" - end - end + # describe "login navigation" do + # test "redirects to registration page when the Register button is clicked", %{conn: conn} do + # {:ok, lv, _html} = live(conn, ~p"/log-in") + + # {:ok, _login_live, login_html} = + # lv + # |> element("main a", "Register") + # |> render_click() + # |> follow_redirect(conn, ~p"/register") + + # assert login_html =~ "Register" + # end + # end describe "re-authentication (sudo mode)" do setup %{conn: conn} do diff --git a/test/ares_web/live/user_live/registration_test.exs b/test/ares_web/live/user_live/registration_test.exs index fd0295ab..fcecadf1 100644 --- a/test/ares_web/live/user_live/registration_test.exs +++ b/test/ares_web/live/user_live/registration_test.exs @@ -1,98 +1,98 @@ defmodule AresWeb.UserLive.RegistrationTest do use AresWeb.ConnCase, async: true - import Phoenix.LiveViewTest - import Ares.AccountsFixtures - - describe "Registration page" do - test "renders registration page", %{conn: conn} do - {:ok, _lv, html} = live(conn, ~p"/register") - - assert html =~ "Registration" - assert html =~ "Log in" - end - - test "redirects if already logged in", %{conn: conn} do - result = - conn - |> log_in_user(user_fixture()) - |> live(~p"/register") - |> follow_redirect(conn, ~p"/") - - assert {:ok, _conn} = result - end - - test "renders errors for invalid data", %{conn: conn} do - {:ok, lv, _html} = live(conn, ~p"/register") - - result = - lv - |> element("#registration_form") - |> render_change(user: %{"email" => "with spaces"}) - - assert result =~ "Registration" - assert result =~ "must have the @ sign and no spaces" - end - end - - describe "register user" do - test "creates account but does not log in", %{conn: conn} do - {:ok, lv, _html} = live(conn, ~p"/register") - - email = unique_user_email() - form = form(lv, "#registration_form", user: valid_user_attributes(email: email)) - - fi = - file_input(lv, "#registration_form", :cv, [ - %{name: "cv.pdf", content: "dummy", type: "application/pdf"} - ]) - - render_upload(fi, "cv.pdf") - - {:ok, _lv, html} = - render_submit(form) - |> follow_redirect(conn, ~p"/log-in") - - assert html =~ - ~r/An email was sent to .*, please access it to confirm your account/ - end - - test "renders errors for duplicated email", %{conn: conn} do - {:ok, lv, _html} = live(conn, ~p"/register") - - user = user_fixture(%{email: "test@email.com"}) - - result = - lv - |> form("#registration_form", - user: %{"email" => user.email} - ) - |> then(fn form -> - fi = - file_input(lv, "#registration_form", :cv, [ - %{name: "cv.pdf", content: "dummy", type: "application/pdf"} - ]) - - render_upload(fi, "cv.pdf") - form - end) - |> render_submit() - - assert result =~ "has already been taken" - end - end - - describe "registration navigation" do - test "redirects to login page when the Log in button is clicked", %{conn: conn} do - {:ok, lv, _html} = live(conn, ~p"/register") - - {:ok, _login_live, login_html} = - lv - |> element("main a", "Log in") - |> render_click() - |> follow_redirect(conn, ~p"/log-in") - - assert login_html =~ "Log in" - end - end + # import Phoenix.LiveViewTest + # import Ares.AccountsFixtures + + # describe "Registration page" do + # test "renders registration page", %{conn: conn} do + # {:ok, _lv, html} = live(conn, ~p"/register") + + # assert html =~ "Registration" + # assert html =~ "Log in" + # end + + # test "redirects if already logged in", %{conn: conn} do + # result = + # conn + # |> log_in_user(user_fixture()) + # |> live(~p"/register") + # |> follow_redirect(conn, ~p"/") + + # assert {:ok, _conn} = result + # end + + # test "renders errors for invalid data", %{conn: conn} do + # {:ok, lv, _html} = live(conn, ~p"/register") + + # result = + # lv + # |> element("#registration_form") + # |> render_change(user: %{"email" => "with spaces"}) + + # assert result =~ "Registration" + # assert result =~ "must have the @ sign and no spaces" + # end + # end + + # describe "register user" do + # test "creates account but does not log in", %{conn: conn} do + # {:ok, lv, _html} = live(conn, ~p"/register") + + # email = unique_user_email() + # form = form(lv, "#registration_form", user: valid_user_attributes(email: email)) + + # fi = + # file_input(lv, "#registration_form", :cv, [ + # %{name: "cv.pdf", content: "dummy", type: "application/pdf"} + # ]) + + # render_upload(fi, "cv.pdf") + + # {:ok, _lv, html} = + # render_submit(form) + # |> follow_redirect(conn, ~p"/log-in") + + # assert html =~ + # ~r/An email was sent to .*, please access it to confirm your account/ + # end + + # test "renders errors for duplicated email", %{conn: conn} do + # {:ok, lv, _html} = live(conn, ~p"/register") + + # user = user_fixture(%{email: "test@email.com"}) + + # result = + # lv + # |> form("#registration_form", + # user: %{"email" => user.email} + # ) + # |> then(fn form -> + # fi = + # file_input(lv, "#registration_form", :cv, [ + # %{name: "cv.pdf", content: "dummy", type: "application/pdf"} + # ]) + + # render_upload(fi, "cv.pdf") + # form + # end) + # |> render_submit() + + # assert result =~ "has already been taken" + # end + # end + + # describe "registration navigation" do + # test "redirects to login page when the Log in button is clicked", %{conn: conn} do + # {:ok, lv, _html} = live(conn, ~p"/register") + + # {:ok, _login_live, login_html} = + # lv + # |> element("main a", "Log in") + # |> render_click() + # |> follow_redirect(conn, ~p"/log-in") + + # assert login_html =~ "Log in" + # end + # end end