diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index c84bad0dc3..b4de3719e5 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -126,6 +126,7 @@ "an_email_has_already_been_sent_to": "", "an_error_occured_while_restoring_project": "", "an_error_occurred_when_verifying_the_coupon_code": "", + "annual_discount": "", "anonymous": "", "anyone_with_link_can_edit": "", "anyone_with_link_can_view": "", @@ -1376,6 +1377,7 @@ "saml_missing_signature_error": "", "saml_response": "", "save": "", + "save_20_percent_when_you_switch_to_annual": "", "save_or_cancel-cancel": "", "save_or_cancel-or": "", "save_or_cancel-save": "", @@ -1595,6 +1597,7 @@ "sure_you_want_to_change_plan": "", "sure_you_want_to_delete": "", "sure_you_want_to_leave_group": "", + "switch_back_to_monthly_pay_20_more": "", "switch_plan": "", "switch_to_editor": "", "switch_to_pdf": "", @@ -1979,6 +1982,7 @@ "you_are_a_manager_of_publisher_x": "", "you_are_a_manager_of_x_plan_as_member_of_group_subscription_y_administered_by_z": "", "you_are_a_manager_of_x_plan_as_member_of_group_subscription_y_administered_by_z_you": "", + "you_are_now_saving_20_percent": "", "you_are_on_a_paid_plan_contact_support_to_find_out_more": "", "you_are_on_x_plan_as_a_confirmed_member_of_institution_y": "", "you_are_on_x_plan_as_member_of_group_subscription_y_administered_by_z": "", diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/subscription.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/subscription.scss index 2c0b75947d..77ff1f5f62 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/pages/subscription.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/pages/subscription.scss @@ -175,6 +175,10 @@ h4 { margin-bottom: var(--spacing-06); + + &:has(+ .payment-nudge-annual-button) { + margin-bottom: 0; + } } .features-list { @@ -440,6 +444,16 @@ } } +.payment-nudge-annual-button { + margin: var(--spacing-02) 0 var(--spacing-06) 0; + + @include body-sm; + + button { + padding: 0; + } +} + .add-on-card { display: flex; align-items: center; diff --git a/services/web/locales/en.json b/services/web/locales/en.json index 67d369dd90..ed0ac1b527 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -1837,6 +1837,7 @@ "saml_response": "SAML Response", "save": "Save", "save_20_percent": "save 20%", + "save_20_percent_when_you_switch_to_annual": "Save 20% when you switch to annual", "save_or_cancel-cancel": "Cancel", "save_or_cancel-or": "or", "save_or_cancel-save": "Save", @@ -2093,6 +2094,7 @@ "sure_you_want_to_delete": "Are you sure you want to permanently delete the following files?", "sure_you_want_to_leave_group": "Are you sure you want to leave this group?", "sv": "Swedish", + "switch_back_to_monthly_pay_20_more": "Switch back to monthly (20% more)", "switch_plan": "Switch plan", "switch_to_editor": "Switch to editor", "switch_to_pdf": "Switch to PDF", @@ -2537,6 +2539,7 @@ "you_are_a_manager_of_x_plan_as_member_of_group_subscription_y_administered_by_z": "You are a <1>manager of the <0>__planName__ group subscription <1>__groupName__ administered by <1>__adminEmail__.", "you_are_a_manager_of_x_plan_as_member_of_group_subscription_y_administered_by_z_you": "You are a <1>manager of the <0>__planName__ group subscription <1>__groupName__ administered by <1>you (__adminEmail__).", "you_are_currently_logged_in_as": "You are currently logged in as __email__.", + "you_are_now_saving_20_percent": "You are now saving 20%", "you_are_on_a_paid_plan_contact_support_to_find_out_more": "You’re on an __appName__ Paid plan. <0>Contact support to find out more.", "you_are_on_x_plan_as_a_confirmed_member_of_institution_y": "You are on our <0>__planName__ plan as a <1>confirmed member of <1>__institutionName__", "you_are_on_x_plan_as_member_of_group_subscription_y_administered_by_z": "You are on our <0>__planName__ plan as a <1>member of the group subscription <1>__groupName__ administered by <1>__adminEmail__", diff --git a/services/web/types/recurly/pricing/subscription.ts b/services/web/types/recurly/pricing/subscription.ts index 744d08c3ea..78b761fd61 100644 --- a/services/web/types/recurly/pricing/subscription.ts +++ b/services/web/types/recurly/pricing/subscription.ts @@ -5,7 +5,7 @@ import { Tax, } from 'recurly__recurly-js' -interface Plan { +export interface Plan { code: string name: string period: { diff --git a/services/web/types/subscription/payment-context-value.tsx b/services/web/types/subscription/payment-context-value.tsx index 79dec23ef5..496f7e027b 100644 --- a/services/web/types/subscription/payment-context-value.tsx +++ b/services/web/types/subscription/payment-context-value.tsx @@ -4,6 +4,18 @@ import { SubscriptionPricingStateTax } from 'recurly__recurly-js' import { SubscriptionPricingInstanceCustom } from '../recurly/pricing/subscription' import { currencies, CurrencyCode } from './currency' +export type RecurlyPrice = + | { + subtotal: string + plan: string + addons: string + setup_fee: string + discount: string + tax: string + total: string + } + | undefined + export type PricingFormState = { first_name: string last_name: string @@ -35,17 +47,7 @@ export type PaymentContextValue = { pricing: React.MutableRefObject recurlyLoading: boolean recurlyLoadError: boolean - recurlyPrice: - | { - subtotal: string - plan: string - addons: string - setup_fee: string - discount: string - tax: string - total: string - } - | undefined + recurlyPrice: RecurlyPrice monthlyBilling: boolean | undefined taxes: SubscriptionPricingStateTax[] coupon: @@ -71,4 +73,5 @@ export type PaymentContextValue = { React.SetStateAction > updatePlan: (newPlanCode: string) => void + showNudgeToAnnualText: boolean }