diff --git a/app/controllers/competitions_controller.rb b/app/controllers/competitions_controller.rb index 7a0532e79d7..b3136a8a223 100644 --- a/app/controllers/competitions_controller.rb +++ b/app/controllers/competitions_controller.rb @@ -370,11 +370,15 @@ def registration_collisions_json end def calculate_dues - country_iso2 = Country.find_by(id: params[:country_id])&.iso2 - multiplier = ActiveRecord::Type::Boolean.new.cast(params[:competitor_limit_enabled]) ? params[:competitor_limit].to_i : 1 - total_dues = DuesCalculator.dues_for_n_competitors(country_iso2, params[:base_entry_fee_lowest_denomination].to_i, params[:currency_code], multiplier) + country_iso2 = Country.find_by(id: params[:countryId])&.iso2 + per_competitor_dues = DuesCalculator.dues_per_competitor( + country_iso2, + params[:baseEntryFee].to_i, + params[:currencyCode], + ) + render json: { - dues_value: total_dues.present? ? total_dues.format : nil, + dues_value: per_competitor_dues.to_f, } end diff --git a/app/webpacker/components/CompetitionForm/FormSections/DuesEstimate.jsx b/app/webpacker/components/CompetitionForm/FormSections/DuesEstimate.jsx new file mode 100644 index 00000000000..664cd752cc2 --- /dev/null +++ b/app/webpacker/components/CompetitionForm/FormSections/DuesEstimate.jsx @@ -0,0 +1,48 @@ +import React, { useMemo } from 'react'; +import { Input, Modal } from 'semantic-ui-react'; +import useInputState from '../../../lib/hooks/useInputState'; +import { calculateDuesUrl } from '../../../lib/requests/routes.js.erb'; +import { currenciesData } from '../../../lib/wca-data.js.erb'; +import useLoadedData from '../../../lib/hooks/useLoadedData'; +import Loading from '../../Requests/Loading'; +import Errored from '../../Requests/Errored'; + +export default function DuesEstimate({ + close, countryId, currencyCode, baseEntryFee, competitorLimit, +}) { + const [competitorCount, setCompetitorCount] = useInputState(competitorLimit || 0); + const currencyInfo = useMemo( + () => (currenciesData.byIso[currencyCode] || currenciesData.byIso.USD), + [currencyCode], + ); + + const { + data, loading, error, + } = useLoadedData(calculateDuesUrl(countryId, currencyCode, baseEntryFee)); + + const { dues_value: duesValue } = data || {}; + + if (loading) return ; + if (error) return ; + + return ( + + Dues Estimate + + + + {`Dues for ${competitorCount} competitors (approximately): ${currencyInfo?.symbol || ''}${(duesValue * competitorCount).toFixed(2)}`} + + + + ); +} diff --git a/app/webpacker/components/CompetitionForm/FormSections/RegistrationFees.js b/app/webpacker/components/CompetitionForm/FormSections/RegistrationFees.js index 0f690655f5b..e5d219965c0 100644 --- a/app/webpacker/components/CompetitionForm/FormSections/RegistrationFees.js +++ b/app/webpacker/components/CompetitionForm/FormSections/RegistrationFees.js @@ -1,4 +1,5 @@ -import React, { useMemo } from 'react'; +import React, { useState } from 'react'; +import { Button } from 'semantic-ui-react'; import { InputBoolean, InputCurrencyAmount, @@ -7,12 +8,10 @@ import { InputSelect, } from '../../wca/FormBuilder/input/FormInputs'; import { currenciesData } from '../../../lib/wca-data.js.erb'; -import I18n from '../../../lib/i18n'; -import { calculateDuesUrl } from '../../../lib/requests/routes.js.erb'; -import useLoadedData from '../../../lib/hooks/useLoadedData'; import ConditionalSection from './ConditionalSection'; import SubSection from '../../wca/FormBuilder/SubSection'; import { useFormObject } from '../../wca/FormBuilder/provider/FormObjectProvider'; +import DuesEstimate from './DuesEstimate'; const currenciesOptions = Object.keys(currenciesData.byIso).map((iso) => ({ key: iso, @@ -29,59 +28,26 @@ export default function RegistrationFees() { competitorLimit, registration, } = useFormObject(); + const [showDuesEstimate, setShowDuesEstimate] = useState(false); const currency = entryFees.currencyCode; const canRegOnSite = registration && registration.allowOnTheSpot; - const savedParams = useMemo(() => { - const params = new URLSearchParams(); - - params.append('competitor_limit_enabled', competitorLimit.enabled); - params.append('competitor_limit', competitorLimit.count); - params.append('currency_code', entryFees.currencyCode); - params.append('base_entry_fee_lowest_denomination', entryFees.baseEntryFee); - params.append('country_id', country); - - return params; - }, [competitorLimit, country, entryFees]); - - const entryFeeDuesUrl = useMemo( - () => `${calculateDuesUrl}?${savedParams.toString()}`, - [savedParams], - ); - - const { - data: duesJson, - error, - } = useLoadedData(entryFeeDuesUrl); - - const duesText = useMemo(() => { - if (error || !duesJson?.dues_value) { - return I18n.t('competitions.competition_form.dues_estimate.ajax_error'); - } - - if (competitorLimit.enabled) { - return `${I18n.t('competitions.competition_form.dues_estimate.calculated', { - limit: competitorLimit.count, - estimate: duesJson?.dues_value, - })} (${currency})`; - } - - return `${I18n.t('competitions.competition_form.dues_estimate.per_competitor', { - estimate: duesJson?.dues_value, - })} (${currency})`; - }, [competitorLimit, currency, duesJson, error]); - return ( - - - {duesText} - - + setShowDuesEstimate(true)}>Show Dues Estimate + {showDuesEstimate && ( + setShowDuesEstimate(false)} + countryId={country} + currencyCode={entryFees.currencyCode} + baseEntryFee={entryFees.baseEntryFee} + competitorLimit={competitorLimit.count} + /> + )} diff --git a/app/webpacker/lib/requests/routes.js.erb b/app/webpacker/lib/requests/routes.js.erb index 8ede18803e7..3c342bd0575 100644 --- a/app/webpacker/lib/requests/routes.js.erb +++ b/app/webpacker/lib/requests/routes.js.erb @@ -137,7 +137,7 @@ export const seriesEligibleCompetitionsJsonUrl = `<%= CGI.unescape(Rails.applica export const registrationCollisionsJsonUrl = `<%= CGI.unescape(Rails.application.routes.url_helpers.registration_collisions_json_path)%>`; -export const calculateDuesUrl = `<%= CGI.unescape(Rails.application.routes.url_helpers.calculate_dues_path)%>`; +export const calculateDuesUrl = (countryId, currencyCode, baseEntryFee) => `<%= CGI.unescape(Rails.application.routes.url_helpers.calculate_dues_path)%>?${jsonToQueryString({ countryId, currencyCode, baseEntryFee })}`; export const adminPostingCompetitionsUrl = `<%= CGI.unescape(Rails.application.routes.url_helpers.results_posting_dashboard_path(format: "json")) %>`; diff --git a/lib/dues_calculator.rb b/lib/dues_calculator.rb index bbeaf95b42e..5cfa7f1f528 100644 --- a/lib/dues_calculator.rb +++ b/lib/dues_calculator.rb @@ -3,13 +3,7 @@ module DuesCalculator def self.dues_for_n_competitors(country_iso2, base_entry_fee_lowest_denomination, currency_code, n) dues_per_competitor_in_usd_money = dues_per_competitor_in_usd(country_iso2, base_entry_fee_lowest_denomination, currency_code) - if dues_per_competitor_in_usd_money.present? - (dues_per_competitor_in_usd_money * n).exchange_to(currency_code) - else - nil - end - rescue CurrencyUnavailable - nil + dues_per_competitor_in_usd_money.exchange_to(currency_code) end def self.dues_per_competitor_in_usd(country_iso2, base_entry_fee_lowest_denomination, currency_code)
+ {`Dues for ${competitorCount} competitors (approximately): ${currencyInfo?.symbol || ''}${(duesValue * competitorCount).toFixed(2)}`} +
- - {duesText} - -