first commit
Some checks failed
Build / run (push) Has been cancelled

This commit is contained in:
maher
2025-10-29 11:42:25 +01:00
commit 703f50a09d
4595 changed files with 385164 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
import {useEffect, useRef, useState} from 'react';
import {useSearchParams} from 'react-router-dom';
import {loadStripe, SetupIntent} from '@stripe/stripe-js';
import {message} from '../../../i18n/message';
import {apiClient} from '../../../http/query-client';
import {useNavigate} from '../../../utils/hooks/use-navigate';
import {
BillingRedirectMessage,
BillingRedirectMessageConfig,
} from '../../billing-redirect-message';
import {invalidateBillingUserQuery} from '../use-billing-user';
import {useSettings} from '../../../core/settings/use-settings';
const previousUrl = '/billing';
export function ChangePaymentMethodDone() {
const {
billing: {stripe_public_key},
} = useSettings();
const navigate = useNavigate();
const [params] = useSearchParams();
const clientSecret = params.get('setup_intent_client_secret');
const [messageConfig, setMessageConfig] =
useState<BillingRedirectMessageConfig>();
const stripeInitiated = useRef<boolean>();
useEffect(() => {
if (stripeInitiated.current || !clientSecret) return;
loadStripe(stripe_public_key!).then(stripe => {
if (!stripe) {
setMessageConfig(getRedirectMessageConfig());
return;
}
stripe.retrieveSetupIntent(clientSecret).then(({setupIntent}) => {
if (setupIntent?.status === 'succeeded') {
changeDefaultPaymentMethod(setupIntent.payment_method as string).then(
() => {
invalidateBillingUserQuery();
}
);
}
setMessageConfig(getRedirectMessageConfig(setupIntent?.status));
});
});
stripeInitiated.current = true;
}, [stripe_public_key, clientSecret]);
if (!clientSecret) {
navigate(previousUrl);
return null;
}
return <BillingRedirectMessage config={messageConfig} />;
}
function getRedirectMessageConfig(
status?: SetupIntent.Status
): BillingRedirectMessageConfig {
switch (status) {
case 'succeeded':
return {
...redirectMessageDefaults,
message: message('Payment method changed successfully!'),
status: 'success',
};
case 'processing':
return {
...redirectMessageDefaults,
message: message(
"Your request is processing. We'll update you when your payment method is confirmed."
),
status: 'success',
};
case 'requires_payment_method':
return {
...redirectMessageDefaults,
message: message(
'Payment method confirmation failed. Please try another payment method.'
),
status: 'error',
};
default:
return {
...redirectMessageDefaults,
message: message('Something went wrong'),
status: 'error',
};
}
}
const redirectMessageDefaults: Omit<
BillingRedirectMessageConfig,
'message' | 'status'
> = {
link: previousUrl,
buttonLabel: message('Go back'),
};
function changeDefaultPaymentMethod(paymentMethodId: string) {
return apiClient.post('billing/stripe/change-default-payment-method', {
payment_method_id: paymentMethodId,
});
}

View File

@@ -0,0 +1,29 @@
import {Fragment} from 'react';
import {Breadcrumb} from '../../../ui/breadcrumbs/breadcrumb';
import {useNavigate} from '../../../utils/hooks/use-navigate';
import {BreadcrumbItem} from '../../../ui/breadcrumbs/breadcrumb-item';
import {Trans} from '../../../i18n/trans';
import {Outlet} from 'react-router-dom';
const previousUrl = '/billing';
export function ChangePaymentMethodLayout() {
const navigate = useNavigate();
return (
<Fragment>
<Breadcrumb>
<BreadcrumbItem isLink onSelected={() => navigate(previousUrl)}>
<Trans message="Billing" />
</BreadcrumbItem>
<BreadcrumbItem>
<Trans message="Payment method" />
</BreadcrumbItem>
</Breadcrumb>
<h1 className="text-3xl font-bold my-32 md:my-64">
<Trans message="Change payment method" />
</h1>
<Outlet />
</Fragment>
);
}

View File

@@ -0,0 +1,31 @@
import {Trans} from '../../../i18n/trans';
import {Button} from '../../../ui/buttons/button';
import {Link} from 'react-router-dom';
import {StripeElementsForm} from '../../checkout/stripe/stripe-elements-form';
import {useSettings} from '../../../core/settings/use-settings';
const previousUrl = '/billing';
export function ChangePaymentMethodPage() {
const {base_url} = useSettings();
return (
<div className="max-w-[464px]">
<StripeElementsForm
type="setupIntent"
submitLabel={<Trans message="Change" />}
returnUrl={`${base_url}/billing/change-payment-method/done`}
/>
<Button
variant="outline"
className="w-full mt-16"
size="md"
to={previousUrl}
elementType={Link}
type="button"
>
<Trans message="Go back" />
</Button>
</div>
);
}