Skip to content
Merged
19 changes: 19 additions & 0 deletions static/gsApp/components/organizationSubscriptionContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type React from 'react';

import OrganizationContainer from 'sentry/views/organizationContainer';

import SubscriptionContext from 'getsentry/components/subscriptionContext';

type Props = {
children: React.JSX.Element;
};

function OrganizationSubscriptionContext({children}: Props) {
return (
<OrganizationContainer>
<SubscriptionContext>{children}</SubscriptionContext>
</OrganizationContainer>
);
}

export default OrganizationSubscriptionContext;
24 changes: 23 additions & 1 deletion static/gsApp/hooks/rootRoutes.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
import type {SentryRouteObject} from 'sentry/components/route';
import {makeLazyloadComponent as make} from 'sentry/makeLazyloadComponent';
import errorHandler from 'sentry/utils/errorHandler';

const rootRoutes = (): SentryRouteObject => ({});
import OrganizationSubscriptionContext from 'getsentry/components/organizationSubscriptionContext';

const rootRoutes = (): SentryRouteObject => ({
children: [
{
// TODO(checkout v3): change this to the correct path (/settings/billing/checkout/)
// when GA'd
path: '/checkout-v3/',
component: errorHandler(OrganizationSubscriptionContext),
deprecatedRouteProps: true,
customerDomainOnlyRoute: true,
children: [
{
index: true,
component: make(() => import('../views/decideCheckout')),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use absolute path here

deprecatedRouteProps: true,
},
],
},
],
});

export default rootRoutes;
1 change: 1 addition & 0 deletions static/gsApp/hooks/settingsRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const settingsRoutes = (): SentryRouteObject => ({
redirectTo: 'overview/',
},
{
// TODO(checkout v3): This should be removed when checkout v3 is GA'd
path: 'checkout/',
name: 'Change',
component: errorHandler(SubscriptionContext),
Expand Down
74 changes: 71 additions & 3 deletions static/gsApp/views/amCheckout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,22 @@ import moment from 'moment-timezone';

import type {Client} from 'sentry/api';
import {Alert} from 'sentry/components/core/alert';
import {Button} from 'sentry/components/core/button';
import {LinkButton} from 'sentry/components/core/button/linkButton';
import {ExternalLink} from 'sentry/components/core/link';
import LoadingError from 'sentry/components/loadingError';
import LoadingIndicator from 'sentry/components/loadingIndicator';
import LogoSentry from 'sentry/components/logoSentry';
import Panel from 'sentry/components/panels/panel';
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
import TextOverflow from 'sentry/components/textOverflow';
import {IconArrow} from 'sentry/icons';
import {t, tct} from 'sentry/locale';
import ConfigStore from 'sentry/stores/configStore';
import type {DataCategory} from 'sentry/types/core';
import type {RouteComponentProps} from 'sentry/types/legacyReactRouter';
import type {Organization} from 'sentry/types/organization';
import {browserHistory} from 'sentry/utils/browserHistory';
import type {QueryClient} from 'sentry/utils/queryClient';
import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import withApi from 'sentry/utils/withApi';
Expand Down Expand Up @@ -122,6 +126,12 @@ class AMCheckout extends Component<Props, State> {
) {
props.onToggleLegacy(props.subscription.planTier);
}
// TODO(checkout v3): remove these checks once checkout v3 is GA'd
if (props.location?.pathname.includes('checkout-v3') && !props.isNewCheckout) {
browserHistory.push(`/settings/${props.organization.slug}/billing/checkout/`);
} else if (!props.location?.pathname.includes('checkout-v3') && props.isNewCheckout) {
browserHistory.push(`/checkout-v3/`);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have a backlog ticket to refactor this component to FC so we can use useNavigate, but until then i'm not sure if there's anything we can use beyond browserHistory

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah this is fine for now

}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Navigation in Constructor Causes React Warnings

Navigation logic is being executed in the component's constructor. This can cause side effects during the render phase, potentially leading to React warnings, unpredictable navigation, or infinite redirect loops.

Fix in Cursor Fix in Web

let step = 1;
if (props.location?.hash) {
const stepMatch = /^#step(\d)$/.exec(props.location.hash);
Expand Down Expand Up @@ -771,12 +781,21 @@ class AMCheckout extends Component<Props, State> {
const isOnSponsoredPartnerPlan =
(subscription.partner?.isActive && subscription.isSponsored) || false;

const ParentComponent = isNewCheckout ? FullScreenContainer : Fragment;

return (
<Fragment>
<ParentComponent>
<SentryDocumentTitle
title={t('Change Subscription')}
orgSlug={organization.slug}
/>
{isNewCheckout && (
<FullScreenHeader>
<HeaderContent>
<LogoSentry />
</HeaderContent>
</FullScreenHeader>
)}
{isOnSponsoredPartnerPlan && (
<Alert.Container>
<Alert type="info">
Expand All @@ -800,9 +819,20 @@ class AMCheckout extends Component<Props, State> {
data-test-id="change-subscription"
/>
)}

<CheckoutContainer isNewCheckout={!!isNewCheckout}>
<div>
{isNewCheckout && (
<BackButton
borderless
aria-label={t('Back to Subscription Overview')}
onClick={() => {
browserHistory.push(`/settings/${organization.slug}/billing/`);
}}
>
<IconArrow direction="left" />
<span>{t('Back')}</span>
</BackButton>
)}
{this.renderPartnerAlert()}
<CheckoutStepsContainer
data-test-id="checkout-steps"
Expand Down Expand Up @@ -863,11 +893,42 @@ class AMCheckout extends Component<Props, State> {
)}
</SidePanel>
</CheckoutContainer>
</Fragment>
</ParentComponent>
);
}
}

const FullScreenContainer = styled('div')`
display: flex;
flex-direction: column;
align-items: center;
background: ${p => p.theme.background};
`;

const FullScreenHeader = styled('header')`
width: 100%;
border-bottom: 1px solid ${p => p.theme.border};
display: flex;
justify-content: center;
`;

const HeaderContent = styled('div')`
width: 100%;
display: flex;
justify-content: flex-start;
padding: ${p => p.theme.space['2xl']};
max-width: ${p => p.theme.breakpoints.xl};
`;

const BackButton = styled(Button)`
align-self: flex-start;
padding: 0;

& span {
margin-left: ${p => p.theme.space.sm};
}
`;

const CheckoutContainer = styled('div')<{isNewCheckout: boolean}>`
display: grid;
gap: ${p => p.theme.space['2xl']};
Expand All @@ -877,6 +938,13 @@ const CheckoutContainer = styled('div')<{isNewCheckout: boolean}>`
p.isNewCheckout ? p.theme.breakpoints.md : p.theme.breakpoints.lg}) {
grid-template-columns: auto;
}

${p =>
p.isNewCheckout &&
css`
max-width: ${p.theme.breakpoints.xl};
padding: ${p.theme.space['2xl']};
`}
`;

const SidePanel = styled('div')`
Expand Down
Loading