redeemPromoCode.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import styled from '@emotion/styled';
  2. import {addSuccessMessage} from 'sentry/actionCreators/indicator';
  3. import {fetchOrganizationDetails} from 'sentry/actionCreators/organization';
  4. import type {Client} from 'sentry/api';
  5. import ApiForm from 'sentry/components/forms/apiForm';
  6. import TextField from 'sentry/components/forms/fields/textField';
  7. import Panel from 'sentry/components/panels/panel';
  8. import PanelBody from 'sentry/components/panels/panelBody';
  9. import PanelHeader from 'sentry/components/panels/panelHeader';
  10. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  11. import Text from 'sentry/components/text';
  12. import {t} from 'sentry/locale';
  13. import {space} from 'sentry/styles/space';
  14. import type {RouteComponentProps} from 'sentry/types/legacyReactRouter';
  15. import type {Organization} from 'sentry/types/organization';
  16. import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyticsParams';
  17. import withApi from 'sentry/utils/withApi';
  18. import withOrganization from 'sentry/utils/withOrganization';
  19. import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
  20. import SubscriptionContext from 'getsentry/components/subscriptionContext';
  21. import withSubscription from 'getsentry/components/withSubscription';
  22. import SubscriptionStore from 'getsentry/stores/subscriptionStore';
  23. import type {Subscription} from 'getsentry/types';
  24. import {isDisabledByPartner} from 'getsentry/utils/partnerships';
  25. import PartnershipNote from 'getsentry/views/subscriptionPage/partnershipNote';
  26. type Props = RouteComponentProps<unknown, unknown> & {
  27. api: Client;
  28. organization: Organization;
  29. subscription: Subscription;
  30. };
  31. function RedeemPromoCode({organization, api, subscription}: Props) {
  32. const {accountBalance} = subscription;
  33. const accountCredit =
  34. accountBalance < 0 ? Number((accountBalance / -100).toFixed(2)) : 0;
  35. useRouteAnalyticsParams({
  36. account_credit: accountCredit,
  37. });
  38. const AccountCredit =
  39. accountCredit > 0 ? (
  40. <AccountCreditWrapper id="account-balance">
  41. <ItemContainer>{t('Your account credit:')}</ItemContainer>
  42. <ItemContainer>{'$' + accountCredit.toString()}</ItemContainer>
  43. </AccountCreditWrapper>
  44. ) : null;
  45. if (isDisabledByPartner(subscription)) {
  46. return <PartnershipNote subscription={subscription} />;
  47. }
  48. return (
  49. <SubscriptionContext>
  50. <div className="ref-redeem-code">
  51. <SentryDocumentTitle title={t('Redeem Promo Code')} orgSlug={organization.slug} />
  52. <SettingsPageHeader title={t('Redeem Promotional Code')} />
  53. <Panel>
  54. <PanelHeader>{t('Redeem Promotional Code')}</PanelHeader>
  55. <PanelBody>
  56. <ApiForm
  57. extraButton={AccountCredit}
  58. apiMethod="PUT"
  59. apiEndpoint={`/customers/${organization.slug}/redeem-promo/`}
  60. submitLabel={t('Redeem')}
  61. resetOnError
  62. onSubmitSuccess={resp => {
  63. const msg =
  64. resp?.details || t('Successfully applied credit to your organization');
  65. SubscriptionStore.loadData(organization.slug, null, {
  66. markStartedTrial: true,
  67. });
  68. fetchOrganizationDetails(api, organization.slug);
  69. addSuccessMessage(msg);
  70. }}
  71. >
  72. <Text>
  73. <p>
  74. {t(
  75. 'Received a promotional code? Enter it here to apply credit to your organization.'
  76. )}
  77. </p>
  78. </Text>
  79. <TextField name="code" label={t('Promotional Code')} required />
  80. </ApiForm>
  81. </PanelBody>
  82. </Panel>
  83. </div>
  84. </SubscriptionContext>
  85. );
  86. }
  87. export default withApi(withSubscription(withOrganization(RedeemPromoCode)));
  88. const AccountCreditWrapper = styled('div')`
  89. width: 100%;
  90. display: flex;
  91. justify-content: flex-start;
  92. gap: ${space(1)};
  93. padding: 0 ${space(2)};
  94. `;
  95. const ItemContainer = styled('span')`
  96. margin: auto 0;
  97. `;