diff --git a/projects/packages/my-jetpack/_inc/hooks/use-notification-watcher/index.ts b/projects/packages/my-jetpack/_inc/hooks/use-notification-watcher/index.ts index 0efbfe8f3da00..37c1be01d288b 100644 --- a/projects/packages/my-jetpack/_inc/hooks/use-notification-watcher/index.ts +++ b/projects/packages/my-jetpack/_inc/hooks/use-notification-watcher/index.ts @@ -4,11 +4,13 @@ import useBadInstallNotice from './use-bad-install-notice'; import useConnectionErrorsNotice from './use-connection-errors-notice'; import useDeprecateFeatureNotice from './use-deprecate-feature-notice'; import useExpiringPlansNotice from './use-expiring-plans-notice'; +import useProtectThreatsDetectedNotice from './use-protect-threats-detected-notice'; import useSiteConnectionNotice from './use-site-connection-notice'; const useNotificationWatcher = () => { const { redBubbleAlerts } = getMyJetpackWindowInitialState(); + useProtectThreatsDetectedNotice( redBubbleAlerts ); useExpiringPlansNotice( redBubbleAlerts ); useBackupNeedsAttentionNotice( redBubbleAlerts ); useDeprecateFeatureNotice( redBubbleAlerts ); diff --git a/projects/packages/my-jetpack/_inc/hooks/use-notification-watcher/use-protect-threats-detected-notice.tsx b/projects/packages/my-jetpack/_inc/hooks/use-notification-watcher/use-protect-threats-detected-notice.tsx new file mode 100644 index 0000000000000..1674368333318 --- /dev/null +++ b/projects/packages/my-jetpack/_inc/hooks/use-notification-watcher/use-protect-threats-detected-notice.tsx @@ -0,0 +1,126 @@ +import { Col, getRedirectUrl, Text } from '@automattic/jetpack-components'; +import { __, sprintf } from '@wordpress/i18n'; +import { useContext, useEffect, useCallback } from 'react'; +import { NOTICE_PRIORITY_MEDIUM } from '../../context/constants'; +import { NoticeContext } from '../../context/notices/noticeContext'; +import useProduct from '../../data/products/use-product'; +import preventWidows from '../../utils/prevent-widows'; +import useAnalytics from '../use-analytics'; +import type { NoticeOptions } from '../../context/notices/types'; + +type RedBubbleAlerts = Window[ 'myJetpackInitialState' ][ 'redBubbleAlerts' ]; + +const useProtectThreatsDetectedNotice = ( redBubbleAlerts: RedBubbleAlerts ) => { + const { recordEvent } = useAnalytics(); + const { setNotice } = useContext( NoticeContext ); + const { detail } = useProduct( 'protect' ); + const { + hasPaidPlanForProduct, + standalonePluginInfo, + manageUrl: protectDashboardUrl, + } = detail || {}; + const { isStandaloneActive } = standalonePluginInfo || {}; + + const { + type, + data: { + threat_count: threatCount, + critical_threat_count: criticalThreatCount, + fixable_threat_ids: fixableThreatIds, + }, + } = redBubbleAlerts?.protect_has_threats || { type: 'warning', data: {} }; + + const fixThreatsLearnMoreUrl = getRedirectUrl( 'protect-footer-learn-more-scan', { + anchor: 'how-do-i-fix-threats', + } ); + + const noticeTitle = sprintf( + // translators: %s is the product name. Can be either "Scan" or "Protect". + __( '%s found threats on your site', 'jetpack-my-jetpack' ), + hasPaidPlanForProduct && isStandaloneActive ? 'Protect' : 'Scan' + ); + + const onPrimaryCtaClick = useCallback( () => { + window.open( protectDashboardUrl ); + recordEvent( 'jetpack_my_jetpack_protect_threats_detected_notice_primary_cta_click', { + threat_count: threatCount, + critical_threat_count: criticalThreatCount, + fixable_threat_ids: fixableThreatIds, + } ); + }, [ criticalThreatCount, fixableThreatIds, protectDashboardUrl, recordEvent, threatCount ] ); + + const onSecondaryCtaClick = useCallback( () => { + window.open( fixThreatsLearnMoreUrl ); + recordEvent( 'jetpack_my_jetpack_protect_threats_detected_notice_secondary_cta_click', { + threat_count: threatCount, + critical_threat_count: criticalThreatCount, + fixable_threat_ids: fixableThreatIds, + } ); + }, [ criticalThreatCount, fixThreatsLearnMoreUrl, fixableThreatIds, recordEvent, threatCount ] ); + + useEffect( () => { + if ( ! redBubbleAlerts?.protect_has_threats ) { + return; + } + + const noticeMessage = ( +