defmodule Legendary.CoreWeb.Helpers do @moduledoc """ HTML helpers for our styled (Tailwind) forms. """ use Phoenix.HTML import Phoenix.Controller, only: [get_flash: 2] import Legendary.CoreWeb.ErrorHelpers def has_role?(conn = %Plug.Conn{}, role) do conn |> Pow.Plug.current_user() |> Legendary.Auth.Roles.has_role?(role) end def changeset_error_block(changeset) do ~E""" <%= if changeset.action do %>

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

<% end %> """ end def flash_block(conn) do ~E"""
<%= [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 ~E"""
<%= 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) ~E""" <%= content_tag :div, class: Enum.join([classes, error_classes], " ") do %> <%= apply(Phoenix.HTML.Form, input_helper, [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:shadow-outline 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:shadow-outline w-full" def styled_button(text) do ~E""" <%= submit text, 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 ~E""" <%= 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 paginator(first..last, current, callback) do [first, current - 1, current, current + 1, last] |> Enum.sort() |> Enum.filter(& &1 >= first) |> Enum.filter(& &1 <= last) |> Enum.dedup() |> Enum.map(& callback.(first..last, &1)) 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 ~E"""

<%= title %>

<%= changeset_error_block(changeset) %>
<%= content %>
""" end def floating_page_wrapper(do: content) do ~E"""
<%= 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