From a4cfecb2aa80aae299e154d36f0124809e8ed034 Mon Sep 17 00:00:00 2001 From: Jimmy Domagala-Tang Date: Wed, 7 May 2025 10:13:35 -0400 Subject: [PATCH] Merge pull request #25251 from overleaf/jdt-show-wf-provided-bundle-on-free-plans Show AI Assist entitlment via Writefull on free user's subscriptions page GitOrigin-RevId: 20a456a231f60df279b949057972125735166904 --- .../components/dashboard/free-plan.tsx | 11 +++ .../dashboard/personal-subscription.tsx | 22 +----- .../components/dashboard/redirect-alerts.tsx | 24 +++++++ .../dashboard/states/active/active-new.tsx | 4 -- .../dashboard/states/active/add-ons.tsx | 55 +-------------- .../writefull-bundle-management-modal.tsx | 68 ++++++++++++++++++- 6 files changed, 105 insertions(+), 79 deletions(-) create mode 100644 services/web/frontend/js/features/subscription/components/dashboard/redirect-alerts.tsx diff --git a/services/web/frontend/js/features/subscription/components/dashboard/free-plan.tsx b/services/web/frontend/js/features/subscription/components/dashboard/free-plan.tsx index ce4c2baaa5..a8cf7dcf7b 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/free-plan.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/free-plan.tsx @@ -1,10 +1,15 @@ import { useTranslation, Trans } from 'react-i18next' +import WritefullManagedBundleAddOn from '@/features/subscription/components/dashboard/states/active/change-plan/modals/writefull-bundle-management-modal' +import RedirectAlerts from './redirect-alerts' +import getMeta from '@/utils/meta' function FreePlan() { const { t } = useTranslation() + const hasAiAssistViaWritefull = getMeta('ol-hasAiAssistViaWritefull') return ( <> + {t('upgrade_now')} + {hasAiAssistViaWritefull && ( + <> +

{t('add_ons')}

