chore: adopt to new endpoint to mark payment as default

This commit is contained in:
Kevin Grüneberg committed 2024-06-03 20:50:11 +08:00
1 parent 4a43f3b854
commit 6ee7fa6aa1
4 files changed
+115 -31

No files matched your search

@@ -2,10 +2,8 @@ import toast from 'react-hot-toast'
import { useParams } from 'common'
import type { OrganizationPaymentMethod } from 'data/organizations/organization-payment-methods-query'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
import { useOrgSubscriptionUpdateMutation } from 'data/subscriptions/org-subscription-update-mutation'
import type { SubscriptionTier } from 'data/subscriptions/types'
import { Button, Modal } from 'ui'
import { useOrganizationPaymentMethodMarkAsDefaultMutation } from 'data/organizations/organization-payment-method-default-mutation'
export interface ChangePaymentMethodModalProps {
selectedPaymentMethod?: OrganizationPaymentMethod
@@ -17,9 +15,8 @@ const ChangePaymentMethodModal = ({
onClose,
}: ChangePaymentMethodModalProps) => {
const { slug } = useParams()
const { data: subscription } = useOrgSubscriptionQuery({ orgSlug: slug })
const { mutate: updateOrgSubscription, isLoading: isUpdating } = useOrgSubscriptionUpdateMutation(
{
const { mutate: markAsDefault, isLoading: isUpdating } =
useOrganizationPaymentMethodMarkAsDefaultMutation({
onSuccess: () => {
toast.success(
`Successfully changed payment method to the card ending with ${
@@ -31,23 +28,15 @@ const ChangePaymentMethodModal = ({
onError: (error) => {
toast.error(`Failed to change payment method: ${error.message}`)
},
}
)
})
const onConfirmUpdate = async () => {
if (!slug) return console.error('Slug is required')
if (!subscription) return console.error('Subscription is required')
if (!selectedPaymentMethod) return console.error('Card ID is required')
const selectedTier =
subscription.plan.id === 'pro' && subscription.usage_billing_enabled
? 'tier_payg'
: `tier_${subscription.plan.id}`
updateOrgSubscription({
markAsDefault({
slug,
tier: selectedTier as SubscriptionTier,
paymentMethod: selectedPaymentMethod.id,
paymentMethodId: selectedPaymentMethod.id,
})
}
@@ -177,20 +177,17 @@ const PaymentMethods = () => {
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{subscription?.plan.id !== 'free' &&
subscription?.payment_method_type === 'card' && (
<>
<DropdownMenuItem
key="make-default"
onClick={() =>
setSelectedMethodForUse(paymentMethod)
}
>
<p>Use this card</p>
</DropdownMenuItem>
<DropdownMenuSeparator />
</>
)}
{
<>
<DropdownMenuItem
key="make-default"
onClick={() => setSelectedMethodForUse(paymentMethod)}
>
<p>Use this card</p>
</DropdownMenuItem>
<DropdownMenuSeparator />
</>
}
<DropdownMenuItem
key="delete-method"
onClick={() => setSelectedMethodToDelete(paymentMethod)}
@@ -0,0 +1,65 @@
import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
import { toast } from 'react-hot-toast'
import { put, handleError } from 'data/fetchers'
import type { ResponseError } from 'types'
import { organizationKeys } from './keys'
export type OrganizationPaymentMethodDefaultVariables = {
slug: string
paymentMethodId: string
}
export async function markPaymentMethodAsDefault({
slug,
paymentMethodId,
}: OrganizationPaymentMethodDefaultVariables) {
if (!slug) throw new Error('Slug is required')
const { data, error } = await put(`/platform/organizations/{slug}/payments/default`, {
body: { payment_method_id: paymentMethodId },
params: {
path: {
slug,
},
},
})
if (error) throw handleError(error)
return data
}
type OrganizationPaymentMethodDefaultData = Awaited<ReturnType<typeof markPaymentMethodAsDefault>>
export const useOrganizationPaymentMethodMarkAsDefaultMutation = ({
onSuccess,
onError,
...options
}: Omit<
UseMutationOptions<
OrganizationPaymentMethodDefaultData,
ResponseError,
OrganizationPaymentMethodDefaultVariables
>,
'mutationFn'
> = {}) => {
const queryClient = useQueryClient()
return useMutation<
OrganizationPaymentMethodDefaultData,
ResponseError,
OrganizationPaymentMethodDefaultVariables
>((vars) => markPaymentMethodAsDefault(vars), {
async onSuccess(data, variables, context) {
const { slug } = variables
await queryClient.invalidateQueries(organizationKeys.paymentMethods(slug))
await onSuccess?.(data, variables, context)
},
async onError(data, variables, context) {
if (onError === undefined) {
toast.error(`Failed to mark payment method as default: ${data.message}`)
} else {
onError(data, variables, context)
}
},
...options,
})
}
+33
View File
@@ -267,6 +267,10 @@ export interface paths {
/** Detach Stripe payment method with the given card ID */
delete: operations['PaymentsController_detachPaymentMethod']
}
'/platform/organizations/{slug}/payments/default': {
/** Mark given paymnet method as default for organization */
put: operations['PaymentsController_markPaymentMethodAsDefault']
}
'/platform/organizations/{slug}/payments/setup-intent': {
/** Sets up a payment method */
post: operations['SetupIntentOrgController_setUpPaymentMethod']
@@ -2925,6 +2929,9 @@ export interface components {
stripeAccount?: string
}
}
MarkDefaultPaymentMethodBody: {
payment_method_id: string
}
HCaptchaBody: {
hcaptchaToken: string
}
@@ -7588,6 +7595,32 @@ export interface operations {
}
}
}
/** Mark given paymnet method as default for organization */
PaymentsController_markPaymentMethodAsDefault: {
parameters: {
path: {
/** @description Organization slug */
slug: string
}
}
requestBody: {
content: {
'application/json': components['schemas']['MarkDefaultPaymentMethodBody']
}
}
responses: {
200: {
content: never
}
403: {
content: never
}
/** @description Failed to mark payment method as default */
500: {
content: never
}
}
}
/** Sets up a payment method */
SetupIntentOrgController_setUpPaymentMethod: {
parameters: {