fix: Stripe payment integration

This commit is contained in:
Ahmed Bouhuolia
2024-09-23 13:21:54 +02:00
parent 9ba651decb
commit 8109236e72
19 changed files with 287 additions and 369 deletions

View File

@@ -15,7 +15,6 @@ export interface StripeInvoiceCheckoutSessionPOJO {
redirectTo: string;
}
export interface StripeWebhookEventPayload {
event: any;
}
}

View File

@@ -2,6 +2,7 @@ import { Inject, Service } from 'typedi';
import HasTenancyService from '../Tenancy/TenancyService';
import { GetPaymentMethodsPOJO } from './types';
import config from '@/config';
import { isStripePaymentConfigured } from './utils';
@Service()
export class GetPaymentMethodsStateService {
@@ -31,11 +32,13 @@ export class GetPaymentMethodsStateService {
const stripePublishableKey = config.stripePayment.publishableKey;
const stripeCurrencies = ['USD', 'EUR'];
const stripeRedirectUrl = 'https://your-stripe-redirect-url.com';
const isStripeServerConfigured = isStripePaymentConfigured();
const paymentMethodPOJO: GetPaymentMethodsPOJO = {
stripe: {
isStripeAccountCreated,
isStripePaymentActive,
isStripeServerConfigured,
stripeAccountId,
stripePaymentMethodId,
stripePublishableKey,

View File

@@ -17,6 +17,7 @@ export interface GetPaymentMethodsPOJO {
stripe: {
isStripeAccountCreated: boolean;
isStripePaymentActive: boolean;
isStripeServerConfigured: boolean;
stripeAccountId: string | null;
stripePaymentMethodId: number | null;
stripePublishableKey: string | null;

View File

@@ -0,0 +1,9 @@
import config from '@/config';
export const isStripePaymentConfigured = () => {
return (
config.stripePayment.secretKey &&
config.stripePayment.publishableKey &&
config.stripePayment.webhooksSecret
);
};

View File

@@ -1,6 +1,6 @@
import { Inject, Service } from 'typedi';
import { StripePaymentService } from '@/services/StripePayment/StripePaymentService';
import HasTenancyService from '@/services/Tenancy/TenancyService';
import { Inject, Service } from 'typedi';
import { CreateStripeAccountDTO } from './types';
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import events from '@/subscribers/events';
@@ -8,17 +8,17 @@ import events from '@/subscribers/events';
@Service()
export class CreateStripeAccountService {
@Inject()
private stripePaymentService: StripePaymentService;
private tenancy: HasTenancyService;
@Inject()
private tenancy: HasTenancyService;
private stripePaymentService: StripePaymentService;
@Inject()
private eventPublisher: EventPublisher;
/**
* Creates a new Stripe account.
* @param {number} tenantId
* @param {number} tenantI
* @param {CreateStripeAccountDTO} stripeAccountDTO
* @returns {Promise<string>}
*/

View File

@@ -1,5 +0,0 @@
import { StripeIntegration2 } from '@/containers/StripePayment/StripeIntegration';
export default function IntegrationsPage() {
return <StripeIntegration2 />
}

View File

@@ -1,35 +1,20 @@
// @ts-nocheck
import React, { useEffect } from 'react';
import styled from 'styled-components';
import {
Button,
Classes,
Intent,
Menu,
MenuItem,
Popover,
Tag,
Text,
} from '@blueprintjs/core';
import { AppToaster, Box, Card, Group, Stack } from '@/components';
import { StripeLogo } from '@/icons/StripeLogo';
import {
PaymentMethodsBoot,
usePaymentMethodsBoot,
} from './PreferencesPaymentMethodsBoot';
import { Classes, Text } from '@blueprintjs/core';
import { Box, Stack } from '@/components';
import { PaymentMethodsBoot } from './PreferencesPaymentMethodsBoot';
import { StripePreSetupDialog } from './dialogs/StripePreSetupDialog/StripePreSetupDialog';
import { DialogsName } from '@/constants/dialogs';
import {
useAlertActions,
useChangePreferencesPageTitle,
useDialogActions,
useDrawerActions,
} from '@/hooks/state';
import { useCreateStripeAccountLink } from '@/hooks/query/stripe-integration';
import { useChangePreferencesPageTitle } from '@/hooks/state';
import { StripeIntegrationEditDrawer } from './drawers/StripeIntegrationEditDrawer';
import { StripePaymentMethod } from './StripePaymentMethod';
import { DialogsName } from '@/constants/dialogs';
import { DRAWERS } from '@/constants/drawers';
import { MoreIcon } from '@/icons/More';
/**
* Payment methods page.
* @returns {JSX.Element}
*/
export default function PreferencesPaymentMethodsPage() {
const changePageTitle = useChangePreferencesPageTitle();
@@ -58,141 +43,8 @@ export default function PreferencesPaymentMethodsPage() {
);
}
function StripePaymentMethod() {
const { openDialog } = useDialogActions();
const { openDrawer } = useDrawerActions();
const { openAlert } = useAlertActions();
const { paymentMethodsState } = usePaymentMethodsBoot();
const stripeState = paymentMethodsState?.stripe;
const isAccountCreated = stripeState?.isStripeAccountCreated;
const isAccountActive = stripeState?.isStripePaymentActive;
const stripeAccountId = stripeState?.stripeAccountId;
const stripePaymentMethodId = stripeState?.stripePaymentMethodId;
const {
mutateAsync: createStripeAccountLink,
isLoading: isCreateStripeLinkLoading,
} = useCreateStripeAccountLink();
// Handle Stripe setup button click.
const handleSetUpBtnClick = () => {
openDialog(DialogsName.StripeSetup);
};
// Handle complete Stripe setup button click.
const handleCompleteSetUpBtnClick = () => {
createStripeAccountLink({ stripeAccountId })
.then((res) => {
const { clientSecret } = res;
if (clientSecret.url) {
window.open(clientSecret.url, '_blank');
}
})
.catch(() => {
AppToaster.show({
message: 'Something went wrong.',
intent: Intent.DANGER,
});
});
};
// Handle edit button click.
const handleEditBtnClick = () => {
openDrawer(DRAWERS.STRIPE_PAYMENT_INTEGRATION_EDIT);
};
// Handle delete connection button click.
const handleDeleteConnectionClick = () => {
openAlert('delete-stripe-payment-method', {
paymentMethodId: stripePaymentMethodId,
});
};
return (
<Card style={{ margin: 0 }}>
<Group position="apart">
<Group>
<StripeLogo />
{isAccountActive && (
<Tag minimal intent={Intent.SUCCESS}>
Active
</Tag>
)}
</Group>
<Group spacing={10}>
{isAccountActive && (
<Button small onClick={handleEditBtnClick}>
Edit
</Button>
)}
{!isAccountCreated && (
<Button intent={Intent.PRIMARY} small onClick={handleSetUpBtnClick}>
Set it Up
</Button>
)}
{isAccountCreated && !isAccountActive && (
<Button
intent={Intent.PRIMARY}
small
onClick={handleCompleteSetUpBtnClick}
loading={isCreateStripeLinkLoading}
>
Complete Stripe Set Up
</Button>
)}
{isAccountCreated && (
<Popover
content={
<Menu>
<MenuItem
intent={Intent.DANGER}
text={'Delete Connection'}
onClick={handleDeleteConnectionClick}
/>
</Menu>
}
>
<Button small icon={<MoreIcon size={16} />} />
</Popover>
)}
</Group>
</Group>
<PaymentDescription
className={Classes.TEXT_MUTED}
style={{ fontSize: 13 }}
>
Stripe is an online payment processing platform that allows you to
receive one-time and recurring payments securely from customers. It also
manages all your payments and makes reconciliation a breeze. You can set
it up in no time and get paid faster. 
</PaymentDescription>
<PaymentFooter>
<Text>
<a href={'#'}>View Stripe's Transaction Fees</a>
</Text>
</PaymentFooter>
</Card>
);
}
const PaymentMethodsRoot = styled(Box)`
witdth: 100%;
max-width: 700px;
margin: 20px;
`;
const PaymentDescription = styled(Text)`
font-size: 13px;
margin-top: 12px;
`;
const PaymentFooter = styled(Box)`
margin-top: 14px;
font-size: 12px;
`;

View File

@@ -0,0 +1,172 @@
// @ts-nocheck
import React from 'react';
import styled from 'styled-components';
import {
Button,
Classes,
Intent,
Menu,
MenuItem,
Popover,
Tag,
Text,
} from '@blueprintjs/core';
import { AppToaster, Box, Card, Group, Stack } from '@/components';
import { StripeLogo } from '@/icons/StripeLogo';
import { usePaymentMethodsBoot } from './PreferencesPaymentMethodsBoot';
import { DialogsName } from '@/constants/dialogs';
import {
useAlertActions,
useDialogActions,
useDrawerActions,
} from '@/hooks/state';
import { useCreateStripeAccountLink } from '@/hooks/query/stripe-integration';
import { DRAWERS } from '@/constants/drawers';
import { MoreIcon } from '@/icons/More';
import { STRIPE_PRICING_LINK } from './constants';
export function StripePaymentMethod() {
const { openDialog } = useDialogActions();
const { openDrawer } = useDrawerActions();
const { openAlert } = useAlertActions();
const { paymentMethodsState } = usePaymentMethodsBoot();
const stripeState = paymentMethodsState?.stripe;
const isAccountCreated = stripeState?.isStripeAccountCreated;
const isAccountActive = stripeState?.isStripePaymentActive;
const stripeAccountId = stripeState?.stripeAccountId;
const stripePaymentMethodId = stripeState?.stripePaymentMethodId;
const isStripeServerConfigured = stripeState?.isStripeServerConfigured;
const {
mutateAsync: createStripeAccountLink,
isLoading: isCreateStripeLinkLoading,
} = useCreateStripeAccountLink();
// Handle Stripe setup button click.
const handleSetUpBtnClick = () => {
openDialog(DialogsName.StripeSetup);
};
// Handle complete Stripe setup button click.
const handleCompleteSetUpBtnClick = () => {
createStripeAccountLink({ stripeAccountId })
.then((res) => {
const { clientSecret } = res;
if (clientSecret.url) {
window.open(clientSecret.url, '_blank');
}
})
.catch(() => {
AppToaster.show({
message: 'Something went wrong.',
intent: Intent.DANGER,
});
});
};
// Handle edit button click.
const handleEditBtnClick = () => {
openDrawer(DRAWERS.STRIPE_PAYMENT_INTEGRATION_EDIT, {
stripePaymentMethodId: stripePaymentMethodId,
});
};
// Handle delete connection button click.
const handleDeleteConnectionClick = () => {
openAlert('delete-stripe-payment-method', {
paymentMethodId: stripePaymentMethodId,
});
};
return (
<Card style={{ margin: 0 }}>
<Group position="apart">
<Group>
<StripeLogo />
{isAccountActive && (
<Tag minimal intent={Intent.SUCCESS}>
Active
</Tag>
)}
</Group>
<Group spacing={10}>
{isAccountActive && (
<Button small onClick={handleEditBtnClick}>
Edit
</Button>
)}
{!isAccountCreated && (
<Button intent={Intent.PRIMARY} small onClick={handleSetUpBtnClick}>
Set it Up
</Button>
)}
{isAccountCreated && !isAccountActive && (
<Button
intent={Intent.PRIMARY}
small
onClick={handleCompleteSetUpBtnClick}
loading={isCreateStripeLinkLoading}
>
Complete Stripe Set Up
</Button>
)}
{isAccountCreated && (
<Popover
content={
<Menu>
<MenuItem
intent={Intent.DANGER}
text={'Delete Connection'}
onClick={handleDeleteConnectionClick}
/>
</Menu>
}
>
<Button small icon={<MoreIcon size={16} />} />
</Popover>
)}
</Group>
</Group>
<PaymentDescription
className={Classes.TEXT_MUTED}
style={{ fontSize: 13 }}
>
Stripe is an online payment processing platform that allows you to
receive one-time and recurring payments securely from customers. It also
manages all your payments and makes reconciliation a breeze. You can set
it up in no time and get paid faster. 
</PaymentDescription>
<PaymentFooter>
<Stack spacing={10}>
<Text>
<a target="_blank" rel="noreferrer" href={STRIPE_PRICING_LINK}>
View Stripe's Transaction Fees
</a>
</Text>
{!isStripeServerConfigured && (
<Text style={{ color: '#CD4246' }}>
Stripe payment is not configured from the server.{' '}
</Text>
)}
</Stack>
</PaymentFooter>
</Card>
);
}
const PaymentDescription = styled(Text)`
font-size: 13px;
margin-top: 12px;
`;
const PaymentFooter = styled(Box)`
margin-top: 14px;
font-size: 12px;
`;

View File

@@ -5,7 +5,7 @@ import { Intent, Alert } from '@blueprintjs/core';
import { AppToaster, FormattedMessage as T } from '@/components';
import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect';
import withAlertActions from '@/containers/Alert/withAlertActions';
import { useDeletePaymentMethod } from '@/hooks/query/payment-methods';
import { useDeletePaymentMethod } from '@/hooks/query/payment-services';
import { compose } from '@/utils';
/**
@@ -28,7 +28,6 @@ function DeleteStripeAccountAlert({
const handleCancelOpenBill = () => {
closeAlert(name);
};
// Handle confirm bill open.
const handleConfirmBillOpen = () => {
deletePaymentMethod({ paymentMethodId })

View File

@@ -0,0 +1 @@
export const STRIPE_PRICING_LINK = 'https://stripe.com/pricing';

View File

@@ -2,6 +2,7 @@ import React, { createContext, useContext } from 'react';
import { Spinner } from '@blueprintjs/core';
import { useAccounts } from '@/hooks/query';
import { useGetPaymentMethod } from '@/hooks/query/payment-services';
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
interface StripeIntegrationEditContextType {
accounts: any;
@@ -20,7 +21,6 @@ export const useStripeIntegrationEditBoot = () => {
const context = useContext<StripeIntegrationEditContextType>(
StripeIntegrationEditContext,
);
if (!context) {
throw new Error(
'useStripeIntegrationEditContext must be used within a StripeIntegrationEditProvider',
@@ -30,9 +30,15 @@ export const useStripeIntegrationEditBoot = () => {
};
export const StripeIntegrationEditBoot: React.FC = ({ children }) => {
const {
payload: { stripePaymentMethodId },
} = useDrawerContext();
const { data: accounts, isLoading: isAccountsLoading } = useAccounts({}, {});
const { data: paymentMethod, isLoading: isPaymentMethodLoading } =
useGetPaymentMethod(9);
useGetPaymentMethod(stripePaymentMethodId, {
enabled: !!stripePaymentMethodId,
});
const value = {
// Accounts.

View File

@@ -10,8 +10,9 @@ import {
export function StripeIntegrationEditContent() {
return (
<StripeIntegrationEditBoot>
<>
<DrawerHeaderContent title={'Edit Stripe Integration'} />
<StripeIntegrationEditBoot>
<StripeIntegrationEditForm>
<DrawerBody>
@@ -23,6 +24,6 @@ export function StripeIntegrationEditContent() {
</div>
</StripeIntegrationEditForm>
</StripeIntegrationEditBoot>
</StripeIntegrationEditBoot>
</>
);
}

View File

@@ -2,7 +2,9 @@
import React from 'react';
import intl from 'react-intl-universal';
import styled from 'styled-components';
import { isEmpty } from 'lodash';
import { Button, Intent } from '@blueprintjs/core';
import { useHistory } from 'react-router-dom';
import {
FFormGroup,
FEditableText,
@@ -18,6 +20,11 @@ import { PaymentOptionsButtonPopver } from '@/containers/PaymentMethods/SelectPa
export function InvoiceFormFooterLeft() {
const { paymentServices } = useInvoiceFormContext();
const history = useHistory();
const handleSetupPaymentsClick = () => {
history.push('/preferences/payment-methods');
};
return (
<Stack spacing={20}>
@@ -60,11 +67,22 @@ export function InvoiceFormFooterLeft() {
<VisaIcon />
<MastercardIcon />
</Group>
<PaymentOptionsButtonPopver paymentMethods={paymentServices}>
<PaymentOptionsButton intent={Intent.PRIMARY} small minimal>
Payment Options
{isEmpty(paymentServices) ? (
<PaymentOptionsButton
intent={Intent.PRIMARY}
onClick={handleSetupPaymentsClick}
small
minimal
>
Setup payment gateways
</PaymentOptionsButton>
</PaymentOptionsButtonPopver>
) : (
<PaymentOptionsButtonPopver paymentMethods={paymentServices}>
<PaymentOptionsButton intent={Intent.PRIMARY} small minimal>
Payment Options
</PaymentOptionsButton>
</PaymentOptionsButtonPopver>
)}
</PaymentOptionsText>
</PaymentOptionsFormGroup>
</Stack>

View File

@@ -1,113 +0,0 @@
import React, { useState } from 'react';
import {
useCreateStripeAccount,
useCreateStripeAccountLink,
} from '@/hooks/query/stripe-integration';
export const StripeIntegration2 = () => {
const [accountCreatePending, setAccountCreatePending] = useState(false);
const [accountLinkCreatePending, setAccountLinkCreatePending] =
useState(false);
const [error, setError] = useState(false);
const [connectedAccountId, setConnectedAccountId] = useState<string>();
const { mutateAsync: createStripeAccount } = useCreateStripeAccount();
const { mutateAsync: createStripeAccountLink } = useCreateStripeAccountLink();
return (
<div className="container">
<div className="banner">
<h2>Bigcapital Technology, Inc.</h2>
</div>
<div className="content">
{!connectedAccountId && <h2>Get ready for take off</h2>}
{!connectedAccountId && (
<p>
Bigcapital Technology, Inc. is the world's leading air travel
platform: join our team of pilots to help people travel faster.
</p>
)}
{connectedAccountId && (
<h2>Add information to start accepting money</h2>
)}
{connectedAccountId && (
<p>
Matt's Mats partners with Stripe to help you receive payments and
keep your personal bank and details secure.
</p>
)}
{!accountCreatePending && !connectedAccountId && (
<button
onClick={async () => {
setAccountCreatePending(true);
setError(false);
createStripeAccount({}).then((response) => {
const { account_id: accountId } = response;
setAccountCreatePending(false);
if (accountId) {
setConnectedAccountId(accountId);
}
if (error) {
setError(true);
}
});
}}
>
Create an account!
</button>
)}
{connectedAccountId && !accountLinkCreatePending && (
<button
onClick={() => {
setAccountLinkCreatePending(true);
setError(false);
createStripeAccountLink({
stripeAccountId: connectedAccountId,
})
.then((res) => {
const { clientSecret } = res;
setAccountLinkCreatePending(false);
if (clientSecret.url) {
window.location.href = clientSecret.url;
}
})
.catch(() => {
setError(true);
});
}}
>
Add information
</button>
)}
{error && <p className="error">Something went wrong!</p>}
{(connectedAccountId ||
accountCreatePending ||
accountLinkCreatePending) && (
<div className="dev-callout">
{connectedAccountId && (
<p>
Your connected account ID is:{' '}
<code className="bold">{connectedAccountId}</code>
</p>
)}
{accountCreatePending && <p>Creating a connected account...</p>}
{accountLinkCreatePending && <p>Creating a new Account Link...</p>}
</div>
)}
<div className="info-callout">
<p>
This is a sample app for Stripe-hosted Connect onboarding.{' '}
<a
href="https://docs.stripe.com/connect/onboarding/quickstart?connect-onboarding-surface=hosted"
target="_blank"
rel="noopener noreferrer"
>
View docs
</a>
</p>
</div>
</div>
</div>
);
};

View File

@@ -1,47 +0,0 @@
import { useState, useEffect } from 'react';
import {
loadConnectAndInitialize,
StripeConnectInstance,
} from '@stripe/connect-js';
import { useCreateStripeAccountSession } from '@/hooks/query/stripe-integration';
export const useStripeConnect = (connectedAccountId?: string) => {
const [stripeConnectInstance, setStripeConnectInstance] =
useState<StripeConnectInstance | null>();
const { mutateAsync: createAccountSession } = useCreateStripeAccountSession();
useEffect(() => {
if (connectedAccountId) {
const fetchClientSecret = async (): Promise<string> => {
try {
const clientSecret = await createAccountSession({
connectedAccountId,
});
return clientSecret?.client_secret as string;
} catch (error) {
// Handle errors on the client side here
if (error instanceof Error) {
throw new Error(`An error occurred: ${error.message}`);
} else {
throw new Error('An unknown error occurred');
}
}
};
setStripeConnectInstance(
loadConnectAndInitialize({
publishableKey: 'pk_test_51PRck9BW396nDn7gxEw1uvkoGwl5BXDWnrhntQIWReiDnH2Zdm7uL0RSvzKN6SR6ELHDK99dF9UbVEumgTu8k0oN00pP0J91Lx',
fetchClientSecret,
appearance: {
overlays: 'dialog',
variables: {
colorPrimary: '#ffffff',
},
},
}),
);
}
}, [connectedAccountId, createAccountSession]);
return stripeConnectInstance;
};

View File

@@ -7,25 +7,6 @@ import {
import useApiRequest from '../useRequest';
// # Delete payment method
// -----------------------------------------
interface DeletePaymentMethodValues {
paymentMethodId: number;
}
export const useDeletePaymentMethod = (
options?: UseMutationOptions<void, Error, DeletePaymentMethodValues>,
): UseMutationResult<void, Error, DeletePaymentMethodValues> => {
const apiRequest = useApiRequest();
return useMutation<void, Error, DeletePaymentMethodValues>(
({ paymentMethodId }) => {
return apiRequest
.delete(`/payment-services/${paymentMethodId}`)
.then((res) => res.data);
},
{ ...options },
);
};
// # Edit payment method
// -----------------------------------------

View File

@@ -12,6 +12,9 @@ import { transformToCamelCase, transfromToSnakeCase } from '@/utils';
const PaymentServicesQueryKey = 'PaymentServices';
const PaymentServicesStateQueryKey = 'PaymentServicesState';
// # Get payment services.
// -----------------------------------------
export interface GetPaymentServicesResponse {}
/**
* Retrieves the integrated payment services.
@@ -40,10 +43,13 @@ export const useGetPaymentServices = (
);
};
// # Get payment services state.
// -----------------------------------------
export interface GetPaymentServicesStateResponse {
stripe: {
isStripeAccountCreated: boolean;
isStripePaymentActive: boolean;
isStripeServerConfigured: boolean;
stripeAccountId: string | null;
stripePaymentMethodId: number | null;
stripeCurrencies: string[];
@@ -78,6 +84,8 @@ export const useGetPaymentServicesState = (
);
};
// # Update payment method
// -----------------------------------------
interface UpdatePaymentMethodResponse {
id: number;
message: string;
@@ -125,6 +133,8 @@ export const useUpdatePaymentMethod = (): UseMutationResult<
);
};
// # Get payment method
// -----------------------------------------
interface GetPaymentMethodResponse {}
/**
* Retrieves a specific payment method.
@@ -133,6 +143,7 @@ interface GetPaymentMethodResponse {}
*/
export const useGetPaymentMethod = (
paymentMethodId: number,
options?: UseQueryOptions<GetPaymentMethodResponse, Error>,
): UseQueryResult<GetPaymentMethodResponse, Error> => {
const apiRequest = useApiRequest();
@@ -145,5 +156,32 @@ export const useGetPaymentMethod = (
(res) =>
transformToCamelCase(res.data?.data) as GetPaymentMethodResponse,
),
options,
);
};
// # Delete payment method
// -----------------------------------------
interface DeletePaymentMethodValues {
paymentMethodId: number;
}
export const useDeletePaymentMethod = (
options?: UseMutationOptions<void, Error, DeletePaymentMethodValues>,
): UseMutationResult<void, Error, DeletePaymentMethodValues> => {
const apiRequest = useApiRequest();
const queryClient = useQueryClient();
return useMutation<void, Error, DeletePaymentMethodValues>(
({ paymentMethodId }) => {
return apiRequest
.delete(`/payment-services/${paymentMethodId}`)
.then((res) => res.data);
},
{
onSuccess: () => {
queryClient.invalidateQueries(PaymentServicesStateQueryKey);
},
...options,
},
);
};

View File

@@ -83,19 +83,29 @@ export const useDialogActions = () => {
};
};
/**
* Drawer actions.
* @returns
*/
export const useDrawerActions = () => {
const dispatch = useDispatch();
return {
openDrawer: useDispatchAction(openDrawer),
closeDrawer: useDispatchAction(closeDrawer),
openDrawer: (name, payload?: {}) => dispatch(openDrawer(name, payload)),
closeDrawer: (name, payload?: {}) => dispatch(closeDrawer(name, payload)),
};
};
/**
* Alert actions.
* @returns
*/
export const useAlertActions = () => {
const dispatch = useDispatch();
return {
openAlert: (name, payload) => dispatch(openAlert(name, payload)),
closeAlert: (name, payload) => dispatch(closeAlert(name, payload)),
openAlert: (name, payload?: {}) => dispatch(openAlert(name, payload)),
closeAlert: (name, payload?: {}) => dispatch(closeAlert(name, payload)),
};
};

View File

@@ -110,13 +110,6 @@ export const getPreferenceRoutes = () => [
component: lazy(() => import('@/containers/Subscriptions/BillingPage')),
exact: true,
},
{
path: `${BASE_URL}/integrations`,
component: lazy(
() => import('@/containers/Preferences/Integrations/IntegrationsPage'),
),
exact: true,
},
{
path: `${BASE_URL}/`,
component: lazy(() => import('../containers/Preferences/DefaultRoute')),