+ + + )} ) } diff --git a/services/web/frontend/js/features/subscription/components/dashboard/personal-subscription.tsx b/services/web/frontend/js/features/subscription/components/dashboard/personal-subscription.tsx index d6a511af75..2173ea45d3 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/personal-subscription.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/personal-subscription.tsx @@ -7,6 +7,7 @@ import { ExpiredSubscription } from './states/expired' import { useSubscriptionDashboardContext } from '../../context/subscription-dashboard-context' import PersonalSubscriptionRecurlySyncEmail from './personal-subscription-recurly-sync-email' import OLNotification from '@/features/ui/components/ol/ol-notification' +import RedirectAlerts from './redirect-alerts' function PastDueSubscriptionAlert({ subscription, @@ -33,27 +34,6 @@ function PastDueSubscriptionAlert({ ) } -function RedirectAlerts() { - const queryParams = new URLSearchParams(window.location.search) - const redirectReason = queryParams.get('redirect-reason') - const { t } = useTranslation() - - if (!redirectReason) { - return null - } - - let warning - if (redirectReason === 'writefull-entitled') { - warning = t('good_news_you_are_already_receiving_this_add_on_via_writefull') - } else if (redirectReason === 'double-buy') { - warning = t('good_news_you_already_purchased_this_add_on') - } else { - return null - } - - return {warning}} /> -} - function PersonalSubscriptionStates({ subscription, }: { diff --git a/services/web/frontend/js/features/subscription/components/dashboard/redirect-alerts.tsx b/services/web/frontend/js/features/subscription/components/dashboard/redirect-alerts.tsx new file mode 100644 index 0000000000..be5bab484e --- /dev/null +++ b/services/web/frontend/js/features/subscription/components/dashboard/redirect-alerts.tsx @@ -0,0 +1,24 @@ +import { useTranslation } from 'react-i18next' +import OLNotification from '@/features/ui/components/ol/ol-notification' + +export function RedirectAlerts() { + const queryParams = new URLSearchParams(window.location.search) + const redirectReason = queryParams.get('redirect-reason') + const { t } = useTranslation() + + if (!redirectReason) { + return null + } + + let warning + if (redirectReason === 'writefull-entitled') { + warning = t('good_news_you_are_already_receiving_this_add_on_via_writefull') + } else if (redirectReason === 'double-buy') { + warning = t('good_news_you_already_purchased_this_add_on') + } else { + return null + } + + return {warning}} /> +} +export default RedirectAlerts diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/active-new.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/active-new.tsx index 2f01474251..dfc6448fb0 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/active-new.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/active-new.tsx @@ -10,7 +10,6 @@ import { ConfirmChangePlanModal } from './change-plan/modals/confirm-change-plan import { KeepCurrentPlanModal } from './change-plan/modals/keep-current-plan-modal' import { ChangeToGroupModal } from './change-plan/modals/change-to-group-modal' import { CancelAiAddOnModal } from '@/features/subscription/components/dashboard/states/active/change-plan/modals/cancel-ai-add-on-modal' -import { WritefullBundleManagementModal } from '@/features/subscription/components/dashboard/states/active/change-plan/modals/writefull-bundle-management-modal' import OLButton from '@/features/ui/components/ol/ol-button' import isInFreeTrial from '../../../../util/is-in-free-trial' import AddOns from '@/features/subscription/components/dashboard/states/active/add-ons' @@ -72,7 +71,6 @@ export function ActiveSubscriptionNew({ } const handlePlanChange = () => setModalIdShown('change-plan') - const handleManageOnWritefull = () => setModalIdShown('manage-on-writefull') const handleCancelClick = (addOnCode: string) => { if ( [AI_ASSIST_STANDALONE_MONTHLY_PLAN_CODE, AI_ADD_ON_CODE].includes( @@ -266,7 +264,6 @@ export function ActiveSubscriptionNew({ subscription={subscription} onStandalonePlan={onStandalonePlan} handleCancelClick={handleCancelClick} - handleManageOnWritefull={handleManageOnWritefull} /> @@ -274,7 +271,6 @@ export function ActiveSubscriptionNew({ - ) diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/add-ons.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/add-ons.tsx index 9d7a511ab0..521f670e5f 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/add-ons.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/add-ons.tsx @@ -12,12 +12,12 @@ import { import sparkle from '@/shared/svgs/sparkle.svg' import { PaidSubscription } from '../../../../../../../../types/subscription/dashboard/subscription' import { LICENSE_ADD_ON } from '@/features/group-management/components/upgrade-subscription/upgrade-subscription-plan-details' +import WritefullManagedBundleAddOn from './change-plan/modals/writefull-bundle-management-modal' type AddOnsProps = { subscription: PaidSubscription onStandalonePlan: boolean handleCancelClick: (code: string) => void - handleManageOnWritefull: () => void } type AddOnProps = { @@ -100,57 +100,10 @@ function AddOn({ ) } -function WritefullGrantedAddOn({ - handleManageOnWritefull, -}: { - handleManageOnWritefull: () => void -}) { - const { t } = useTranslation() - return ( -
-
- -
-
-
{ADD_ON_NAME}
-
- {t('included_as_part_of_your_writefull_subscription')} -
-
- -
- - - - - - - {t('manage_subscription')} - - - -
-
- ) -} - function AddOns({ subscription, onStandalonePlan, handleCancelClick, - handleManageOnWritefull, }: AddOnsProps) { const { t } = useTranslation() const hasAiAssistViaWritefull = getMeta('ol-hasAiAssistViaWritefull') @@ -187,11 +140,7 @@ function AddOns({ nextBillingDate={subscription.payment.nextPaymentDueDate} /> ))} - {hasAiAssistViaWritefull && ( - - )} + {hasAiAssistViaWritefull && } ) : (

{t('you_dont_have_any_add_ons_on_your_account')}

diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/writefull-bundle-management-modal.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/writefull-bundle-management-modal.tsx index ef512ddec5..d5933d137a 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/writefull-bundle-management-modal.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/writefull-bundle-management-modal.tsx @@ -8,8 +8,13 @@ import OLModal, { OLModalTitle, } from '@/features/ui/components/ol/ol-modal' import OLButton from '@/features/ui/components/ol/ol-button' +import sparkle from '@/shared/svgs/sparkle.svg' +import { Dropdown, DropdownMenu, DropdownToggle } from 'react-bootstrap-5' +import OLDropdownMenuItem from '@/features/ui/components/ol/ol-dropdown-menu-item' +import MaterialIcon from '@/shared/components/material-icon' +import { ADD_ON_NAME } from '@/features/subscription/data/add-on-codes' -export function WritefullBundleManagementModal() { +function WritefullBundleManagementModal() { const modalId: SubscriptionDashModalIds = 'manage-on-writefull' const { t } = useTranslation() const { handleCloseModal, modalIdShown } = useSubscriptionDashboardContext() @@ -49,3 +54,64 @@ export function WritefullBundleManagementModal() { ) } + +function WritefullGrantedAddOn({ + handleManageOnWritefull, +}: { + handleManageOnWritefull: () => void +}) { + const { t } = useTranslation() + return ( +
+
+ +
+
+
{ADD_ON_NAME}
+
+ {t('included_as_part_of_your_writefull_subscription')} +
+
+ +
+ + + + + + + {t('manage_subscription')} + + + +
+
+ ) +} + +export function WritefullManagedBundleAddOn() { + const { setModalIdShown } = useSubscriptionDashboardContext() + const handleManageOnWritefull = () => setModalIdShown('manage-on-writefull') + return ( + <> + + + + ) +} + +export default WritefullManagedBundleAddOn