WIP
This commit is contained in:
parent
c9791acff8
commit
8b17c987d8
4 changed files with 57 additions and 41 deletions
|
@ -1,6 +1,7 @@
|
|||
defmodule ChoreTracker.Accounts.User do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
alias ChoreTracker.Chores
|
||||
|
||||
schema "users" do
|
||||
field :username, :string
|
||||
|
@ -12,6 +13,8 @@ defmodule ChoreTracker.Accounts.User do
|
|||
field :display_name, :string
|
||||
|
||||
timestamps(type: :utc_datetime)
|
||||
|
||||
has_many :assigned_chores, Chores.Chore, foreign_key: :next_assignee_id
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
|
|
@ -19,24 +19,41 @@ defmodule ChoreTracker.Chores do
|
|||
do: Repo.get!(Chore, id) |> Repo.preload([{:logs, :user}, :assignees, :next_assignee])
|
||||
|
||||
def create_chore(attrs \\ %{}) do
|
||||
%Chore{}
|
||||
|> change_chore(attrs)
|
||||
|> Repo.insert()
|
||||
result =
|
||||
Ecto.Multi.new()
|
||||
|> Ecto.Multi.insert(:chore, change_chore(%Chore{}, attrs))
|
||||
|> Ecto.Multi.update(:chore_with_assignee, fn %{chore: chore} ->
|
||||
next_assignee = next_chore_assignee(chore)
|
||||
change_chore_assignee(chore, next_assignee)
|
||||
end)
|
||||
|> Repo.transaction()
|
||||
|
||||
case result do
|
||||
{:ok, %{chore_with_assignee: chore}} -> {:ok, chore}
|
||||
{:error, :chore, changeset, _} -> {:error, changeset}
|
||||
end
|
||||
end
|
||||
|
||||
def update_chore(%Chore{} = chore, attrs) do
|
||||
changeset = change_chore(chore, attrs)
|
||||
|
||||
result =
|
||||
Ecto.Multi.new()
|
||||
|> Ecto.Multi.update(:chore, changeset)
|
||||
|> Ecto.Multi.run(:update_next_assignee, fn _repo, %{chore: chore} ->
|
||||
|> Ecto.Multi.update(:chore_with_assignee, fn %{chore: chore} ->
|
||||
if Ecto.Changeset.changed?(changeset, :assignees) do
|
||||
save_next_chore_assignee(chore)
|
||||
next_assignee = next_chore_assignee(chore)
|
||||
change_chore_assignee(chore, next_assignee)
|
||||
else
|
||||
{:ok, chore}
|
||||
Ecto.Changeset.change(chore)
|
||||
end
|
||||
end)
|
||||
|> Repo.transaction()
|
||||
|
||||
case result do
|
||||
{:ok, %{chore_with_assignee: chore}} -> {:ok, chore}
|
||||
{:error, :chore, changeset, _} -> {:error, changeset}
|
||||
end
|
||||
end
|
||||
|
||||
def delete_chore(%Chore{} = chore) do
|
||||
|
@ -51,12 +68,14 @@ defmodule ChoreTracker.Chores do
|
|||
|> Changeset.put_assoc(:assignees, assignees)
|
||||
end
|
||||
|
||||
def update_chore_assignee(%Chore{} = chore, attrs) do
|
||||
change_chore_assignee(chore, attrs) |> Repo.update()
|
||||
def change_chore_assignee(%Chore{} = chore, user) do
|
||||
id =
|
||||
case user do
|
||||
nil -> nil
|
||||
%User{} -> user.id
|
||||
end
|
||||
|
||||
def change_chore_assignee(%Chore{} = chore, attrs \\ %{}) do
|
||||
chore |> Ecto.Changeset.cast(attrs, [:next_assignee_id])
|
||||
chore |> Ecto.Changeset.change(%{next_assignee_id: id})
|
||||
end
|
||||
|
||||
def get_last_chore_log_for_assignee(%Chore{} = chore, %User{} = user) do
|
||||
|
@ -74,8 +93,9 @@ defmodule ChoreTracker.Chores do
|
|||
:log,
|
||||
%ChoreLog{} |> ChoreLog.changeset(%{user_id: user.id, chore_id: chore.id})
|
||||
)
|
||||
|> Ecto.Multi.run(:chore, fn _repo, _change ->
|
||||
save_next_chore_assignee(chore)
|
||||
|> Ecto.Multi.update(:chore_assignee, fn _ ->
|
||||
next_assignee = next_chore_assignee(chore)
|
||||
change_chore_assignee(chore, next_assignee)
|
||||
end)
|
||||
|> Repo.transaction()
|
||||
end
|
||||
|
@ -113,28 +133,21 @@ defmodule ChoreTracker.Chores do
|
|||
Returns `nil` if chore has no assignees.
|
||||
"""
|
||||
def next_chore_assignee(%Chore{} = chore) do
|
||||
chore = chore |> Repo.preload([{:assignees, :assigned_chores}])
|
||||
|
||||
chore.assignees
|
||||
|> Enum.map(&{&1, get_last_chore_log_for_assignee(chore, &1)})
|
||||
|> Enum.sort_by(
|
||||
fn {_assignee, log} ->
|
||||
case log do
|
||||
fn assignee ->
|
||||
time =
|
||||
case get_last_chore_log_for_assignee(chore, assignee) do
|
||||
nil -> 0
|
||||
%ChoreLog{inserted_at: inserted_at} -> DateTime.to_unix(inserted_at)
|
||||
end
|
||||
|
||||
{time, length(assignee.assigned_chores)}
|
||||
end,
|
||||
:asc
|
||||
:desc
|
||||
)
|
||||
|> Enum.map(fn {assignee, _log} -> assignee end)
|
||||
|> List.first()
|
||||
end
|
||||
|
||||
defp save_next_chore_assignee(%Chore{} = chore) do
|
||||
next_assignee = next_chore_assignee(chore)
|
||||
|
||||
if next_assignee do
|
||||
chore |> update_chore_assignee(%{next_assignee_id: next_assignee.id})
|
||||
else
|
||||
{:ok, nil}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,7 +21,7 @@ defmodule ChoreTrackerWeb.ChoreLive.FormComponent do
|
|||
>
|
||||
<div class="flex gap-2 flex-wrap">
|
||||
<.input field={@form[:name]} type="text" label="Name" wrapper_class="flex-1" />
|
||||
<.input field={@form[:emoji]} type="text" label="Emoji" />
|
||||
<.input field={@form[:emoji]} type="text" label="Emoji" min="1" max="1" />
|
||||
</div>
|
||||
<.input field={@form[:description]} type="textarea" label="Description" />
|
||||
<div class="flex gap-6 flex-wrap">
|
||||
|
|
|
@ -41,7 +41,7 @@ defmodule ChoreTrackerWeb.ChoreLive.Show do
|
|||
%{"chore" => chore_params} = params
|
||||
chore = socket.assigns.chore
|
||||
|
||||
case Chores.update_chore_assignee(chore, chore_params) do
|
||||
case Chores.update_chore(chore, chore_params) do
|
||||
{:ok, chore} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|
@ -57,6 +57,6 @@ defmodule ChoreTrackerWeb.ChoreLive.Show do
|
|||
defp update_state(socket, chore) do
|
||||
socket
|
||||
|> assign(:chore, chore |> Repo.preload(:next_assignee))
|
||||
|> assign(:assignee_form, to_form(Chores.change_chore_assignee(chore)))
|
||||
|> assign(:assignee_form, to_form(Chores.change_chore(chore)))
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue