-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { PaymentElement, useElements, useStripe } from "@stripe/react-stripe-js" | ||
import { useState } from "react" | ||
import { Button } from "react-day-picker" | ||
|
||
interface PaymentMethodFormProps { | ||
isEditMode: boolean | ||
setEditMode: (isEditMode: boolean) => void | ||
provider: string | ||
owner: string | ||
} | ||
|
||
const EditPaymentMethodForm = ({ | ||
isEditMode, | ||
setEditMode, | ||
provider, | ||
owner, | ||
}: PaymentMethodFormProps) => { | ||
const stripe = useStripe() | ||
const elements = useElements() | ||
const [isSubmitting, setIsSubmitting] = useState(false) | ||
const [errorMessage, setErrorMessage] = useState<string | null>(null) | ||
|
||
const handleSubmit = async (event: React.FormEvent) => { | ||
event.preventDefault() | ||
setIsSubmitting(true) | ||
setErrorMessage(null) | ||
|
||
if (!stripe || !elements) { | ||
setErrorMessage('Stripe has not loaded yet. Please try again.') | ||
setIsSubmitting(false) | ||
return | ||
} | ||
|
||
const { error } = await stripe.confirmPayment({ | ||
elements, | ||
confirmParams: { | ||
// eslint-disable-next-line camelcase | ||
return_url: 'https://codecov.io', | ||
}, | ||
}) | ||
|
||
if (error) { | ||
setErrorMessage(error.message || 'An unexpected error occurred.') | ||
setIsSubmitting(false) | ||
} else { | ||
setIsSubmitting(false) | ||
} | ||
} | ||
|
||
return ( | ||
<div> | ||
<PaymentElement | ||
options={{ | ||
layout: 'tabs', | ||
defaultValues: { | ||
billingDetails: { | ||
name: 'John Doe', | ||
}, | ||
}, | ||
}} | ||
/> | ||
<div className="mb-8 mt-4 flex gap-1"> | ||
<Button | ||
hook="submit-payment-method-update" | ||
Check failure on line 64 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/EditPaymentMethod/EditPaymentMethodForm.tsx GitHub Actions / Run Type Checker
Check failure on line 64 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/EditPaymentMethod/EditPaymentMethodForm.tsx GitHub Actions / Upload Bundle Stats - Staging
Check failure on line 64 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/EditPaymentMethod/EditPaymentMethodForm.tsx GitHub Actions / Upload Bundle Stats - Production
|
||
type="submit" | ||
variant="primary" | ||
disabled={isSubmitting} // TODO - handle | ||
onClick={handleSubmit} | ||
to={undefined} | ||
> | ||
Save | ||
</Button> | ||
<Button | ||
type="button" | ||
hook="cancel-payment-method-update" | ||
Check failure on line 75 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/EditPaymentMethod/EditPaymentMethodForm.tsx GitHub Actions / Upload Bundle Stats - Staging
Check failure on line 75 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/EditPaymentMethod/EditPaymentMethodForm.tsx GitHub Actions / Upload Bundle Stats - Production
|
||
variant="plain" | ||
// disabled={isLoading} | ||
onClick={() => console.log('TODO - implement me')} // TODO - implement me | ||
to={undefined} | ||
> | ||
Cancel | ||
</Button> | ||
</div> | ||
|
||
{errorMessage && <div className="text-red-500">{errorMessage}</div>} | ||
</div> | ||
) | ||
} | ||
|
||
export default EditPaymentMethodForm |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { useQuery } from '@tanstack/react-query' | ||
import { z } from 'zod' | ||
|
||
import Api from 'shared/api' | ||
import { NetworkErrorObject } from 'shared/api/helpers' | ||
|
||
export const StripeSetupIntentSchema = z.object({ | ||
clientSecret: z.string(), | ||
}) | ||
|
||
export interface UseStripeSetupIntentArgs { | ||
provider: string | ||
owner: string | ||
opts?: { | ||
enabled?: boolean | ||
} | ||
} | ||
|
||
function fetchStripeSetupIntent({ | ||
provider, | ||
owner, | ||
signal, | ||
}: { | ||
provider: string | ||
owner: string | ||
signal?: AbortSignal | ||
}) { | ||
const path = `/${provider}/${owner}/account-details/setup_intent` | ||
return Api.get({ path, provider, signal }) | ||
} | ||
|
||
export function useStripeSetupIntent({ | ||
provider, | ||
owner, | ||
opts = {}, | ||
}: UseStripeSetupIntentArgs) { | ||
return useQuery({ | ||
queryKey: ['setupIntent', provider, owner], | ||
queryFn: ({ signal }) => | ||
fetchStripeSetupIntent({ provider, owner, signal }).then((res) => { | ||
const parsedRes = StripeSetupIntentSchema.safeParse(res) | ||
|
||
if (!parsedRes.success) { | ||
return Promise.reject({ | ||
status: 404, | ||
data: {}, | ||
dev: 'useStripeSetupIntent - 404 failed to parse', | ||
} satisfies NetworkErrorObject) | ||
} | ||
|
||
return parsedRes.data | ||
}), | ||
...opts, | ||
}) | ||
} |