progress on modal functionality and form styling

This commit is contained in:
Adam Piontek 2021-03-03 16:07:59 -05:00
parent c7e12f7d49
commit be155d7b98
16 changed files with 417 additions and 308 deletions

View file

@ -4,16 +4,26 @@ defmodule Bones73kWeb.ModalComponent do
@impl true
def render(assigns) do
~L"""
<div id="<%= @id %>" class="phx-modal"
phx-capture-click="close"
phx-window-keydown="close"
<div id="<%= @id %>" class="modal fade"
phx-hook="BsModal"
phx-window-keydown="hide"
phx-key="escape"
phx-target="#<%= @id %>"
phx-page-loading>
<div class="phx-modal-content">
<%= live_patch raw("&times;"), to: @return_to, class: "phx-modal-close" %>
<%= live_component @socket, @component, @opts %>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><%= Keyword.get(@opts, :title, "Modal title") %></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<%= live_component @socket, @component, @opts %>
</div>
</div>
</div>
</div>
"""
@ -23,4 +33,9 @@ defmodule Bones73kWeb.ModalComponent do
def handle_event("close", _, socket) do
{:noreply, push_patch(socket, to: socket.assigns.return_to)}
end
@impl true
def handle_event("hide", _, socket) do
{:noreply, push_event(socket, "modal-please-hide", %{})}
end
end

View file

@ -5,12 +5,10 @@ defmodule Bones73kWeb.PropertyLive.FormComponent do
@impl true
def update(%{property: property} = assigns, socket) do
changeset = Properties.change_property(property)
{:ok,
socket
|> assign(assigns)
|> assign(:changeset, changeset)}
socket
|> assign(assigns)
|> assign(:changeset, Properties.change_property(property))
|> live_okreply()
end
@impl true
@ -30,10 +28,10 @@ defmodule Bones73kWeb.PropertyLive.FormComponent do
defp save_property(socket, :edit, property_params) do
case Properties.update_property(socket.assigns.property, property_params) do
{:ok, _property} ->
{:noreply,
socket
|> put_flash(:info, "Property updated successfully")
|> push_redirect(to: socket.assigns.return_to)}
socket
|> put_flash(:info, "Property updated successfully")
|> push_event("modal-please-hide", %{})
|> live_noreply()
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, :changeset, changeset)}
@ -46,10 +44,10 @@ defmodule Bones73kWeb.PropertyLive.FormComponent do
case Properties.create_property(property_params) do
{:ok, _property} ->
{:noreply,
socket
|> put_flash(:info, "Property created successfully")
|> push_redirect(to: socket.assigns.return_to)}
socket
|> put_flash(:info, "Property created successfully")
|> push_event("modal-please-hide", %{})
|> live_noreply()
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, changeset: changeset)}

View file

@ -1,22 +1,44 @@
<h2><%= @title %></h2>
<%= form_for @changeset, "#", [
phx_target: @myself,
phx_change: "validate",
phx_submit: "save"
], fn f -> %>
<%= f = form_for @changeset, "#",
id: "property-form",
phx_target: @myself,
phx_change: "validate",
phx_submit: "save" %>
<%= label f, :name %>
<%= text_input f, :name %>
<%= error_tag f, :name %>
<div class="mb-3" phx-feedback-for="<%= input_id(f, :name)%>">
<%= label f, :name, class: "form-label" %>
<div class="input-group has-validation">
<%= text_input f, :name,
class: input_class(f, :name, "form-control"),
aria_describedby: error_id(f, :name)
%>
<%= error_tag f, :name %>
</div>
</div>
<%= label f, :price %>
<%= number_input f, :price, step: "any" %>
<%= error_tag f, :price %>
<div class="mb-3" phx-feedback-for="<%= input_id(f, :price)%>">
<%= label f, :price, class: "form-label" %>
<div class="input-group has-validation">
<%= number_input f, :price,
class: input_class(f, :price, "form-control"),
step: "any",
aria_describedby: error_id(f, :price)
%>
<%= error_tag f, :price %>
</div>
</div>
<%= label f, :description %>
<%= textarea f, :description %>
<%= error_tag f, :description %>
<div class="mb-3" phx-feedback-for="<%= input_id(f, :description)%>">
<%= label f, :description, class: "form-label" %>
<div class="input-group has-validation">
<%= textarea f, :description,
class: input_class(f, :description, "form-control"),
aria_describedby: error_id(f, :description)
%>
<%= error_tag f, :description %>
</div>
</div>
<%= submit "Save", phx_disable_with: "Saving..." %>
</form>
<%= submit "Save", phx_disable_with: "Saving...", class: "btn btn-primary" %>
<% end %>

View file

@ -30,7 +30,7 @@ defmodule Bones73kWeb.UserLive.Registration do
@impl true
def handle_event("validate", %{"user" => user_params}, socket) do
cs = Accounts.change_user_registration(%User{}, user_params)
{:noreply, assign(socket, changeset: %{cs | action: :update})}
{:noreply, assign(socket, changeset: %{cs | action: :validate})}
end
@impl true

View file

