UNPKG

@datalayer/core

Version:

[![Datalayer](https://assets.datalayer.tech/datalayer-25.svg)](https://datalayer.io)

92 lines (91 loc) 4.79 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /* * Copyright (c) 2023-2025 Datalayer, Inc. * Distributed under the terms of the Modified BSD License. */ import { createElement, useCallback, useEffect, useState } from 'react'; import { Button, Flash, FormControl, Spinner, Text } from '@primer/react'; import { Box } from '@datalayer/primer-addons'; import { useCache } from '../../hooks'; /** * Stripe checkout. */ export function StripeCheckout({ checkoutPortal, }) { const { useCreateCheckoutSession, useStripePrices } = useCache(); const [stripe, setStripe] = useState(null); const [components, setComponents] = useState(null); const [items, setItems] = useState(null); const [product, setProduct] = useState(null); const [checkout, setCheckout] = useState(false); // Get Stripe prices using TanStack Query hook const { data: pricesData } = useStripePrices(); // Update items when prices data changes useEffect(() => { if (pricesData) { setItems(pricesData); } }, [pricesData]); // Get checkout session mutation const checkoutSessionMutation = useCreateCheckoutSession(); // Load stripe components. useEffect(() => { import('@stripe/react-stripe-js').then(module => { setComponents(module); }); }, []); // Load stripe API useEffect(() => { if (checkoutPortal?.metadata?.stripe_key) { import('@stripe/stripe-js').then(module => { setStripe(module.loadStripe(checkoutPortal.metadata?.stripe_key ?? '')); }); } }, [checkoutPortal?.metadata?.stripe_key]); const fetchClientSecret = useCallback(async () => { const location = document.location; // Create a Checkout Session using TanStack Query mutation const result = await checkoutSessionMutation.mutateAsync({ product, location, }); return result; }, [checkoutSessionMutation, product]); const options = { fetchClientSecret }; let view = (_jsx(Box, { sx: { minHeight: '40px' }, children: _jsx(Spinner, {}) })); if (checkout) { if (stripe && components) { view = createElement(Box, { id: 'checkout', sx: { flex: '1 1 auto' } }, createElement(components.EmbeddedCheckoutProvider, { stripe, options }, createElement(components.EmbeddedCheckout))); } } else if (items) { view = items.length ? (_jsxs(Box, { sx: { flex: '1 1 auto' }, onKeyDown: event => { if (product && event.key === 'Enter') { setCheckout(true); } }, children: [_jsx(Text, { as: "h3", children: "Choose a credits package" }), _jsx(Box, { role: "radiogroup", sx: { display: 'grid', gap: 'var(--stack-gap-normal)', gridTemplateColumns: Array(items.length).fill('1fr').join(' '), padding: 'var(--stack-padding-normal) 0', }, children: items.map(item => (_jsx(Box, { role: "radio", "aria-labelledby": `checkout-price-${item.id}`, "aria-checked": product?.id === item.id, onClick: () => { setProduct(item); }, sx: { borderStyle: 'solid', borderRadius: 'var(--borderRadius-medium)', borderWidth: 'var(--borderWidth-thick)', borderColor: product?.id === item.id ? 'var(--borderColor-accent-emphasis)' : 'var(--borderColor-default)', padding: 'var(--stack-padding-condensed)', cursor: 'pointer', }, children: _jsxs(FormControl, { sx: { alignItems: 'center', }, children: [_jsx(FormControl.Label, { id: `checkout-price-${item.id}`, sx: { alignSelf: 'center' }, children: item.name }), _jsx(Text, { as: "p", children: new Intl.NumberFormat(undefined, { style: 'currency', currency: item.currency, }).format(item.amount / 100) }), _jsxs(Text, { as: "p", children: [item.credits, " credits"] })] }, item.id) }))) }), _jsx(Button, { variant: "primary", onClick: () => { setCheckout(true); }, disabled: product === null, sx: { float: 'right' }, children: "Checkout" })] })) : (_jsx(Box, { children: _jsx(Flash, { variant: "danger", children: "Unable to fetch the available products. Please try again later." }) })); } return view; }