lib/layout/row.ex

defmodule LayoutBuilder.Layout.Row do
  use Ecto.Schema
  import Ecto.Changeset
  alias Ecto.UUID
  alias LayoutBuilder.Layout.Col

  @moduledoc """
  Row represents a row inside a Layout or a Col.
  """

  @type t() :: %__MODULE__{
    id: Ecto.UUID.t() | nil,
    name: String.t(),
    cols: list(Col.t()) | nil,
  }

  embedded_schema do
    field :name, :string
    embeds_many :cols, Col
  end

  @spec build_row() :: %__MODULE__{
    id: Ecto.UUID.t(),
    name: nil,
    cols: [
      %Col{
        id: Ecto.UUID.t(),
        name: nil,
        rows: []
      }
    ]
  }
  def build_row(), do: %__MODULE__{id: UUID.generate(), cols: [Col.build_col]}

  @spec add_col(__MODULE__.t()) :: __MODULE__.t()
  def add_col(%__MODULE__{} = row) do
    %__MODULE__{row | cols: [Col.build_col | row.cols]}
  end

  def changeset(%__MODULE__{} = struct, attrs) do
    change(struct)
    |> changeset(attrs)
  end

  def changeset(%Ecto.Changeset{} = change, %__MODULE__{} = attrs) do
    changeset(change, Map.from_struct(attrs))
  end

  def changeset(%Ecto.Changeset{} = change, %{} = attrs) do
    change
    |> cast(attrs, [:name])
    |> cast_embed(:cols)
  end
end