@ -19,7 +19,7 @@ defmodule Bones73kWeb.UserLive.ResetPassword do
@impl true
def handle_event("validate", %{"user" => user_params}, socket) do
cs = Accounts.change_user_password(socket.assigns.user, user_params)
{:noreply, socket |> assign(changeset: %{cs | action: :update})}
{:noreply, socket |> assign(changeset: %{cs | action: :validate})}
end
def handle_event("save", %{"user" => user_params}, socket) do
@ -34,7 +34,7 @@ defmodule Bones73kWeb.UserLive.ResetPassword do
{:noreply,
socket
|> put_flash(:error, "Please check the errors below.")
|> assign(changeset: %{changeset | action: :update})}
|> assign(changeset: changeset)}
end
end
end

View file

@ -20,7 +20,7 @@ defmodule Bones73kWeb.UserLive.Settings.Email do
@impl true
def handle_event("validate", %{"user" => user_params}, socket) do
cs = get_changeset(socket.assigns.current_user, user_params)
{:noreply, assign(socket, changeset: %{cs | action: :update})}
{:noreply, assign(socket, changeset: %{cs | action: :validate})}
end
# user_settings_path GET /users/settings/confirm_email/:token Bones73kWeb.UserSettingsController :confirm_email

View file

@ -30,6 +30,7 @@
<%= icon_div @socket, "bi-lock", [class: "icon fs-5"] %>
</span>
<%= password_input f, :current_password,
value: input_value(f, :current_password),
class: "form-control",
required: true,
aria_describedby: error_id(f, :current_password)

View file

@ -30,7 +30,7 @@ defmodule Bones73kWeb.UserLive.Settings.Password do
@impl true
def handle_event("validate", %{"user" => user_params}, socket) do
cs = get_changeset(socket.assigns.current_user, user_params)
{:noreply, assign(socket, changeset: %{cs | action: :update})}
{:noreply, assign(socket, changeset: %{cs | action: :validate})}
end
@impl true

View file

@ -44,6 +44,7 @@
<%= icon_div @socket, "bi-lock", [class: "icon fs-5"] %>
</span>
<%= password_input f, :current_password,
value: input_value(f, :current_password),
class: "form-control",
required: true,
aria_describedby: error_id(f, :current_password)

View file

@ -11,27 +11,31 @@
<div class="border-4 border-dashed border-gray-200 rounded-lg h-96"></div>
</div> %>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatibus dolore sunt quia aperiam sint id
reprehenderit? Dolore incidunt alias inventore accusantium nulla optio, ducimus eius aliquam hic, pariatur
voluptate distinctio.
Praesent velit justo, auctor ut nibh id, fermentum eleifend nunc. Cras sed purus dignissim, ornare elit et, ultrices elit. Sed quis neque consequat, laoreet ante a, hendrerit elit. Maecenas dapibus sed nulla vitae consectetur. Duis sollicitudin augue nisl, et rhoncus enim tempor at. Fusce scelerisque sollicitudin purus sit amet iaculis. Phasellus lacinia mi ut laoreet accumsan. Sed sagittis erat nec sem placerat, ut volutpat neque porttitor. Suspendisse tempor mauris vel mollis sagittis. In ut laoreet arcu. Duis sed felis in dui imperdiet luctus nec faucibus sem. Donec commodo urna ut enim fringilla, quis lacinia ligula malesuada. Quisque feugiat fermentum pretium. Integer sed porttitor lacus, sed bibendum diam. Aliquam dapibus neque et pharetra interdum.
</p>
<!-- /End replace -->
</div>
<%# <div class="columns is-centered">
<div class="column is-three-fifths">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
Launch demo modal
</button>
<div class="title is-4">
<span>Other Page</span>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Aliquam ultrices elit purus, eget dignissim orci pulvinar id. Curabitur tincidunt, ligula eu condimentum porttitor, nibh sapien scelerisque urna, nec cursus nisi nisi a neque. Mauris hendrerit orci blandit, suscipit ante nec, porttitor neque. Nunc.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
<div class="subtitle">With a subtitle no less!</div>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatibus dolore sunt quia aperiam sint id
reprehenderit? Dolore incidunt alias inventore accusantium nulla optio, ducimus eius aliquam hic, pariatur
voluptate distinctio.
</p>
</div>
</div> %>
</div>

View file

@ -30,37 +30,13 @@ defmodule Bones73kWeb.ErrorHelpers do
def error_id(input_id) when is_binary(input_id), do: "#{input_id}_feedback"
def input_class(form, field, classes \\ "") do
case field_status(form, field) do
:ok -> "#{classes} is-valid"
:error -> "#{classes} is-invalid"
_ -> classes
end
end
defp field_status(form, field) do
case field_has_data?(form, field) do
true ->
form.errors
|> Keyword.get_values(field)
|> Enum.empty?()
|> case do
true -> :ok
false -> :error
case form.source.action do
nil -> classes
_ ->
case Keyword.has_key?(form.errors, field) do
true -> "#{classes} is-invalid"
_ -> "#{classes} is-valid"
end
false ->
:default
end
end
defp field_has_data?(form, field) when is_atom(field),
do: field_has_data?(form, Atom.to_string(field))
defp field_has_data?(form, field) when is_binary(field) do
case Map.get(form.params, field) do
nil -> false
"" -> false
_ -> true
end
end