defmodule PutzplanWeb.TaskLive.Index do use PutzplanWeb, :live_view @impl true def render(assigns) do ~H""" <.header> Listing Tasks <:actions> <.link patch={~p"/tasks/new"}> <.button>New Task
<%= for task <- @tasks do %>
{task.description}
<.link phx-click={JS.push("complete", value: %{id: task.id})} class="text-green-600 hover:text-green-800 p-1 rounded-full hover:bg-green-100" >
Due
{format_date(task.due)}
<.link navigate={~p"/tasks/#{task}"}>Show
<.link patch={~p"/tasks/#{task}/edit"} class="text-blue-600 hover:text-blue-800 p-1 rounded-full hover:bg-blue-100" phx-click-stop-propagation="true" > <.link phx-click={JS.push("delete", value: %{id: task.id}) |> hide(task.id)} data-confirm="Are you sure?" class="text-red-600 hover:text-red-800 p-1 rounded-full hover:bg-red-100" phx-click-stop-propagation="true" >
<% end %>
<.modal :if={@live_action in [:new, :edit]} id="task-modal" show on_cancel={JS.patch(~p"/tasks")}> <.live_component module={PutzplanWeb.TaskLive.FormComponent} id={(@task && @task.id) || :new} title={@page_title} current_user={@current_user} action={@live_action} task={@task} patch={~p"/"} /> """ end @impl true def mount(_params, _session, socket) do if connected?(socket), do: Putzplan.PubSub.subscribe_tasks() tasks = Ash.read!(Putzplan.Tasks.Task, load: [:due], actor: socket.assigns[:current_user]) |> sort_tasks_by_due_date() {:ok, socket |> assign(:tasks, tasks) |> assign_new(:current_user, fn -> nil end)} end defp sort_tasks_by_due_date(tasks) do Enum.sort_by(tasks, & &1.due, Date) end @impl true def handle_params(params, _url, socket) do {:noreply, apply_action(socket, socket.assigns.live_action, params)} end @impl true def handle_info({:delete, task}, socket) do updated_tasks = Enum.reject(socket.assigns.tasks, fn t -> t.id == task.id end) {:noreply, assign(socket, :tasks, updated_tasks)} end @impl true def handle_info({:upsert, task}, socket) do updated_tasks = socket.assigns.tasks |> Enum.reject(fn t -> t.id == task.id end) |> Enum.concat([task]) |> sort_tasks_by_due_date() {:noreply, assign(socket, :tasks, updated_tasks)} end @impl true def handle_info({:update, task_id}, socket) do task = Ash.get!(Putzplan.Tasks.Task, task_id, load: [:due]) updated_tasks = socket.assigns.tasks |> Enum.reject(fn t -> t.id == task.id end) |> Enum.concat([task]) |> sort_tasks_by_due_date() {:noreply, assign(socket, :tasks, updated_tasks)} end defp apply_action(socket, :edit, %{"id" => id}) do socket |> assign(:page_title, "Edit Task") |> assign( :task, Ash.get!(Putzplan.Tasks.Task, id, actor: socket.assigns.current_user) ) end defp apply_action(socket, :new, _params) do socket |> assign(:page_title, "New Task") |> assign(:task, nil) end defp apply_action(socket, :index, _params) do socket |> assign(:page_title, "Listing Tasks") |> assign(:task, nil) end @impl true def handle_event("delete", %{"id" => id}, socket) do task = Ash.get!(Putzplan.Tasks.Task, id, actor: socket.assigns.current_user) Ash.destroy!(task, actor: socket.assigns.current_user) Putzplan.PubSub.delete_task(task) {:noreply, socket} end @impl true def handle_event("complete", %{"id" => id}, socket) do completed_task = Putzplan.Tasks.CompletedTask |> Ash.Changeset.for_create(:create, %{task: id, user: socket.assigns.current_user.id}) |> Ash.create!(actor: socket.assigns.current_user) task = Ash.get!(Putzplan.Tasks.Task, id, load: [:due]) Putzplan.PubSub.upsert_task(task) Putzplan.PubSub.upsert_completed_task(completed_task) {:noreply, socket} end defp format_date(date) do string = case Date.diff(date, Date.utc_today()) do -1 -> "yesterday" 0 -> "today" 1 -> "tomorrow" days when days > 0 and days < 7 -> "next " <> get_weekday(Date.day_of_week(date)) _ -> Date.to_string(date) end String.capitalize(string) end defp get_weekday(index) do days = %{ 1 => "monday", 2 => "tuesday", 3 => "wednesday", 4 => "thursday", 5 => "friday", 6 => "saturday", 7 => "sunday" } Map.get(days, index) end end