diff --git a/apps/meteor/client/components/GenericUpsellModal.tsx b/apps/meteor/client/components/GenericUpsellModal.tsx deleted file mode 100644 index 7e24219dafb3..000000000000 --- a/apps/meteor/client/components/GenericUpsellModal.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { Box, Button, Modal } from '@rocket.chat/fuselage'; -import type { Keys as IconName } from '@rocket.chat/icons'; -import { useRouter, useSetModal, useSetting, useTranslation } from '@rocket.chat/ui-contexts'; -import type { ReactNode, ReactElement, ComponentProps } from 'react'; -import React, { useCallback, useEffect, useRef } from 'react'; - -type UpsellModalProps = { - children?: ReactNode; - tagline?: ReactNode; - cancelText?: ReactNode; - confirmText?: ReactNode; - title: string | ReactElement; - subtitle?: string | ReactElement; - description?: string | ReactElement; - icon?: IconName; - img: ComponentProps['src']; - onCancel?: () => void; - onClose?: () => void; - onConfirm?: () => void; - onCloseEffect?: () => void; -}; - -const GenericUpsellModal = ({ - tagline, - title, - subtitle, - img, - cancelText, - confirmText, - icon, - description, - onCancel, - onConfirm, - onClose = onCancel, - onCloseEffect, -}: UpsellModalProps) => { - const t = useTranslation(); - const cloudWorkspaceHadTrial = Boolean(useSetting('Cloud_Workspace_Had_Trial')); - - const router = useRouter(); - const setModal = useSetModal(); - - const handleModalClose = useCallback(() => { - setModal(null); - }, [setModal]); - - const handleConfirmModal = useCallback(() => { - handleModalClose(); - router.navigate({ - pathname: '/admin/upgrade/go-fully-featured-registered', - }); - }, [handleModalClose, router]); - - const talkToSales = 'https://go.rocket.chat/i/contact-sales'; - const handleCancelModal = useCallback(() => { - handleModalClose(); - window.open(talkToSales, '_blank'); - }, [handleModalClose]); - - const onCloseRef = useRef(onCloseEffect ?? handleModalClose); - onCloseRef.current = onCloseEffect ?? handleModalClose; - - useEffect(() => { - return () => { - const onClose = onCloseRef.current; - onClose?.(); - }; - }, []); - - return ( - - - {icon && } - - {tagline ?? t('Enterprise_capability')} - {title} - - - - - - {subtitle && ( - - {subtitle} - - )} - - {description && {description}} - - - - - - - - - - ); -}; - -export default GenericUpsellModal; diff --git a/apps/meteor/client/components/GenericUpsellModal/GenericUpsellModal.tsx b/apps/meteor/client/components/GenericUpsellModal/GenericUpsellModal.tsx new file mode 100644 index 000000000000..e5f77f307285 --- /dev/null +++ b/apps/meteor/client/components/GenericUpsellModal/GenericUpsellModal.tsx @@ -0,0 +1,83 @@ +import { Box, Button, Modal } from '@rocket.chat/fuselage'; +import type { Keys as IconName } from '@rocket.chat/icons'; +import { useTranslation } from '@rocket.chat/ui-contexts'; +import type { ReactNode, ReactElement, ComponentProps } from 'react'; +import React from 'react'; + +type GenericUpsellModalProps = { + children?: ReactNode; + tagline?: ReactNode; + cancelText?: ReactNode; + confirmText?: ReactNode; + title: string | ReactElement; + subtitle?: string | ReactElement; + description?: string | ReactElement; + icon?: IconName; + img: ComponentProps['src']; + onCancel?: () => void; + onClose?: () => void; + onConfirm?: () => void; + annotation?: ReactNode; +}; + +const GenericUpsellModal = ({ + tagline, + title, + subtitle, + img, + cancelText, + confirmText, + icon, + description, + onCancel, + onConfirm, + onClose = onCancel, + annotation, +}: GenericUpsellModalProps) => { + const t = useTranslation(); + + return ( + + + {icon && } + + {tagline ?? t('Enterprise_capability')} + {title} + + + + + + {subtitle && ( + + {subtitle} + + )} + {description && ( + + {description} + + )} + + + {annotation && {annotation}} + {(onCancel || onConfirm) && ( + + {onCancel && ( + + )} + {onConfirm && ( + + )} + + )} + + + ); +}; + +export default GenericUpsellModal; diff --git a/apps/meteor/client/components/GenericUpsellModal/hooks/index.ts b/apps/meteor/client/components/GenericUpsellModal/hooks/index.ts new file mode 100644 index 000000000000..f7af26c76c48 --- /dev/null +++ b/apps/meteor/client/components/GenericUpsellModal/hooks/index.ts @@ -0,0 +1 @@ +export * from './useUpsellActions'; diff --git a/apps/meteor/client/components/GenericUpsellModal/hooks/useUpsellActions.ts b/apps/meteor/client/components/GenericUpsellModal/hooks/useUpsellActions.ts new file mode 100644 index 000000000000..38fa9e65b632 --- /dev/null +++ b/apps/meteor/client/components/GenericUpsellModal/hooks/useUpsellActions.ts @@ -0,0 +1,29 @@ +import { useRouter, useSetModal, useCurrentModal } from '@rocket.chat/ui-contexts'; +import { useCallback } from 'react'; + +import { useExternalLink } from '../../../hooks/useExternalLink'; +import { useIsEnterprise } from '../../../hooks/useIsEnterprise'; + +const TALK_TO_SALES_URL = 'https://go.rocket.chat/i/contact-sales'; + +export const useUpsellActions = (hasLicenseModule = false) => { + const router = useRouter(); + const setModal = useSetModal(); + const handleOpenLink = useExternalLink(); + const isModalOpen = useCurrentModal() !== null; + + const { data } = useIsEnterprise(); + const shouldShowUpsell = !data?.isEnterprise || !hasLicenseModule; + + const handleGoFullyFeatured = useCallback(() => { + setModal(null); + router.navigate('/admin/upgrade/go-fully-featured-registered'); + }, [router, setModal]); + + const handleTalkToSales = useCallback(() => { + setModal(null); + handleOpenLink(TALK_TO_SALES_URL); + }, [handleOpenLink, setModal]); + + return { isModalOpen, shouldShowUpsell, handleGoFullyFeatured, handleTalkToSales }; +}; diff --git a/apps/meteor/client/components/GenericUpsellModal/index.ts b/apps/meteor/client/components/GenericUpsellModal/index.ts new file mode 100644 index 000000000000..0c93e070adf2 --- /dev/null +++ b/apps/meteor/client/components/GenericUpsellModal/index.ts @@ -0,0 +1 @@ +export { default } from './GenericUpsellModal'; diff --git a/apps/meteor/client/views/marketplace/UnlimitedAppsUpsellModal.tsx b/apps/meteor/client/views/marketplace/UnlimitedAppsUpsellModal.tsx index ec3037fa37b9..5c2f4adbd1c7 100644 --- a/apps/meteor/client/views/marketplace/UnlimitedAppsUpsellModal.tsx +++ b/apps/meteor/client/views/marketplace/UnlimitedAppsUpsellModal.tsx @@ -2,20 +2,25 @@ import { useSetting, useTranslation } from '@rocket.chat/ui-contexts'; import React from 'react'; import GenericUpsellModal from '../../components/GenericUpsellModal'; +import { useUpsellActions } from '../../components/GenericUpsellModal/hooks'; -const UnlimitedAppsUpsellModal = () => { +const UnlimitedAppsUpsellModal = ({ onClose }: { onClose: () => void }) => { const t = useTranslation(); - const cloudWorkspaceHadTrial = useSetting('Cloud_Workspace_Had_Trial') as boolean; + const cloudWorkspaceHadTrial = useSetting('Cloud_Workspace_Had_Trial'); + const { handleGoFullyFeatured, handleTalkToSales } = useUpsellActions(); return ( ); }; - export default UnlimitedAppsUpsellModal; diff --git a/apps/meteor/client/views/marketplace/components/MarketplaceHeader.tsx b/apps/meteor/client/views/marketplace/components/MarketplaceHeader.tsx index e0c12b73cf9b..f93cb1fcd339 100644 --- a/apps/meteor/client/views/marketplace/components/MarketplaceHeader.tsx +++ b/apps/meteor/client/views/marketplace/components/MarketplaceHeader.tsx @@ -33,7 +33,7 @@ const MarketplaceHeader = ({ title }: { title: string }): ReactElement | null => {isAdmin && result.isSuccess && !result.data.hasUnlimitedApps && (