rauversion/rauversion-ror

View on GitHub
app/helpers/tailwind_form_builder.rb

Summary

Maintainability
A
3 hrs
Test Coverage
class TailwindFormBuilder < ActionView::Helpers::FormBuilder
  # include ActionView::Helpers::TagHelper
  # include ActionView::Context

  def hint(attribute, options)
    return "" if options[:hint].blank? && hint_tr(attribute).blank?

    @template.tag.div(class: "text-gray-500 text-xs") do
      options[:hint] || hint_tr(attribute)
    end
  end

  def error(attribute, object)
    return if object.blank?
    return "" if object.errors[attribute.to_sym].blank?

    @template.tag.div(class: "text-red-500 text-xs italic") do
      object.errors[attribute.to_sym].uniq.join(", ").to_s
    end
  end

  def field_details(attribute, object, options)
    content = (error(attribute, object) + hint(attribute, options)).html_safe
    return "" if content.blank?

    @template.tag.div(class: "mt-1 text-xs text-gray-500 dark:text-gray-100") do
      (error(attribute, object) + hint(attribute, options)).html_safe
    end
  end

  def text_field(attribute, options = {})
    @template.content_tag :div, class: "w-full sm:w-full" do
      [
        options[:label].is_a?(FalseClass) ? @template.content_tag(:div) : @template.label_tag(tr(options[:label] || attribute), nil),
        super(attribute, options.reverse_merge(class: "input")),
        field_details(attribute, object, options)
      ].join.html_safe
    end
  end

  def email_field(attribute, options = {})
    @template.content_tag :div, class: "w-full sm:w-full" do
      [
        options[:label].is_a?(FalseClass) ? @template.content_tag(:div) : @template.label_tag(tr(options[:label] || attribute), nil),
        super(attribute, options.reverse_merge(class: "input")),
        field_details(attribute, object, options)
      ].join.html_safe
    end
  end

  def password_field(attribute, options = {})
    @template.content_tag :div, class: "w-full sm:w-full" do
      [
        options[:label].is_a?(FalseClass) ? @template.content_tag(:div) : @template.label_tag(tr(options[:label] || attribute), nil),
        super(attribute, options.reverse_merge(class: "input")),
        field_details(attribute, object, options)
      ].join.html_safe
    end
  end

  def number_field(attribute, options = {})
    @template.tag.div(class: "w-full sm:w-full py-2") do
      [
        options[:label].is_a?(FalseClass) ? @template.content_tag(:div) : @template.label_tag(tr(options[:label] || attribute), nil),
        super(attribute, options.reverse_merge(class: "input")),
        field_details(attribute, object, options)
      ].join.html_safe
    end
  end

  def link_field(attribute, options = {})
    @template.tag.div(class: "w-full sm:w-full py-2") do
      @template.label_tag(tr(options[:label] || attribute), nil) +
        @template.tag.div(class: "flex") do
          @template.tag.span(class: "inline-flex items-center px-3 text-sm text-gray-900 dark:bg-gray-900 bg-gray-200 border border-r-0 border-gray-300 rounded-l-md dark:bg-gray-600 dark:text-gray-400 dark:border-gray-600") do
            options[:link]
          end +
            @template.tag.input(name: "#{object.class.table_name.singularize}[#{attribute}]", value: object.send(attribute), class: "rounded-none rounded-r-lg bg-gray-50 border text-gray-900 focus:ring-blue-500 focus:border-blue-500 block flex-1 min-w-0 w-full text-sm border-gray-300 p-2.5  dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500")
        end + field_details(attribute, object, options)
    end
  end

  def right_indicator_field(attribute, options = {})
    @template.tag.div(class: "w-full sm:w-full py-2") do
      @template.label_tag(tr(options[:label] || attribute), nil) +
        @template.tag.div(class: "flex") do
          @template.tag.input(name: "#{object.class.table_name.singularize}[#{attribute}]", value: object.send(attribute), class: "rounded-none rounded-l-lg bg-gray-50 border text-gray-900 focus:ring-blue-500 focus:border-blue-500 block flex-1 min-w-0 w-full text-sm border-gray-300 p-2.5  dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500") +
            @template.tag.span(class: "inline-flex items-center px-3 text-sm text-gray-900 dark:bg-gray-900 bg-gray-200 border border-l-0 border-gray-300 rounded-r-md dark:bg-gray-600 dark:text-gray-400 dark:border-gray-600") do
              options[:link]
            end
        end + field_details(attribute, object, options)
    end
  end

  def text_area(attribute, options = {})
    @template.tag.div(class: "w-full sm:w-full py-2") do
      @template.label_tag(tr(options[:label] || attribute), nil) +
        super(attribute, options.reverse_merge(class: "block w-full rounded-md border-0 py-1.5 bg-muted text-gray-900 shadow-sm ring-1 ring-inset ring-subtle placeholder:text-subtle focus:ring-2 focus:ring-inset focus:ring-brand-600 sm:text-sm sm:leading-6")) +
        field_details(attribute, object, options)
    end
  end

  # def select_field(object_name, method_name, template_object, options = {})
  #  puts options
  #  @template.tag.div(class: "w-full sm:w-full py-2", "data-controller": "select") do
  #    @template.label_tag(tr(options[:label] || object_name), nil) +
  #      super(object_name, method_name, template_object, options.reverse_merge(class: "select")) +
  #      @template.tag.div(data: {"select-target": "holder"}) { "" } +
  #      field_details(object_name, object, options)
  #  end
  # end

  def color_fieldssss(object_name, method = "", options = {})
    Tags::ColorField.new(object_name, method, self, options).render
  end

  def div_radio_button(method, tag_value, options = {})
    @template.tag.div(@template.radio_button(
                        @object_name, method, tag_value, objectify_options(options)
                      ))
  end

  def radio_button(method, value, options = {})
    options.merge!(class: "form-radio mr-2 h-4 w-4 text-indigo-600 transition duration-150 ease-in-out") unless options.has_key?(:class)

    label_content = if options[:label] == false
                      ""
                    else
                      @template.label_tag(
                        tr(options[:label] || method), nil,
                        class: "block text-sm leading-5 text-muted"
                      )
                    end

    @template.tag.div(class: "inline-flex items-center #{options[:wrapper_class]}") do
      super + label_content +
        @template.tag.div(class: "text-sm font-normal leading-5 text-muted") do
          field_details(method, object, options)
        end
    end
  end

  def check_box(method, options = {}, checked_value = "1", unchecked_value = "0")
    # Conditionally build the label if options[:label] is not false
    info = ""
    unless options[:label] == false
      info = @template.label_tag(
        tr(options[:label] || method), nil,
        class: "block text-gray-500 dark:text-white text-sm font-normal"
      ) + field_details(method, object, options)
    end

    # Merge in default class unless a specific class has been provided in options
    options.merge!(class: "self-center mt-1-- mr-2 form-checkbox h-4 w-4 text-indigo-600 transition duration-150 ease-in-out") unless options.key?(:class)

    # Create the checkbox and, conditionally, its label
    @template.tag.div(class: "flex items-center") do
      @template.check_box(
        @object_name, method, objectify_options(options), checked_value, unchecked_value
      ) + (info.present? ? @template.tag.div(class: "flex-col items-center") { info } : "".html_safe)
    end
  end

  def uploader_field(method, tag_value = "", options = {})
    @template.tag.div(class: "overflow-hidden relative w-64 mt-4 mb-4") do
      @template.tag.div("data-controller": "upload-preview") do
        @template.image_tag("logo.png", width: "100px", hight: "100px", "data-upload-preview-target": "output") +
          @template.tag.div(class: "") do
            @template.label_tag(method) +
              @template.file_field_tag(method,
                "data-action": "upload-preview#readURL",
                "data-upload-preview-target": "input",
                class: "form-control-file photo_upload cursor-pointer absolute block py-2 px-4 w-full opacity-0 pin-r pin-t")
          end
      end +
        %(
                  <button class="bg-gray-300 hover:bg-blue-light text-white font-bold py-2 px-4 w-full inline-flex items-center">
                      <svg fill="#FFF" height="18" viewBox="0 0 24 24" width="18" xmlns="http://www.w3.org/2000/svg">
                          <path d="M0 0h24v24H0z" fill="none"/>
                              <path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"/>
                      </svg>
                      <span class="ml-2">Upload Document</span>
                  </button>
              ).html_safe
    end
  end

  def file_preview_field(method, tag_value = "", options = {})
    @template.content_tag :div, class: "overflow-hidden relative w-64 mt-4 mb-4" do
      @template.content_tag :div, "data-controller": "image-preview" do
        [
          file_field(method, options.merge(data: {action: "change->image-preview#preview", "image-preview-target": "file"}, class: "hidden")),
          @template.image_tag(tag_value, data: {"image-preview-target": "output"}, class: "p-4 w-[100px]"),
          label(method, "Upload file", class: "rounded-full cursor-pointer bg-brand-600 px-4 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-brand-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand-600")
        ].join.html_safe
      end
    end
  end

  def tr(name)
    I18n.t("activerecord.forms.#{@object_name}.#{name}.label", default: name.to_s)
    # I18n.t(name, scope: [:activerecord, :attributes, @object_name], :default => name.to_s)
  end

  def hint_tr(name)
    I18n.t("activerecord.forms.#{@object_name}.#{name}.hint", default: nil)
  end
end