mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-19 05:09:38 +02:00
125 lines
4.6 KiB
Ruby
125 lines
4.6 KiB
Ruby
class ApplicationFormBuilder < ActionView::Helpers::FormBuilder
|
|
def initialize(object_name, object, template, options)
|
|
options[:html] ||= {}
|
|
options[:html][:class] ||= "space-y-4"
|
|
|
|
super(object_name, object, template, options)
|
|
end
|
|
|
|
(field_helpers - [ :label, :check_box, :radio_button, :fields_for, :fields, :hidden_field, :file_field ]).each do |selector|
|
|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
|
def #{selector}(method, options = {})
|
|
default_options = { class: "form-field__input" }
|
|
merged_options = default_options.merge(options)
|
|
|
|
return super(method, merged_options) unless options[:label]
|
|
|
|
@template.form_field_tag do
|
|
label(method, *label_args(options)) +
|
|
super(method, merged_options.except(:label))
|
|
end
|
|
end
|
|
RUBY_EVAL
|
|
end
|
|
|
|
# See `Monetizable` concern, which adds a _money suffix to the attribute name
|
|
# For a monetized field, the setter will always be the attribute name without the _money suffix
|
|
def money_field(method, options = {})
|
|
money = @object.send(method)
|
|
raise ArgumentError, "The value of #{method} is not a Money object" unless money.is_a?(Money) || money.nil?
|
|
|
|
money_amount_method = method.to_s.chomp("_money").to_sym
|
|
money_currency_method = :currency
|
|
|
|
readonly_currency = options[:readonly_currency] || false
|
|
|
|
default_options = {
|
|
class: "form-field__input",
|
|
value: money&.amount,
|
|
placeholder: Money.new(0, money&.currency || Money.default_currency).format
|
|
}
|
|
|
|
merged_options = default_options.merge(options)
|
|
|
|
grouped_options = currency_options_for_select
|
|
selected_currency = money&.currency&.iso_code
|
|
|
|
@template.form_field_tag do
|
|
(label(method, *label_args(options)).to_s if options[:label]) +
|
|
@template.tag.div(class: "flex items-center") do
|
|
number_field(money_amount_method, merged_options.except(:label)) +
|
|
grouped_select(money_currency_method, grouped_options, { selected: selected_currency, disabled: readonly_currency }, class: "ml-auto form-field__input w-fit pr-8")
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
def grouped_select(method, grouped_choices, options = {}, html_options = {})
|
|
default_options = { class: "form-field__input" }
|
|
merged_html_options = default_options.merge(html_options)
|
|
|
|
label_html = label(method, *label_args(options)).to_s if options[:label]
|
|
select_html = @template.grouped_collection_select(@object_name, method, grouped_choices, :last, :first, :last, :first, options, merged_html_options)
|
|
|
|
@template.content_tag(:div, class: "flex items-center") do
|
|
label_html.to_s.html_safe + select_html
|
|
end
|
|
end
|
|
|
|
def select(method, choices, options = {}, html_options = {})
|
|
default_options = { class: "form-field__input" }
|
|
merged_options = default_options.merge(html_options)
|
|
|
|
return super(method, choices, options, merged_options) unless options[:label]
|
|
|
|
@template.form_field_tag do
|
|
label(method, *label_args(options)) +
|
|
super(method, choices, options, merged_options.except(:label))
|
|
end
|
|
end
|
|
|
|
def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
|
|
default_options = { class: "form-field__input" }
|
|
merged_options = default_options.merge(html_options)
|
|
|
|
return super(method, collection, value_method, text_method, options, merged_options) unless options[:label]
|
|
|
|
@template.form_field_tag do
|
|
label(method, *label_args(options)) +
|
|
super(method, collection, value_method, text_method, options, merged_options.except(:label))
|
|
end
|
|
end
|
|
|
|
def submit(value = nil, options = {})
|
|
value, options = nil, value if value.is_a?(Hash)
|
|
default_options = { class: "form-field__submit" }
|
|
merged_options = default_options.merge(options)
|
|
super(value, merged_options)
|
|
end
|
|
|
|
private
|
|
|
|
def currency_options_for_select
|
|
popular_currencies = Money::Currency.popular.map { |currency| [ currency.iso_code, currency.iso_code ] }
|
|
all_currencies = Money::Currency.all_instances.map { |currency| [ currency.iso_code, currency.iso_code ] }
|
|
all_other_currencies = all_currencies.reject { |c| popular_currencies.map(&:last).include?(c.last) }.sort_by(&:last)
|
|
|
|
{
|
|
I18n.t("accounts.new.currency.popular") => popular_currencies,
|
|
I18n.t("accounts.new.currency.all_others") => all_other_currencies
|
|
}
|
|
end
|
|
|
|
def label_args(options)
|
|
case options[:label]
|
|
when Array
|
|
options[:label]
|
|
when String
|
|
[ options[:label], { class: "form-field__label" } ]
|
|
when Hash
|
|
[ nil, options[:label] ]
|
|
else
|
|
[ nil, { class: "form-field__label" } ]
|
|
end
|
|
end
|
|
end
|