diff --git a/lib/atlas/accounts.ex b/lib/atlas/accounts.ex index 38a05f2..9f28781 100644 --- a/lib/atlas/accounts.ex +++ b/lib/atlas/accounts.ex @@ -5,7 +5,7 @@ defmodule Atlas.Accounts do use Atlas.Context - alias Atlas.Accounts.{User, UserNotifier, UserSession, UserToken} + alias Atlas.Accounts.{User, UserNotifier, UserPreference, UserSession, UserToken} ## Database getters @@ -488,4 +488,65 @@ defmodule Atlas.Accounts do Guardian.DB.revoke_all(user_session.id) Repo.delete(user_session) end + + ## User Preference + + @doc """ + Gets the language preference for a given user. + + ## Examples + + iex> get_user_preference(1) + %UserPreference{} + + iex> get_user_preference(999) + nil + """ + def get_user_preference(user_id) do + Repo.get_by(UserPreference, user_id: user_id) + end + + @doc """ + Gets the language string for a given user. + + Returns `nil` if no preference is set. + + ## Examples + + iex> get_user_language(1) + "pt-PT" + + iex> get_user_language(999) + nil + """ + def get_user_language(user_id) do + Repo.one( + from up in UserPreference, + where: up.user_id == ^user_id, + select: up.language, + limit: 1 + ) + end + + @doc """ + Sets the language preference for a given user. + + If the preference exists, it updates only the language field. + + ## Examples + + iex> set_user_language(1, "pt-PT") + {:ok, %UserPreference{}} + + iex> set_user_language(1, "invalid") + {:error, %Ecto.Changeset{}} + """ + def set_user_language(user_id, language) do + %UserPreference{} + |> UserPreference.changeset(%{user_id: user_id, language: language}) + |> Repo.insert( + on_conflict: [set: [language: language]], + conflict_target: :user_id + ) + end end diff --git a/lib/atlas/accounts/user_preferences.ex b/lib/atlas/accounts/user_preferences.ex new file mode 100644 index 0000000..2d9616e --- /dev/null +++ b/lib/atlas/accounts/user_preferences.ex @@ -0,0 +1,30 @@ +defmodule Atlas.Accounts.UserPreference do + @moduledoc """ + Schema for storing a user's preference. + """ + + use Ecto.Schema + import Ecto.Changeset + + @primary_key {:id, :binary_id, autogenerate: true} + @foreign_key_type :binary_id + + @languages ~w(pt-PT en-US) + + schema "user_preferences" do + field :language, :string + + belongs_to :user, Atlas.Accounts.User + + timestamps() + end + + def changeset(user_preference, attrs) do + user_preference + |> cast(attrs, [:user_id, :language]) + |> validate_required([:user_id, :language]) + |> validate_inclusion(:language, @languages) + |> assoc_constraint(:user) + |> unique_constraint(:user_id) + end +end diff --git a/priv/repo/migrations/20250726211654_create_user_preferences.exs b/priv/repo/migrations/20250726211654_create_user_preferences.exs new file mode 100644 index 0000000..ff7a4c4 --- /dev/null +++ b/priv/repo/migrations/20250726211654_create_user_preferences.exs @@ -0,0 +1,18 @@ +defmodule Atlas.Repo.Migrations.CreateUserPreferences do + use Ecto.Migration + + def change do + create table(:user_preferences) do + add :user_id, references(:users, type: :uuid, on_delete: :delete_all), null: false + add :language, :string, null: false + + timestamps() + end + + create unique_index(:user_preferences, [:user_id]) + + create constraint(:user_preferences, :language_must_be_valid, + check: "language IN ('pt-PT', 'en-US')" + ) + end +end