Просмотр исходного кода

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
Jimmy Domagala-Tang 1 год назад
Родитель
Сommit
9f0f910a83

+ 11 - 0
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 (
     <>
+      <RedirectAlerts />
       <Trans
         i18nKey="on_free_plan_upgrade_to_access_features"
         components={[
@@ -26,6 +31,12 @@ function FreePlan() {
       <a className="btn btn-primary me-1" href="/user/subscription/plans">
         {t('upgrade_now')}
       </a>
+      {hasAiAssistViaWritefull && (
+        <>
+          <h2 className="h3 fw-bold">{t('add_ons')}</h2>
+          <WritefullManagedBundleAddOn />
+        </>
+      )}
     </>
   )
 }

+ 1 - 21
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 <OLNotification type="warning" content={<>{warning}</>} />
-}
-
 function PersonalSubscriptionStates({
   subscription,
 }: {

+ 24 - 0
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 <OLNotification type="warning" content={<>{warning}</>} />
+}
+export default RedirectAlerts

+ 0 - 4
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}
       />
 
       <ChangePlanModal />
@@ -274,7 +271,6 @@ export function ActiveSubscriptionNew({
       <KeepCurrentPlanModal />
       <ChangeToGroupModal />
       <CancelAiAddOnModal />
-      <WritefullBundleManagementModal />
       <PauseSubscriptionModal />
     </>
   )

+ 2 - 53
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 (
-    <div className="add-on-card">
-      <div>
-        <img
-          alt="sparkle"
-          className="add-on-card-icon"
-          src={sparkle}
-          aria-hidden="true"
-        />
-      </div>
-      <div className="add-on-card-content">
-        <div className="heading">{ADD_ON_NAME}</div>
-        <div className="description small mt-1">
-          {t('included_as_part_of_your_writefull_subscription')}
-        </div>
-      </div>
-
-      <div className="ms-auto">
-        <Dropdown align="end">
-          <DropdownToggle
-            id="add-on-dropdown-toggle"
-            className="add-on-options-toggle"
-            variant="secondary"
-          >
-            <MaterialIcon
-              type="more_vert"
-              accessibilityLabel={t('more_options')}
-            />
-          </DropdownToggle>
-          <DropdownMenu flip={false}>
-            <OLDropdownMenuItem tabIndex={-1} onClick={handleManageOnWritefull}>
-              {t('manage_subscription')}
-            </OLDropdownMenuItem>
-          </DropdownMenu>
-        </Dropdown>
-      </div>
-    </div>
-  )
-}
-
 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 && (
-            <WritefullGrantedAddOn
-              handleManageOnWritefull={handleManageOnWritefull}
-            />
-          )}
+          {hasAiAssistViaWritefull && <WritefullManagedBundleAddOn />}
         </>
       ) : (
         <p>{t('you_dont_have_any_add_ons_on_your_account')}</p>

+ 67 - 1
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() {
     </OLModal>
   )
 }
+
+function WritefullGrantedAddOn({
+  handleManageOnWritefull,
+}: {
+  handleManageOnWritefull: () => void
+}) {
+  const { t } = useTranslation()
+  return (
+    <div className="add-on-card">
+      <div>
+        <img
+          alt="sparkle"
+          className="add-on-card-icon"
+          src={sparkle}
+          aria-hidden="true"
+        />
+      </div>
+      <div className="add-on-card-content">
+        <div className="heading">{ADD_ON_NAME}</div>
+        <div className="description small mt-1">
+          {t('included_as_part_of_your_writefull_subscription')}
+        </div>
+      </div>
+
+      <div className="ms-auto">
+        <Dropdown align="end">
+          <DropdownToggle
+            id="add-on-dropdown-toggle"
+            className="add-on-options-toggle"
+            variant="secondary"
+          >
+            <MaterialIcon
+              type="more_vert"
+              accessibilityLabel={t('more_options')}
+            />
+          </DropdownToggle>
+          <DropdownMenu flip={false}>
+            <OLDropdownMenuItem tabIndex={-1} onClick={handleManageOnWritefull}>
+              {t('manage_subscription')}
+            </OLDropdownMenuItem>
+          </DropdownMenu>
+        </Dropdown>
+      </div>
+    </div>
+  )
+}
+
+export function WritefullManagedBundleAddOn() {
+  const { setModalIdShown } = useSubscriptionDashboardContext()
+  const handleManageOnWritefull = () => setModalIdShown('manage-on-writefull')
+  return (
+    <>
+      <WritefullGrantedAddOn
+        handleManageOnWritefull={handleManageOnWritefull}
+      />
+      <WritefullBundleManagementModal />
+    </>
+  )
+}
+
+export default WritefullManagedBundleAddOn