Small liveview changes

This commit is contained in:
Ryan Pandya 2022-11-05 13:57:45 -07:00
parent 90c3b06cfc
commit c72c09b1b2
10 changed files with 343 additions and 161 deletions

View File

@ -153,19 +153,8 @@ defmodule Friends.Friend do
Date.diff(Date.utc_today(), friend.born) |> div(365) Date.diff(Date.utc_today(), friend.born) |> div(365)
end end
# TODO: Refactor def can_be_edited_by(friend, user) do
def create_birth_event(friend) do friend.id == user.profile.id
if is_nil(
@repo.all(
from(e in Friends.Event,
where: e.name == "born"
)
)
|> List.flatten()
) do
else
"find"
end
end end
def assign_user(%Friend{} = friend) do def assign_user(%Friend{} = friend) do

View File

@ -0,0 +1,167 @@
defmodule FriendsWeb.FriendsLive.Components do
use FriendsWeb, :live_view
use Phoenix.HTML
import Helpers
alias Friends.Friend
def show_page("overview", assigns) do
~H"""
<ul class="py-4 pl-0 md:text-xl h-1/2">
<li class="flex flex-row mb-8 gap-6">
<strong class="w-28 text-right">Nickname:</strong>
<div class="">
<%= if is_nil(@friend.nickname) do %>
<span class="italic">none</span>
<% else %>
<%= @friend.nickname %>
<% end %>
</div>
</li>
<li class="flex flex-row mb-8 gap-6">
<strong class="w-28 text-right">Birthday:</strong>
<div class=""><%= @friend.born |> Calendar.strftime("%B %d, %Y") %>
<br class="md:hidden"/>
<span class="font-light">(<%= @friend |> Friend.age %> years old)</span>
</div>
</li>
<li class="flex flex-row mb-8 gap-6">
<strong class="w-28 text-right">Email:</strong>
<div class=""><%= @friend.email %></div>
</li>
<li class="flex flex-row mb-8 gap-6">
<strong class="w-28 text-right">Phone:</strong>
<div class=""><%= @friend.phone %></div>
</li>
</ul>
<%= if @friend |> Friend.can_be_edited_by(@current_user) do %>
<div class="form-control flex flex-row mb-4">
<.link patch={"/friend/#{@friend.slug}/#{@page_view}/edit"} class="btn btn-block md:btn-wide text-white">edit</.link>
</div>
<% end %>
"""
end
def show_page("calendar", assigns) do
~H"""
<div id="calendar" class="flex md:flex-row flex-col gap-8 p-8">
<%= for event <- @friend |> Friends.Friend.get_events do %>
<ul>
<li>
<%= event.name %>
</li>
</ul>
<% end %>
<%= if @friend |> Friends.Friend.get_events |> Enum.empty? do %>
<div class="italic">None yet.</div>
<% end %>
</div>
"""
end
def show_page("relationships", assigns) do
~H"""
<div id="relationships" class="flex md:flex-row flex-col gap-8">
<%= for relation <- @friend |> relations do %>
<% relationship = relation(@friend, relation) %>
<div id={"relation-#{relation.id}"} class="card card-compact w-96 bg-base-100 shadow-xl">
<figure><img src="https://placeimg.com/400/225/people" alt={relation.id} /></figure>
<div class="card-body">
<h3 class="card-title">
<%= relation.name %>
<%= if relationship |> Friends.Relationship.get_relation do %>
<div class={"badge badge-#{relationship |> Friends.Relationship.get_color}"}><%= relationship |> Friends.Relationship.get_relation %></div>
<% end %>
</h3>
<p>If a dog chews shoes whose shoes does he choose?</p>
</div>
</div>
<% end %>
<%= if @friend |> relations |> Enum.empty? do %>
<div class="italic p-4">No relationships on record yet.</div>
<% end %>
</div>
<div class="form-control flex flex-row my-8">
<.link patch={"/friend/#{@friend.slug}/update?page=relationships"} class="btn btn-block md:btn-wide text-white">edit</.link>
</div>
"""
end
###
def form_page("overview", assigns) do
~H"""
<.form
for={@changeset}
let={f}
action={@action}
phx_change= "validate"
phx_submit= "save">
<%= hidden_input f, :id, value: @friend.id %>
<div class="border-b-4 flex flex-row">
<%= text_input f, :name, placeholder: "Full Name",
class: "m-0 p-0 pb-2 pl-2 input input-bordered border-dashed",
style: "color: var(--tw-prose-headings);
font-weight: 800;
font-size: 2.25em;
min-width: 50%;
text-indent: 4px;
line-height: 1.1111111;",
value: @friend.name,
phx_debounce: :blur %>
<div class="min-w-fit flex place-items-center mx-4"><%= error_tag f, :name %></div>
</div>
<ul class="py-4 pl-0 h-1/2">
<li class="flex flex-row gap-x-6 h-16">
<strong class="md:text-xl w-20 md:w-28 shrink-0 text-right">Nickname:</strong>
<div class=""><%= text_input f, :nickname, class: "input input-primary input-sm md:input-md", phx_debounce: "blur", value: @friend.nickname %></div>
</li>
<li class="flex flex-row gap-x-6">
<strong class="md:text-xl w-20 md:w-28 shrink-0 text-right">Birthday:</strong>
<div class="flex flex-col h-16">
<%= date_input f, :born, class: "input input-primary input-sm md:input-md", phx_debounce: "blur", value: @friend.born %>
<div class="min-w-fit flex place-items-center mr-4"><%= error_tag f, :born %></div>
</div>
</li>
<li class="flex flex-row gap-x-6">
<strong class="md:text-xl w-20 md:w-28 shrink-0 text-right">Email:</strong>
<div class="flex flex-col h-16">
<%= text_input f, :email, class: "input input-primary input-sm md:input-md", phx_debounce: "blur", value: @friend.email %>
<div class="min-w-fit flex place-items-center mr-4"><%= error_tag f, :email %></div>
</div>
</li>
<li class="flex flex-row gap-x-6">
<strong class="md:text-xl w-20 md:w-28 shrink-0 text-right">Phone:</strong>
<div class="flex flex-col h-16">
<%= text_input f, :phone, class: "input input-primary input-sm md:input-md", phx_debounce: "blur", value: @friend.phone %>
<div class="min-w-fit flex place-items-center mr-4"><%= error_tag f, :phone %></div>
</div>
</li>
</ul>
<div class="form-control flex flex-row gap-x-4 md:justify-end mb-4 md:w-1/2">
<div class="flex-1">
<.link patch={"/friend/#{@friend.slug}"} class="btn btn-block btn-outline">back</.link>
</div>
<div class="flex-1">
<%= if @changeset.valid? do %>
<%= submit "Save", phx_disable_with: "Saving...", class: "btn btn-block" %>
<% else %>
<%= submit "Save", class: "btn btn-block btn-disabled" %>
<% end %>
</div>
<%= if @live_action != :new do %>
<div class="flex-1">
<button phx-click="delete" phx-value-friend_id={@friend.id} class="btn btn-block btn-error">Delete</button>
</div>
<% end %>
</div>
</.form>
"""
end
def form_page("relationships", assigns) do
~H"""
<%= FriendsWeb.FriendLive.Friend.header(assigns) %>
"""
end
end

