mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-19 05:09:38 +02:00
Shared money input should respond to change in currency (#654)
* Add step method to currency * Change amount placeholder and step, when currency select change * Lint * Add test with auth * Extract request to specific service
This commit is contained in:
parent
c46662c99f
commit
5be1ced19e
10 changed files with 63 additions and 6 deletions
6
app/controllers/currencies_controller.rb
Normal file
6
app/controllers/currencies_controller.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
class CurrenciesController < ApplicationController
|
||||
def show
|
||||
@currency = Money::Currency.all_instances.find { |currency| currency.iso_code == params[:id] }
|
||||
render json: { step: @currency.step, placeholder: Money.new(0, @currency).format }
|
||||
end
|
||||
end
|
|
@ -33,11 +33,13 @@ class ApplicationFormBuilder < ActionView::Helpers::FormBuilder
|
|||
|
||||
readonly_currency = options[:readonly_currency] || false
|
||||
|
||||
currency = money&.currency || Money.default_currency
|
||||
default_options = {
|
||||
class: "form-field__input",
|
||||
value: money&.amount,
|
||||
placeholder: Money.new(0, money&.currency || Money.default_currency).format,
|
||||
step: "0.01" # Not all currencies have 2 decimal places
|
||||
"data-money-field-target" => "amount",
|
||||
placeholder: Money.new(0, currency).format,
|
||||
step: currency.step
|
||||
}
|
||||
|
||||
merged_options = default_options.merge(options)
|
||||
|
@ -45,11 +47,11 @@ class ApplicationFormBuilder < ActionView::Helpers::FormBuilder
|
|||
grouped_options = currency_options_for_select
|
||||
selected_currency = money&.currency&.iso_code
|
||||
|
||||
@template.form_field_tag do
|
||||
@template.form_field_tag data: { controller: "money-field" } 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")
|
||||
grouped_select(money_currency_method, grouped_options, { selected: selected_currency, disabled: readonly_currency }, class: "ml-auto form-field__input w-fit pr-8", data: { "money-field-target" => "currency", action: "change->money-field#handleCurrencyChange" })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module FormsHelper
|
||||
def form_field_tag(&)
|
||||
tag.div class: "form-field", &
|
||||
def form_field_tag(options = {}, &block)
|
||||
options[:class] = [ "form-field", options[:class] ].compact.join(" ")
|
||||
tag.div **options, &block
|
||||
end
|
||||
|
||||
def radio_tab_tag(form:, name:, value:, label:, icon:, checked: false, disabled: false)
|
||||
|
|
20
app/javascript/controllers/money_field_controller.js
Normal file
20
app/javascript/controllers/money_field_controller.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { Controller } from "@hotwired/stimulus";
|
||||
import { CurrenciesService } from "services/currencies_service";
|
||||
|
||||
// Connects to data-controller="money-field"
|
||||
// when currency select change, update the input value with the correct placeholder and step
|
||||
export default class extends Controller {
|
||||
static targets = ["amount", "currency"];
|
||||
|
||||
handleCurrencyChange() {
|
||||
const selectedCurrency = event.target.value;
|
||||
this.updateAmount(selectedCurrency);
|
||||
}
|
||||
|
||||
updateAmount(currency) {
|
||||
(new CurrenciesService).get(currency).then((data) => {
|
||||
this.amountTarget.placeholder = data.placeholder;
|
||||
this.amountTarget.step = data.step;
|
||||
});
|
||||
}
|
||||
}
|
5
app/javascript/services/currencies_service.js
Normal file
5
app/javascript/services/currencies_service.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
export class CurrenciesService {
|
||||
get(id) {
|
||||
return fetch(`/currencies/${id}.json`).then((response) => response.json());
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
|
|||
pin "@hotwired/stimulus", to: "stimulus.min.js"
|
||||
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
|
||||
pin_all_from "app/javascript/controllers", under: "controllers"
|
||||
pin_all_from "app/javascript/services", under: "services", to: "services"
|
||||
pin "@github/hotkey", to: "@github--hotkey.js" # @3.1.0
|
||||
|
||||
# Custom namespace for local files
|
||||
|
|
|
@ -46,6 +46,8 @@ Rails.application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
resources :currencies, only: %i[show]
|
||||
|
||||
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
|
||||
# Can be used by load balancers and uptime monitors to verify that the app is live.
|
||||
get "up" => "rails/health#show", as: :rails_health_check
|
||||
|
|
|
@ -58,6 +58,10 @@ class Money::Currency
|
|||
@default_precision = currency_data["default_precision"]
|
||||
end
|
||||
|
||||
def step
|
||||
(1.0/10**default_precision)
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
return nil unless other.is_a?(Money::Currency)
|
||||
@iso_code <=> other.iso_code
|
||||
|
|
12
test/controllers/currencies_controller_test.rb
Normal file
12
test/controllers/currencies_controller_test.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
require "test_helper"
|
||||
|
||||
class CurrenciesControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
sign_in @user = users(:family_admin)
|
||||
end
|
||||
|
||||
test "should show currency" do
|
||||
get currency_url(id: "EUR", format: :json)
|
||||
assert_response :success
|
||||
end
|
||||
end
|
|
@ -46,4 +46,8 @@ class Money::CurrencyTest < ActiveSupport::TestCase
|
|||
assert_equal "12", value4.cents_str(2)
|
||||
assert_equal "123", value4.cents_str(3)
|
||||
end
|
||||
|
||||
test "step returns the smallest value of the currency" do
|
||||
assert_equal 0.01, @currency.step
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue