44 add blocking middleware payment failed (#4339)

* Add info ui component

* Add info in billing settings

* Add billing middleware

* Handle subscription canceled webhook event

* Stop deleting billingSubscription when subscription canceled

* Handle subscription unpaid recovery

* Handle subscription canceled status

* Fix test

* Add test

* Fix test chatSupport display

* Fix design
This commit is contained in:
martmull
2024-03-07 17:22:58 +01:00
committed by GitHub
parent af6ffbcc68
commit 4a7a629824
11 changed files with 354 additions and 58 deletions

View File

@ -0,0 +1,65 @@
import React from 'react';
import { css, useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { IconInfoCircle } from '@/ui/display/icon';
import { Button } from '@/ui/input/button/components/Button.tsx';
export type InfoAccent = 'blue' | 'danger';
export type InfoProps = {
accent?: InfoAccent;
text: string;
buttonTitle: string;
onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
};
const StyledTextContainer = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
`;
const StyledInfo = styled.div<Pick<InfoProps, 'accent'>>`
align-items: center;
border-radius: ${({ theme }) => theme.border.radius.md};
display: flex;
font-weight: ${({ theme }) => theme.font.weight.medium};
justify-content: space-between;
max-width: 512px;
padding: ${({ theme }) => theme.spacing(2)};
${({ theme, accent }) => {
switch (accent) {
case 'blue':
return css`
background: ${theme.color.blueAccent20};
color: ${theme.color.blue50};
`;
case 'danger':
return css`
background: ${theme.color.red10};
color: ${theme.color.red};
`;
}
}}
`;
export const Info = ({
accent = 'blue',
text,
buttonTitle,
onClick,
}: InfoProps) => {
const theme = useTheme();
return (
<StyledInfo accent={accent}>
<StyledTextContainer>
<IconInfoCircle size={theme.icon.size.md} />
{text}
</StyledTextContainer>
<Button
title={buttonTitle}
onClick={onClick}
size={'small'}
variant={'secondary'}
/>
</StyledInfo>
);
};

View File

@ -0,0 +1,45 @@
import { Meta, StoryObj } from '@storybook/react';
import { Info, InfoAccent } from '@/ui/display/info/components/Info.tsx';
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator.tsx';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator.tsx';
import { CatalogStory } from '~/testing/types.ts';
const meta: Meta<typeof Info> = {
title: 'UI/Display/Info/Info',
component: Info,
};
export default meta;
type Story = StoryObj<typeof Info>;
export const Default: Story = {
args: {
accent: 'blue',
text: 'An info component',
buttonTitle: 'Update',
},
decorators: [ComponentDecorator],
};
export const Catalog: CatalogStory<Story, typeof Info> = {
args: {
text: 'An info component',
buttonTitle: 'Update',
},
argTypes: {
accent: { control: false },
},
parameters: {
catalog: {
dimensions: [
{
name: 'accents',
values: ['blue', 'danger'] satisfies InfoAccent[],
props: (accent: InfoAccent) => ({ accent }),
},
],
},
},
decorators: [CatalogDecorator],
};

View File

@ -76,7 +76,13 @@ export const DefaultLayout = ({ children }: DefaultLayoutProps) => {
const isMatchingLocation = useIsMatchingLocation();
const showAuthModal = useMemo(() => {
return (
(onboardingStatus && onboardingStatus !== OnboardingStatus.Completed) ||
(onboardingStatus &&
[
OnboardingStatus.Incomplete,
OnboardingStatus.OngoingUserCreation,
OnboardingStatus.OngoingProfileCreation,
OnboardingStatus.OngoingWorkspaceActivation,
].includes(onboardingStatus)) ||
isMatchingLocation(AppPath.ResetPassword)
);
}, [isMatchingLocation, onboardingStatus]);