View File

@ -1,53 +1,63 @@
defmodule FriendsWeb.FriendLive.Friend do defmodule FriendsWeb.FriendsLive.Friend do
use FriendsWeb, :live_view use FriendsWeb, :live_view
use Phoenix.HTML
import Helpers
import Helpers.Names
alias Friends.{Friend,Relationship}
alias FriendsWeb.FriendLive.Components alias FriendsWeb.FriendLive.Components
alias FriendsWeb.Router.Helpers, as: Routes alias FriendsWeb.Router.Helpers, as: Routes
alias Friends.Friend
import FriendsWeb.LiveHelpers
import Helpers
import Helpers.Names
# Initialize variables on first load # Initialize variables on first load
def mount(%{}, _token, socket) do def mount(%{}, token, socket) do
{:ok, socket {:ok,
socket
|> title("New Friend") |> title("New Friend")
|> assign(:changeset, %Friend{} |> Friend.changeset) |> assign_current_user(token |> Map.get("user_token"))
} |> assign(:changeset, %Friend{} |> Friend.changeset())}
end end
# Show Friend # Show Friend
def handle_params(%{"slug" => slug} = attrs, _token, socket) do def handle_params(%{"slug" => slug} = attrs, _url, socket) do
friend = Friend.get_by_slug(slug) friend = Friend.get_by_slug(slug)
page = if (attrs |> Map.get("page")) in ["overview", "calendar", "relationships"] do page =
if (attrs |> Map.get("page")) in ["overview", "calendar", "relationships"] do
attrs["page"] attrs["page"]
else else
"overview" "redir"
end end
{:noreply, socket if page == "redir" do
{:noreply,
socket
|> push_patch(to: "/friend/#{slug}/overview")}
else
{:noreply,
socket
|> title(friend.name <> " - " <> (page |> :string.titlecase())) |> title(friend.name <> " - " <> (page |> :string.titlecase()))
|> assign_friend(friend) |> assign_friend(friend)
|> page_view(page) |> page_view(page)
|> assign(:action, Routes.friend_path(socket, :update, friend.id)) |> assign(:current_user, nil)
} |> assign(:action, Routes.friend_path(socket, :update, friend.id))}
end
end end
# New Friend # New Friend
def handle_params(attrs, _token, socket) do def handle_params(_attrs, _token, socket) do
friend = Friend.new friend = Friend.new()
{:noreply, socket
{:noreply,
socket
|> title("New Friend") |> title("New Friend")
|> assign_friend(friend) |> assign_friend(friend)
|> page_view("overview") |> page_view("overview")
|> assign(:action,Routes.friend_path(socket, :create)) |> assign(:action, Routes.friend_path(socket, :create))}
}
end end
# Handle form validation # Handle form validation
def handle_event("validate", %{"friend" => form_params}, %{assigns: %{friend: friend}} = socket) do def handle_event("validate", %{"friend" => form_params}, %{assigns: %{friend: friend}} = socket) do
id = form_params["id"] id = form_params["id"]
name = form_params["name"] name = form_params["name"]
nickname = form_params["nickname"] nickname = form_params["nickname"]
@ -65,20 +75,25 @@ defmodule FriendsWeb.FriendLive.Friend do
email: email email: email
} }
changeset = %Friend{} changeset =
%Friend{}
|> Friend.changeset(new_params) |> Friend.changeset(new_params)
|> Map.put(:action, :validate) |> Map.put(:action, :validate)
{ {
:noreply, socket :noreply,
socket
|> assign(:changeset, changeset) |> assign(:changeset, changeset)
|> assign_friend(friend |> struct(new_params), changeset) |> assign_friend(friend |> struct(new_params), changeset)
} }
end end
# Handle form saving # Handle form saving
def handle_event("save", %{"friend" => form_params},%{assigns: %{changeset: changeset}} = socket) do def handle_event(
"save",
%{"friend" => form_params},
%{assigns: %{changeset: changeset}} = socket
) do
name = form_params["name"] name = form_params["name"]
nickname = form_params["nickname"] nickname = form_params["nickname"]
born = form_params["born"] born = form_params["born"]
@ -97,7 +112,7 @@ defmodule FriendsWeb.FriendLive.Friend do
} }
updated_friend = Friend.create_or_update(new_params) updated_friend = Friend.create_or_update(new_params)
new_changeset = updated_friend |> Friend.changeset new_changeset = updated_friend |> Friend.changeset()
{ {
:noreply, :noreply,
@ -111,27 +126,19 @@ defmodule FriendsWeb.FriendLive.Friend do
# Handle deleting a friend # Handle deleting a friend
def handle_event("delete", %{"friend_id" => friend_id}, socket) do def handle_event("delete", %{"friend_id" => friend_id}, socket) do
friend = Friend.get_by_id(friend_id) friend = Friend.get_by_id(friend_id)
{:noreply, {:noreply,
socket socket
|> put_flash(:error, "Deleted '#{friend.name}'.") |> put_flash(:error, "Deleted '#{friend.name}'.")
|> push_navigate(to: "/") |> push_navigate(to: "/")}
}
end
# Set page title
def title(socket, title) do
socket |> assign(:page_title, title)
end end
# Set variables on page: friend, changeset, relationships # Set variables on page: friend, changeset, relationships
def assign_friend(socket, friend) do def assign_friend(socket, friend) do
socket socket
|> assign(:friend, friend) |> assign(:friend, friend)
|> assign(:changeset, friend |> Friend.changeset) |> assign(:changeset, friend |> Friend.changeset())
|> assign(:relationships, friend.relationships) |> assign(:relationships, friend.relationships)
end end
@ -143,16 +150,11 @@ defmodule FriendsWeb.FriendLive.Friend do
|> assign(:relationships, friend.relationships) |> assign(:relationships, friend.relationships)
end end
# Set page_view variable
def page_view(socket, page) do
socket |> assign(:page_view, page)
end
# Route to the right sub-template in Components/Components.ex # Route to the right sub-template in Components/Components.ex
def content(assigns) do def content(assigns) do
~H""" ~H"""
<%= if @live_action != :new do %> <%= if @live_action != :new do %>
<%= FriendsWeb.FriendLive.Friend.menu(assigns) %> <%= FriendsWeb.FriendsLive.Friend.menu(assigns) %>
<% end %> <% end %>
<%= cond do %> <%= cond do %>
<% @live_action == :show -> %> <% @live_action == :show -> %>
@ -177,7 +179,7 @@ defmodule FriendsWeb.FriendLive.Friend do
<div class="hidden sm:tabs sm:mb-8"> <div class="hidden sm:tabs sm:mb-8">
<%= for page <- ["overview", "calendar", "relationships"] do %> <%= for page <- ["overview", "calendar", "relationships"] do %>
<% is_active = if(page == @page_view) do "tab-active" end %> <% is_active = if(page == @page_view) do "tab-active" end %>
<.link patch={"/friend/#{@friend.slug}?page=#{page}"} class={"font-bold sm:tab-lg flex-grow no-underline tab tab-lifted #{is_active}"}> <.link patch={"/friend/#{@friend.slug}/#{page}"} class={"font-bold sm:tab-lg flex-grow no-underline tab tab-lifted #{is_active}"}>
<%= page |> :string.titlecase() %> <%= page |> :string.titlecase() %>
</.link> </.link>
<% end %> <% end %>
@ -185,5 +187,4 @@ defmodule FriendsWeb.FriendLive.Friend do
""" """
end end
end end

View File

@ -1,5 +1,5 @@
<section class="row"> <section class="row">
<article class="column prose"> <article class="column prose">
<FriendsWeb.FriendLive.Friend.content friend={@friend} page_view={@page_view} changeset={@changeset} action={@action} live_action={@live_action}/> <FriendsWeb.FriendsLive.Friend.content friend={@friend} page_view={@page_view} changeset={@changeset} action={@action} live_action={@live_action}/>
</article> </article>
</section> </section>

View File

@ -1,24 +1,31 @@
"""
defmodule FriendsWeb.FriendLive.Show do defmodule FriendsWeb.FriendLive.Show do
use FriendsWeb, :live_view use FriendsWeb, :live_view
alias Friends.Friend
import FriendsWeb.LiveView def handle_params(attrs, token, socket) do
FriendsWeb.FriendLive.Friend.handle_params(attrs, token, socket)
def mount(params, %{"user_token" => user_token}, socket) do end
{:ok,
socket def mount(%{"slug" => slug} = attrs, token, socket) do
|> assign_current_user(user_token) friend = slug |> Friends.Friend.get_by_slug()
}
page =
if (attrs |> Map.get("page")) in ["overview", "calendar", "relationships"] do
attrs["page"]
else
"overview"
end end
def mount(%{"slug" => slug}, _token, socket) do
friend = slug |> Friends.Friend.get_by_slug
{:ok, {:ok,
socket socket
|> assign_current_user(nil) |> title(friend.name <> " - " <> (page |> :string.titlecase()))
|> page_view(page)
|> assign_current_user(token |> Map.get("user_token"))
|> assign(:friend, friend) |> assign(:friend, friend)
} |> assign(:changeset, %Friend{} |> Friend.changeset())
|> assign(:action, Routes.friend_path(socket, :update, friend.id))}
end
end end
"""
end

View File

@ -1 +1,5 @@
<h1><%=@friend.name %></h1> <section class="row">
<article class="column prose">
<FriendsWeb.FriendLive.Friend.content friend={@friend} page_view={@page_view} changeset={@changeset} action={@action} live_action={@live_action}/>
</article>
</section>

View File

@ -12,3 +12,8 @@
<% end %> <% end %>
</ul> </ul>
<%= if @current_user do %>
<div class="m-4 mt-16">
<.link href="/friends/new" class="btn btn-primary">Add Friend</.link>
</div>
<% end %>

View File

@ -1,6 +1,6 @@
defmodule FriendsWeb.ProfileLive.Form do defmodule FriendsWeb.ProfileLive.Form do
use FriendsWeb, :live_view use FriendsWeb, :live_view
import FriendsWeb.LiveView import FriendsWeb.LiveHelpers
def mount(%{}, %{"user_token" => token}, socket) do def mount(%{}, %{"user_token" => token}, socket) do
{:ok, {:ok,

View File

@ -0,0 +1,33 @@
defmodule FriendsWeb.LiveHelpers do
use FriendsWeb, :live_component
def assign_current_user(socket, user_token) do
user =
case user_token do
nil ->
nil
_moot ->
user_token
|> Friends.Accounts.get_user_by_session_token()
|> Friends.Repo.preload(:profile)
end
socket
|> assign(
:current_user,
user
)
end
# Set page title variable
def title(socket, title) do
socket
|> assign(:page_title, title)
end
# Set page_view variable
def page_view(socket, page) do
socket |> assign(:page_view, page)
end
end

View File

@ -1,24 +0,0 @@
defmodule FriendsWeb.LiveView do
use FriendsWeb, :live_component
def assign_current_user(socket, user_token) do
user = case user_token do
nil ->
nil
_moot ->
user_token
|> Friends.Accounts.get_user_by_session_token()
|> Friends.Repo.preload(:profile)
end
socket
|> assign(
:current_user,
user
)
end
def title(socket, title) do
socket
|> assign(:page_title, title)
end
end