defmodule Legendary.CoreWeb.Helpers do @moduledoc """ HTML helpers for our styled (Tailwind) forms. """ use Phoenix.HTML use Phoenix.Component import Phoenix.Controller, only: [get_flash: 2] import ShorterMaps import Legendary.CoreWeb.ErrorHelpers defdelegate current_user(a), to: Legendary.AuthWeb.Helpers defdelegate has_role?(a, b), to: Legendary.AuthWeb.Helpers def changeset_error_block(changeset) do assigns = ~M{changeset} ~H""" <%= if changeset.action do %>

Oops, something went wrong! Please check the errors below.

<% end %> """ end def flash_block(conn) do assigns = ~M{conn} ~H"""
<%= [info: "green", error: "red"] |> Enum.map(fn {level, color} -> %> <%= if get_flash(conn, level) do %>
<%= get_flash(conn, level) %>
×
<% end %> <% end) %>
""" end def styled_input(f, field, opts \\ [], options \\ nil, block_list \\ []) do {content, _} = Keyword.pop(block_list, :do, "") {type, rest_opts} = Keyword.pop(opts, :type, input_type(f, field)) {classes, rest_opts} = Keyword.pop(rest_opts, :class, default_classes_for_type(type)) {label_text, rest_opts} = Keyword.pop(rest_opts, :label) {input_helper, _rest_opts} = Keyword.pop(rest_opts, :input_helper, input_type(f, field)) error_classes = if Keyword.get_values(f.errors || [], field) |> Enum.any?() do " border border-red-500" else "" end assigns = ~M{classes, content, error_classes, f, field, input_helper, label_text, type, options, opts} ~H"""
<%= if label_text do %> <%= label(f, field, label_text, class: "block uppercase text-gray-700 text-xs font-bold mb-2") %> <% else %> <%= label(f, field, class: "block uppercase text-gray-700 text-xs font-bold mb-2") %> <% end %> <%= do_styled_input_tag(type, input_helper, f, field, options, opts, classes, error_classes) %> <%= content %> <%= error_tag(f, field, class: "text-red-500 italic") %>
""" end defp do_styled_input_tag(type, _input_helper, f, field, nil, opts, classes, error_classes) when type in [:date_select, :time_select, :datetime_select] do default_child_opts = [ month: [ class: "appearance-none border-b-2 border-dashed", options: [ {"Jan", "1"}, {"Feb", "2"}, {"Mar", "3"}, {"Apr", "4"}, {"May", "5"}, {"Jun", "6"}, {"Jul", "7"}, {"Aug", "8"}, {"Sep", "9"}, {"Oct", "10"}, {"Nov", "11"}, {"Dec", "12"} ] ], day: [class: "appearance-none border-b-2 border-dashed"], year: [class: "appearance-none border-b-2 border-dashed"], hour: [class: "appearance-none border-b-2 border-dashed"], minute: [class: "appearance-none border-b-2 border-dashed"], second: [class: "appearance-none border-b-2 border-dashed"] ] {child_opts, rest_opts} = Keyword.pop(opts, :child_opts, default_child_opts) assigns = ~M{child_opts, classes, error_classes, f, field, rest_opts, type} ~H""" <%= content_tag :div, class: Enum.join([classes, error_classes], " ") do %> <%= apply(Phoenix.HTML.Form, type, [f, field, rest_opts ++ child_opts]) %> <% end %> """ end defp do_styled_input_tag(_type, input_helper, f, field, nil, opts, classes, error_classes) do apply(Phoenix.HTML.Form, input_helper, [ f, field, opts ++ [class: Enum.join([classes, error_classes], " ")] ]) end defp do_styled_input_tag(_type, input_helper, f, field, options, opts, classes, error_classes) do apply(Phoenix.HTML.Form, input_helper, [ f, field, options, opts ++ [class: Enum.join([classes, error_classes], " ")] ]) end defp default_classes_for_type(type) when type in [:date_select, :time_select, :datetime_select] do "bg-white shadow rounded p-3" end defp default_classes_for_type(:checkbox), do: "appearance-none h-10 w-10 bg-white checked:bg-gray-500 rounded shadow focus:outline-none focus:ring text-white text-xl font-bold mb-2" defp default_classes_for_type(_), do: "px-4 py-3 placeholder-gray-400 text-gray-700 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full" def styled_button(text, opts \\ []) do assigns = ~M{text, opts} ~H""" <%= submit( text, opts ++ [ class: "bg-gray-900 text-white active:bg-gray-700 text-sm font-bold uppercase px-4 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 w-full" ] ) %> """ end def styled_button_link(text, opts) do assigns = ~M{text, opts} ~H""" <%= link( text, opts ++ [ class: "bg-gray-900 text-white active:bg-gray-700 text-sm font-bold uppercase px-4 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 w-full" ] ) %> """ end def styled_button_live_patch(text, opts) do {to, opts} = Keyword.pop(opts, :to, "#") assigns = ~M{text, opts, to} ~H""" <.link patch={@to} {opts} class="bg-gray-900 text-white active:bg-gray-700 text-sm font-bold uppercase px-4 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 w-full" > <%= text %> """ end def styled_button_live_redirect(text, opts) do {to, opts} = Keyword.pop(opts, :to, "#") assigns = ~M{text, opts, to} ~H""" <.link navigate={@to} {opts} class="bg-gray-900 text-white active:bg-gray-700 text-sm font-bold uppercase px-4 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 w-full" > <%= text %> """ end slot(:inner_block, required: true) def styled_button_link(assigns) do ~H""" <.link {assigns} class="bg-gray-900 text-white active:bg-gray-700 text-sm font-bold uppercase px-4 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 w-full" > <%= render_slot(@inner_block) %> """ end def paginator(~M{first, current_page, last} = assigns) do pages = [first, current_page - 1, current_page, current_page + 1, last] |> Enum.sort() |> Enum.filter(&(&1 >= first && &1 <= last)) |> Enum.dedup() assigns = assigns |> Map.put(:pages, pages) ~H""" <%= for page_number <- @pages do %> <%= @callback.(@first..@last, page_number) %> <% end %> """ end def group_rounding_class( first..last, current, [first_class, middle_class, last_class] \\ ["rounded-l", "", "rounded-r"] ) do cond do first == last -> "#{first_class} #{last_class}" current == first -> first_class current == last -> last_class true -> middle_class end end @spec floating_form(any, atom | %{action: any}, [{:do, any}, ...]) :: {:safe, [...]} def floating_form(title, changeset, do: content) do assigns = ~M{changeset, content, title} ~H"""

<%= title %>

<%= changeset_error_block(changeset) %>
<%= content %>
""" end def floating_page_wrapper(do: content) do assigns = ~M{content} ~H"""
<%= content %>
""" end def pow_extension_enabled?(extension) do {extensions, _rest} = Application.get_env(:core, :pow) |> Keyword.pop(:extensions, []) Enum.any?(extensions, &(&1 == extension)) end end