defmodule Usher.Web.Components.InvitationFormComponent do
@moduledoc false
use Usher.Web, :live_component
alias Usher.Invitation
defmodule InvitationFormData do
@moduledoc """
Embedded schema and changeset functions for the invitation form.
Reasons why we're not directly using an `Usher.Invitation` changeset:
1. We need to convert between `expires_at` (a `DateTime`) and `expires_on` (a `Date`)
for user-friendly date input.
2. We want to handle the optional expiration date with a checkbox, which doesn't map
directly to the `Invitation` schema. While we could user a `:virtual` field for this,
Usher Web can't modify the original schema.
"""
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field(:name, :string)
field(:token, :string)
field(:set_expiration, :boolean, default: false)
field(:expires_on, :date)
end
def create_changeset(%Invitation{} = invitation) do
expires_on =
if invitation.expires_at do
DateTime.to_date(invitation.expires_at)
else
nil
end
attrs =
invitation
|> Map.from_struct()
|> Map.take([:name, :token])
|> Map.put(:set_expiration, not is_nil(invitation.expires_at))
|> Map.put(:expires_on, expires_on)
%__MODULE__{}
|> cast(attrs, [:name, :token, :expires_on, :set_expiration])
end
def update_changeset(struct, attrs) do
struct
|> cast(attrs, [:name, :token, :expires_on, :set_expiration])
|> validate_required([:name])
|> maybe_clear_expires_on()
end
defp maybe_clear_expires_on(changeset) do
case get_field(changeset, :set_expiration) do
true ->
validate_required(changeset, [:expires_on])
false ->
put_change(changeset, :expires_on, nil)
end
end
end
@impl Phoenix.LiveComponent
def render(assigns) do
~H"""