feat: Stripe payment checkout session

This commit is contained in:
Ahmed Bouhuolia
2024-09-19 22:24:07 +02:00
parent 0ae7a25c27
commit f5a1d68c52
8 changed files with 226 additions and 4 deletions

View File

@@ -1,18 +1,37 @@
import { Text, Classes, Button, Intent } from '@blueprintjs/core';
import clsx from 'classnames';
import { Box, Group, Stack } from '@/components';
import styles from './PaymentPortal.module.scss';
import { AppToaster, Box, Group, Stack } from '@/components';
import { usePaymentPortalBoot } from './PaymentPortalBoot';
import { useDrawerActions } from '@/hooks/state';
import { useCreateStripeCheckoutSession } from '@/hooks/query/stripe-integration';
import { DRAWERS } from '@/constants/drawers';
import styles from './PaymentPortal.module.scss';
export function PaymentPortal() {
const { openDrawer } = useDrawerActions();
const { sharableLinkMeta } = usePaymentPortalBoot();
const { sharableLinkMeta, linkId } = usePaymentPortalBoot();
const {
mutateAsync: createStripeCheckoutSession,
isLoading: isStripeCheckoutLoading,
} = useCreateStripeCheckoutSession();
// Handles invoice preview button click.
const handleInvoicePreviewBtnClick = () => {
openDrawer(DRAWERS.PAYMENT_INVOICE_PREVIEW);
};
// handles the pay button click.
const handlePayButtonClick = () => {
createStripeCheckoutSession({ linkId })
.then((session) => {
window.open(session.redirectTo);
})
.catch(() => {
AppToaster.show({
intent: Intent.DANGER,
message: 'Something went wrong.',
});
});
};
return (
<Box className={styles.root}>
@@ -91,15 +110,19 @@ export function PaymentPortal() {
>
Download Invoice
</Button>
<Button
onClick={handleInvoicePreviewBtnClick}
className={clsx(styles.footerButton, styles.viewInvoiceButton)}
>
View Invoice
</Button>
<Button
intent={Intent.PRIMARY}
className={clsx(styles.footerButton, styles.buyButton)}
loading={isStripeCheckoutLoading}
onClick={handlePayButtonClick}
>
Pay {sharableLinkMeta?.totalFormatted}
</Button>

View File

@@ -6,6 +6,7 @@ import {
import { Spinner } from '@blueprintjs/core';
interface PaymentPortalContextType {
linkId: string;
sharableLinkMeta: GetSharableLinkMetaResponse | undefined;
isSharableLinkMetaLoading: boolean;
}
@@ -27,6 +28,7 @@ export const PaymentPortalBoot: React.FC<PaymentPortalBootProps> = ({
useGetSharableLinkMeta(linkId);
const value = {
linkId,
sharableLinkMeta,
isSharableLinkMetaLoading,
};

View File

@@ -15,7 +15,6 @@ export function StripeIntegration() {
null,
);
const stripeConnectInstance = useStripeConnect(connectedAccountId || '');
const { mutateAsync: createAccount } = useCreateStripeAccount();
const handleSignupBtnClick = () => {

View File

@@ -5,6 +5,7 @@ import {
UseMutationResult,
} from 'react-query';
import useApiRequest from '../useRequest';
import { transformToCamelCase } from '@/utils';
interface AccountSessionValues {
connectedAccountId?: string;
@@ -57,3 +58,42 @@ export const useCreateStripeAccount = (
{ ...options },
);
};
interface CreateCheckoutSessionValues {
linkId: string;
}
interface CreateCheckoutSessionResponse {
sessionId: string;
publishableKey: string;
redirectTo: string;
}
export const useCreateStripeCheckoutSession = (
options?: UseMutationOptions<
CreateCheckoutSessionResponse,
Error,
CreateCheckoutSessionValues
>,
): UseMutationResult<
CreateCheckoutSessionResponse,
Error,
CreateCheckoutSessionValues
> => {
const apiRequest = useApiRequest();
return useMutation(
(values: CreateCheckoutSessionValues) => {
return apiRequest
.post(
`/stripe_integration/${values.linkId}/create_checkout_session`,
values,
)
.then(
(res) =>
transformToCamelCase(res.data) as CreateCheckoutSessionResponse,
);
},
{ ...options },
);
};