insightsDateRangeQueryLimitFooter.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import styled from '@emotion/styled';
  2. import {Button, type ButtonProps, LinkButton} from 'sentry/components/button';
  3. import {t} from 'sentry/locale';
  4. import {space} from 'sentry/styles/space';
  5. import type {Organization} from 'sentry/types/organization';
  6. import normalizeUrl from 'sentry/utils/url/normalizeUrl';
  7. import withOrganization from 'sentry/utils/withOrganization';
  8. import {openUpsellModal} from 'getsentry/actionCreators/modal';
  9. import UpgradeOrTrialButton from 'getsentry/components/upgradeOrTrialButton';
  10. import withSubscription from 'getsentry/components/withSubscription';
  11. import {useBillingConfig} from 'getsentry/hooks/useBillingConfig';
  12. import type {Subscription} from 'getsentry/types';
  13. interface Props {
  14. organization: Organization;
  15. subscription: Subscription;
  16. }
  17. const DESCRIPTION = t(
  18. 'To view more trends for your Performance data, upgrade to Business.'
  19. );
  20. const QUERY_LIMIT_REFERRER = 'insights-query-limit-footer';
  21. const BUTTON_SIZE: ButtonProps['size'] = 'sm';
  22. /** @internal exported for tests only */
  23. export function InsightsDateRangeQueryLimitFooter({organization, subscription}: Props) {
  24. const checkoutUrl = normalizeUrl(
  25. `/settings/${organization.slug}/billing/checkout/?referrer=checkout-${QUERY_LIMIT_REFERRER}`
  26. );
  27. const source = QUERY_LIMIT_REFERRER;
  28. const canTrial = subscription.canTrial;
  29. const shouldShowQueryLimitFooter = useHasRequiredFeatures(organization, subscription);
  30. if (shouldShowQueryLimitFooter) {
  31. return (
  32. <Container>
  33. <DescriptionContainer>{DESCRIPTION}</DescriptionContainer>
  34. <ButtonContainer>
  35. <UpgradeOrTrialButton
  36. subscription={subscription}
  37. priority="primary"
  38. size={BUTTON_SIZE}
  39. organization={organization}
  40. source={source}
  41. aria-label="Start Trial"
  42. >
  43. {canTrial ? t('Start Trial') : t('Upgrade Now')}
  44. </UpgradeOrTrialButton>
  45. {canTrial && (
  46. <LinkButton size={BUTTON_SIZE} to={checkoutUrl}>
  47. {t('Upgrade Now')}
  48. </LinkButton>
  49. )}
  50. {!canTrial && (
  51. <Button
  52. size={BUTTON_SIZE}
  53. onClick={() =>
  54. openUpsellModal({
  55. organization,
  56. source,
  57. defaultSelection: 'insights-modules',
  58. })
  59. }
  60. >
  61. {t('Learn More')}
  62. </Button>
  63. )}
  64. </ButtonContainer>
  65. </Container>
  66. );
  67. }
  68. return undefined;
  69. }
  70. const ButtonContainer = styled('div')`
  71. display: flex;
  72. gap: ${space(1)};
  73. `;
  74. const Container = styled('div')`
  75. display: flex;
  76. flex-direction: column;
  77. gap: ${space(1)};
  78. padding: ${space(0.5)};
  79. `;
  80. const DescriptionContainer = styled('div')`
  81. font-size: 12px;
  82. `;
  83. const useHasRequiredFeatures = (
  84. organization: Organization,
  85. subscription: Subscription
  86. ) => {
  87. const {data: billingConfig} = useBillingConfig({organization, subscription});
  88. const subscriptionPlan = subscription.planDetails;
  89. const subscriptionPlanFeatures = subscriptionPlan?.features ?? [];
  90. const trialPlan = subscription.trialPlan
  91. ? billingConfig?.planList?.find(plan => plan.id === subscription.trialPlan)
  92. : undefined;
  93. const trialPlanFeatures = trialPlan?.features ?? [];
  94. const enabledFeatures = [
  95. ...new Set([
  96. ...subscriptionPlanFeatures,
  97. ...trialPlanFeatures,
  98. ...organization.features,
  99. ]),
  100. ];
  101. return enabledFeatures.includes('insights-query-date-range-limit');
  102. };
  103. export default withOrganization(
  104. withSubscription(InsightsDateRangeQueryLimitFooter, {noLoader: true})
  105. );