From 771299c951477d266afc86d7417302dbd9850791 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sat, 25 Apr 2026 16:51:54 -0500 Subject: [PATCH] feat(accounts): add Home QTH section to user settings page --- lib/microwaveprop/accounts.ex | 17 +++++++++++ .../controllers/user_settings_controller.ex | 21 ++++++++++++++ .../user_settings_html/edit.html.heex | 29 +++++++++++++++++++ .../user_settings_controller_test.exs | 28 ++++++++++++++++++ 4 files changed, 95 insertions(+) diff --git a/lib/microwaveprop/accounts.ex b/lib/microwaveprop/accounts.ex index 21c69e56..8c66041f 100644 --- a/lib/microwaveprop/accounts.ex +++ b/lib/microwaveprop/accounts.ex @@ -235,6 +235,23 @@ defmodule Microwaveprop.Accounts do |> update_user_and_delete_all_tokens() end + @doc """ + Builds a home-QTH changeset from the given attrs (no DB write). + Useful for rendering the form in templates and LiveViews. + """ + @spec change_user_home_qth(User.t(), map()) :: Ecto.Changeset.t() + def change_user_home_qth(%User{} = user, attrs \\ %{}) do + User.change_home_qth(user, attrs) + end + + @doc """ + Updates the user's home QTH (grid + lat/lon + optional elevation). + """ + @spec update_user_home_qth(User.t(), map()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} + def update_user_home_qth(%User{} = user, attrs) do + user |> User.change_home_qth(attrs) |> Repo.update() + end + ## Session @doc """ diff --git a/lib/microwaveprop_web/controllers/user_settings_controller.ex b/lib/microwaveprop_web/controllers/user_settings_controller.ex index c721cc58..ca621336 100644 --- a/lib/microwaveprop_web/controllers/user_settings_controller.ex +++ b/lib/microwaveprop_web/controllers/user_settings_controller.ex @@ -9,6 +9,7 @@ defmodule MicrowavepropWeb.UserSettingsController do plug :require_sudo_mode plug :assign_email_and_password_changesets + plug :assign_home_qth_changeset plug :assign_beacon_monitors def edit(conn, _params) do @@ -40,6 +41,21 @@ defmodule MicrowavepropWeb.UserSettingsController do end end + def update(conn, %{"action" => "update_home_qth"} = params) do + %{"user" => user_params} = params + user = conn.assigns.current_scope.user + + case Accounts.update_user_home_qth(user, user_params) do + {:ok, _user} -> + conn + |> put_flash(:info, "Home QTH updated.") + |> redirect(to: ~p"/users/settings") + + {:error, changeset} -> + render(conn, :edit, home_qth_changeset: changeset) + end + end + def update(conn, %{"action" => "update_password"} = params) do %{"user" => user_params} = params user = conn.assigns.current_scope.user @@ -78,6 +94,11 @@ defmodule MicrowavepropWeb.UserSettingsController do |> assign(:password_changeset, Accounts.change_user_password(user)) end + defp assign_home_qth_changeset(conn, _opts) do + user = conn.assigns.current_scope.user + assign(conn, :home_qth_changeset, Accounts.change_user_home_qth(user)) + end + defp assign_beacon_monitors(conn, _opts) do user = conn.assigns.current_scope.user diff --git a/lib/microwaveprop_web/controllers/user_settings_html/edit.html.heex b/lib/microwaveprop_web/controllers/user_settings_html/edit.html.heex index b163e66f..9cc1e595 100644 --- a/lib/microwaveprop_web/controllers/user_settings_html/edit.html.heex +++ b/lib/microwaveprop_web/controllers/user_settings_html/edit.html.heex @@ -23,6 +23,35 @@
+ <.form :let={f} for={@home_qth_changeset} action={~p"/users/settings"} id="update_home_qth"> + + +
+

Home QTH

+

+ Used to anchor the rover map (drive radius, distance/bearing labels). + Enter a Maidenhead grid (e.g. EM13qc) or explicit lat/lon. +

+
+ + <.input + field={f[:home_grid]} + type="text" + label="Home grid" + placeholder="EM13qc" + autocomplete="off" + /> + +
+ <.input field={f[:home_lat]} type="number" step="any" label="Latitude" /> + <.input field={f[:home_lon]} type="number" step="any" label="Longitude" /> +
+ + <.button variant="primary" phx-disable-with="Saving...">Save Home QTH + + +
+ <.form :let={f} for={@password_changeset} action={~p"/users/settings"} id="update_password"> diff --git a/test/microwaveprop_web/controllers/user_settings_controller_test.exs b/test/microwaveprop_web/controllers/user_settings_controller_test.exs index 22eb96e9..999ba4a6 100644 --- a/test/microwaveprop_web/controllers/user_settings_controller_test.exs +++ b/test/microwaveprop_web/controllers/user_settings_controller_test.exs @@ -70,6 +70,34 @@ defmodule MicrowavepropWeb.UserSettingsControllerTest do end end + describe "PUT /users/settings (home QTH form)" do + test "updates the user home QTH from a grid", %{conn: conn, user: user} do + conn = + put(conn, ~p"/users/settings", %{ + "action" => "update_home_qth", + "user" => %{"home_grid" => "EM13qc"} + }) + + assert redirected_to(conn) == ~p"/users/settings" + reloaded = Microwaveprop.Repo.reload(user) + assert reloaded.home_grid == "EM13qc" + assert is_float(reloaded.home_lat) + assert is_float(reloaded.home_lon) + end + + test "rejects an invalid grid", %{conn: conn} do + conn = + put(conn, ~p"/users/settings", %{ + "action" => "update_home_qth", + "user" => %{"home_grid" => "ZZ99zz"} + }) + + response = html_response(conn, 200) + assert response =~ "Home QTH" + assert response =~ "must be a 4 or 6 character" + end + end + describe "PUT /users/settings (change email form)" do @tag :capture_log test "updates the user email", %{conn: conn, user: user} do