diff --git a/app/javascript/controllers/onboarding_controller.js b/app/javascript/controllers/onboarding_controller.js index 7e410d916..19c3c9ee8 100644 --- a/app/javascript/controllers/onboarding_controller.js +++ b/app/javascript/controllers/onboarding_controller.js @@ -2,16 +2,20 @@ import { Controller } from "@hotwired/stimulus"; // Connects to data-controller="onboarding" export default class extends Controller { - static targets = ["nameField", "monikerRadio"] + static targets = ["nameField", "monikerRadio", "countryField", "currencyField"] static values = { householdNameLabel: String, householdNamePlaceholder: String, groupNameLabel: String, - groupNamePlaceholder: String + groupNamePlaceholder: String, + country: String, + countryCurrencies: Object, + currencyOverride: Boolean } connect() { this.updateNameFieldForCurrentMoniker(); + this.applyBrowserLocaleDefaults(); } setLocale(event) { @@ -30,6 +34,43 @@ export default class extends Controller { document.documentElement.setAttribute("data-theme", event.target.value); } + applyBrowserLocaleDefaults() { + const browserCountry = this.browserCountry(); + + if (this.hasCountryFieldTarget && browserCountry && this.countryFieldTarget.value === "US" && this.hasCountryOption(browserCountry)) { + this.countryFieldTarget.value = browserCountry; + } + + if (this.hasCurrencyFieldTarget && !this.currencyOverrideValue) { + const country = this.countryValue || (this.hasCountryFieldTarget ? this.countryFieldTarget.value : null) || browserCountry; + const currency = this.currencyForCountry(country); + + if (currency && this.hasCurrencyOption(currency)) { + this.currencyFieldTarget.value = currency; + } + } + } + + browserCountry() { + try { + return new Intl.Locale(navigator.language).maximize().region; + } catch (_error) { + return null; + } + } + + currencyForCountry(country) { + return (this.hasCountryCurrenciesValue ? this.countryCurrenciesValue : {})[country?.toUpperCase()]; + } + + hasCountryOption(country) { + return Array.from(this.countryFieldTarget.options).some((option) => option.value === country); + } + + hasCurrencyOption(currency) { + return Array.from(this.currencyFieldTarget.options).some((option) => option.value === currency); + } + updateNameFieldForCurrentMoniker(event = null) { if (!this.hasNameFieldTarget) { return; diff --git a/app/models/family.rb b/app/models/family.rb index b0f7f2ec2..c2ae27dca 100644 --- a/app/models/family.rb +++ b/app/models/family.rb @@ -151,7 +151,28 @@ class Family < ApplicationRecord before_validation :normalize_enabled_currencies! def primary_currency_code - normalize_currency_code(currency) || "USD" + self.class.normalize_currency_code(currency) || "USD" + end + + def default_currency_for_country + self.class.default_currency_for_country(country) + end + + def self.default_currency_for_country(country) + country_currency = ISO3166::Country.new(country.to_s.upcase)&.currency_code + normalize_currency_code(country_currency) || "USD" + end + + def self.default_currency_by_country + LanguagesHelper::COUNTRY_MAPPING.keys.index_with { |country| default_currency_for_country(country) } + end + + def self.normalize_currency_code(value) + return if value.blank? + + Money::Currency.new(value).iso_code + rescue Money::Currency::UnknownCurrencyError, ArgumentError + nil end def custom_enabled_currencies? @@ -491,15 +512,7 @@ class Family < ApplicationRecord end def normalize_currency_codes(values) - Array(values).filter_map { |value| normalize_currency_code(value) }.uniq - end - - def normalize_currency_code(value) - return if value.blank? - - Money::Currency.new(value).iso_code - rescue Money::Currency::UnknownCurrencyError, ArgumentError - nil + Array(values).filter_map { |value| self.class.normalize_currency_code(value) }.uniq end # Not a plain `inclusion: { in: ActiveSupport::TimeZone.all.map(&:name) }` diff --git a/app/views/onboardings/preferences.html.erb b/app/views/onboardings/preferences.html.erb index a6e0c68a0..e804979c1 100644 --- a/app/views/onboardings/preferences.html.erb +++ b/app/views/onboardings/preferences.html.erb @@ -8,7 +8,15 @@ <%= render "onboardings/logout" %> <% end %> -
- +<%= format_money(Money.new(78.90, params[:currency] || @user.family.currency)) %> - (+<%= format_money(Money.new(6.39, params[:currency] || @user.family.currency)) %>) + +<%= format_money(Money.new(78.90, selected_currency)) %> + (+<%= format_money(Money.new(6.39, selected_currency)) %>) as of <%= format_date(Date.parse("2024-10-23"), :default, format_code: params[:date_format] || @user.family.date_format) %>
<%= t(".moniker_prompt", product_name: product_name) %>