partnerPlanEndingBanner.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import styled from '@emotion/styled';
  2. import PartnerPlanEndingBackground from 'getsentry-images/partnership/plan-ending.svg';
  3. import {LinkButton} from 'sentry/components/button';
  4. import {Tag} from 'sentry/components/core/badge/tag';
  5. import {IconClock} from 'sentry/icons';
  6. import {t, tn} from 'sentry/locale';
  7. import {space} from 'sentry/styles/space';
  8. import type {Organization} from 'sentry/types/organization';
  9. import type {Subscription} from 'getsentry/types';
  10. import {getContractDaysLeft, isTeamPlanFamily} from 'getsentry/utils/billing';
  11. import trackGetsentryAnalytics from 'getsentry/utils/trackGetsentryAnalytics';
  12. function PartnerPlanEndingBanner({
  13. subscription,
  14. organization,
  15. }: {
  16. organization: Organization;
  17. subscription: Subscription;
  18. }) {
  19. const daysLeft = getContractDaysLeft(subscription);
  20. const hasPendingUpgrade =
  21. subscription.pendingChanges !== null &&
  22. subscription.pendingChanges?.planDetails.price > 0;
  23. if (
  24. hasPendingUpgrade ||
  25. !subscription.partner ||
  26. !organization.features.includes('partner-billing-migration') ||
  27. daysLeft > 30 ||
  28. daysLeft < 0
  29. ) {
  30. return null;
  31. }
  32. const handleAnalytics = () => {
  33. trackGetsentryAnalytics('partner_billing_migration.banner.clicked_cta', {
  34. subscription,
  35. organization,
  36. daysLeft,
  37. partner: subscription.partner?.partnership.id,
  38. });
  39. };
  40. const partnerPlanName = subscription.partner?.partnership.displayName;
  41. const planToUpgradeTo = isTeamPlanFamily(subscription.planDetails)
  42. ? 'Team'
  43. : 'Business';
  44. return (
  45. <PartnerPlanEndingBannerWrapper data-test-id="partner-plan-ending-banner">
  46. <div>
  47. <PartnerPlanEndingText>
  48. <PartnerPlanEndingBannerTitle>
  49. {t('Your current promotional plan is ending')}
  50. <DaysLeftTag type="error" icon={<IconClock size="xs" />}>
  51. {tn('%s day left', '%s days left', daysLeft)}
  52. </DaysLeftTag>
  53. </PartnerPlanEndingBannerTitle>
  54. <div>
  55. {t(
  56. 'Your one year promotional plan with Sentry and %s is ending. Upgrade to a Sentry billing plan today to continue to enjoy all the Sentry goodness.',
  57. partnerPlanName
  58. )}
  59. </div>
  60. <LinkButton
  61. priority="primary"
  62. analyticsEventKey="partner_plan_ending_banner.manage_subscription"
  63. analyticsEventName="Partner Plan Ending Banner: Manage Subscription"
  64. size="md"
  65. onClick={() => handleAnalytics()}
  66. to={`/settings/${organization.slug}/billing/checkout/?referrer=partner_plan_ending_banner`}
  67. >
  68. {t('Upgrade to %s', planToUpgradeTo)}
  69. </LinkButton>
  70. </PartnerPlanEndingText>
  71. </div>
  72. <IllustrationContainer src={PartnerPlanEndingBackground} />
  73. </PartnerPlanEndingBannerWrapper>
  74. );
  75. }
  76. const PartnerPlanEndingBannerWrapper = styled('div')`
  77. border: 1px solid ${p => p.theme.border};
  78. border-radius: ${p => p.theme.borderRadius};
  79. background: ${p => p.theme.background};
  80. margin-bottom: ${space(2)};
  81. display: flex;
  82. justify-content: space-between;
  83. align-items: center;
  84. `;
  85. const PartnerPlanEndingText = styled('div')`
  86. padding: ${space(2)};
  87. display: flex;
  88. flex-direction: column;
  89. gap: ${space(1)};
  90. align-items: flex-start;
  91. `;
  92. const PartnerPlanEndingBannerTitle = styled('div')`
  93. font-size: ${p => p.theme.fontSizeExtraLarge};
  94. font-weight: 600;
  95. display: flex;
  96. gap: ${space(1)};
  97. align-items: center;
  98. `;
  99. const DaysLeftTag = styled(Tag)`
  100. font-weight: 400;
  101. `;
  102. const IllustrationContainer = styled('img')`
  103. display: none;
  104. @media (min-width: ${p => p.theme.breakpoints.xlarge}) {
  105. display: block;
  106. border-radius: 0 ${p => p.theme.borderRadius} ${p => p.theme.borderRadius} 0;
  107. pointer-events: none;
  108. flex-grow: 1;
  109. }
  110. `;
  111. export default PartnerPlanEndingBanner;