-
Notifications
You must be signed in to change notification settings - Fork 805
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
My Jetpack: Add red bubble and warning Notice when paid plans are exp…
…ired or expiring soon. (#40115) * Add expired/expiring statuses to products. * changelog * Add logic in remaining product classes for expired/expiring functionality. * Add error/warning border color to expired/expiring product cards. * Trigger red bubble and Notice for expired or expiring paid products. * Refactor/improve how we determine 'has_paid_plan_for_product()'. * Add option to hide expiration status. * Make expired CTA goto purchase management page, and expiring soon CTA goto straight to checkout. * "Your plans" section: Highlight expiring plans (red or yellow) & add 'Renew subscription' link.
- Loading branch information
1 parent
fd10edd
commit e447304
Showing
14 changed files
with
549 additions
and
14 deletions.
There are no files selected for viewing
5 changes: 5 additions & 0 deletions
5
projects/js-packages/components/changelog/add-redbubble_for_expired_products
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Significance: patch | ||
Type: changed | ||
Comment: Just adding a couple additional props to the NoticeActionButton. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
projects/packages/my-jetpack/_inc/hooks/use-notification-watcher/products-list.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export const ProductsList = ( { products }: { products: string[] } ) => { | ||
if ( ! products ) { | ||
return null; | ||
} | ||
return ( | ||
<ul className="products-list"> | ||
{ products.map( ( product, index ) => ( | ||
<li key={ index } className="product-badge"> | ||
{ product } | ||
</li> | ||
) ) } | ||
</ul> | ||
); | ||
}; |
117 changes: 117 additions & 0 deletions
117
...cts/packages/my-jetpack/_inc/hooks/use-notification-watcher/use-expiring-plans-notice.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import { __ } from '@wordpress/i18n'; | ||
import { useContext, useEffect, useCallback } from 'react'; | ||
import { NOTICE_PRIORITY_MEDIUM } from '../../context/constants'; | ||
import { NoticeContext } from '../../context/notices/noticeContext'; | ||
import useAnalytics from '../use-analytics'; | ||
import { useGetExpiringNoticeContent } from './use-get-expiring-notice-content'; | ||
import type { NoticeOptions } from '../../context/notices/types'; | ||
|
||
type RedBubbleAlerts = Window[ 'myJetpackInitialState' ][ 'redBubbleAlerts' ]; | ||
|
||
const useExpiringPlansNotice = ( redBubbleAlerts: RedBubbleAlerts ) => { | ||
const { setNotice } = useContext( NoticeContext ); | ||
const { recordEvent } = useAnalytics(); | ||
|
||
const planExpiredAlerts = Object.keys( redBubbleAlerts ).filter( | ||
key => key.endsWith( '--plan_expiring_soon' ) || key.endsWith( '--plan_expired' ) | ||
) as Array< `${ string }--plan_expiring_soon` | `${ string }--plan_expired` >; | ||
|
||
const expiredAlerts = | ||
planExpiredAlerts.length && | ||
planExpiredAlerts.filter( alert => alert.endsWith( '--plan_expired' ) ); | ||
const expiringSoonAlerts = | ||
planExpiredAlerts.length && | ||
planExpiredAlerts.filter( alert => alert.endsWith( '--plan_expiring_soon' ) ); | ||
|
||
// Already expired alerts take precidence over expiring alerts. | ||
// i.e.- Display 'expired' alert if there is one, otherwise display 'expiring soon' alert. | ||
const alertToDisplay = expiredAlerts.length ? expiredAlerts[ 0 ] : expiringSoonAlerts[ 0 ]; | ||
const isExpiredAlert = alertToDisplay && alertToDisplay.endsWith( '--plan_expired' ); | ||
const expiredAlertType = isExpiredAlert ? 'expired' : 'expiring-soon'; | ||
|
||
const { | ||
product_slug: productSlug, | ||
product_name: productName, | ||
expiry_date: expiryDate, | ||
manage_url: manageUrl, | ||
products_effected: productsEffected, | ||
} = redBubbleAlerts[ alertToDisplay ] || {}; | ||
|
||
const { noticeTitle, noticeMessage, learnMoreUrl } = | ||
useGetExpiringNoticeContent( { | ||
productSlug, | ||
expiredAlertType, | ||
productName, | ||
expiryDate, | ||
productsEffected, | ||
} ) || {}; | ||
|
||
const onPrimaryCtaClick = useCallback( () => { | ||
window.location.href = manageUrl; | ||
recordEvent( | ||
isExpiredAlert | ||
? 'jetpack_my_jetpack_plan_expired_notice_primary_cta_click' | ||
: 'jetpack_my_jetpack_plan_expiring_soon_notice_primary_cta_click', | ||
{ | ||
product_slug: productSlug, | ||
} | ||
); | ||
}, [ isExpiredAlert, manageUrl, productSlug, recordEvent ] ); | ||
|
||
const onSecondaryCtaClick = useCallback( () => { | ||
window.open( learnMoreUrl ); | ||
recordEvent( | ||
isExpiredAlert | ||
? 'jetpack_my_jetpack_plan_expired_notice_secondary_cta_click' | ||
: 'jetpack_my_jetpack_plan_expiring_soon_notice_secondary_cta_click', | ||
{ | ||
product_slug: productSlug, | ||
} | ||
); | ||
}, [ learnMoreUrl, isExpiredAlert, productSlug, recordEvent ] ); | ||
|
||
useEffect( () => { | ||
if ( ! alertToDisplay ) { | ||
return; | ||
} | ||
|
||
const resumePlanText = __( 'Resume my plan', 'jetpack-my-jetpack' ); | ||
const renewPlanText = __( 'Renew my plan', 'jetpack-my-jetpack' ); | ||
|
||
const noticeOptions: NoticeOptions = { | ||
id: isExpiredAlert ? 'plan-expired-notice' : 'plan-expiring-soon-notice', | ||
level: isExpiredAlert ? 'error' : 'warning', | ||
actions: [ | ||
{ | ||
label: isExpiredAlert ? resumePlanText : renewPlanText, | ||
onClick: onPrimaryCtaClick, | ||
noDefaultClasses: true, | ||
}, | ||
{ | ||
label: __( 'Learn more', 'jetpack-my-jetpack' ), | ||
onClick: onSecondaryCtaClick, | ||
isExternalLink: true, | ||
}, | ||
], | ||
priority: NOTICE_PRIORITY_MEDIUM, | ||
}; | ||
|
||
setNotice( { | ||
title: noticeTitle, | ||
message: noticeMessage, | ||
options: noticeOptions, | ||
} ); | ||
}, [ | ||
redBubbleAlerts, | ||
setNotice, | ||
recordEvent, | ||
alertToDisplay, | ||
onPrimaryCtaClick, | ||
onSecondaryCtaClick, | ||
noticeTitle, | ||
noticeMessage, | ||
isExpiredAlert, | ||
] ); | ||
}; | ||
|
||
export default useExpiringPlansNotice; |
Oops, something went wrong.