1
0
Fork 0
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:
Thibaut Gorioux 2024-04-20 14:07:06 +02:00 committed by GitHub
parent c46662c99f
commit 5be1ced19e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 63 additions and 6 deletions

View 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

View file

@ -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

View file

@ -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)

View 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;
});
}
}

View file

@ -0,0 +1,5 @@
export class CurrenciesService {
get(id) {
return fetch(`/currencies/${id}.json`).then((response) => response.json());
}
}

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View file

@ -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