Skip to content

Feature/ba 2468 payment methods management #263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Prev Previous commit
Next Next commit
BA-2468-payment-methods-management
  • Loading branch information
Lúcio BJ committed May 7, 2025
commit 6fc01a05478f6f735574419463554dff45ff03b8
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const AddCardModal: FC<AddCardModalProps> = ({
setIsAddingCardPaymentProcessing(false)
} else {
await queryClient.invalidateQueries({
queryKey: ['useGetPaymentMethod'],
queryKey: ['listPaymentMethods'],
})
if (handleSetupSuccess) {
handleSetupSuccess()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const Checkout: FC<CheckoutProps> = ({
if (paymentMethods?.length > 0) {
setSelectedPaymentMethodId(paymentMethods[0]?.id || '')
}
queryClient.invalidateQueries({ queryKey: ['useGetPaymentMethod'] })
queryClient.invalidateQueries({ queryKey: ['listPaymentMethods'] })
setConfirmationModalOpen(true)
setIsRetry(false)
}
Expand Down Expand Up @@ -279,4 +279,5 @@ const Checkout: FC<CheckoutProps> = ({
</Box>
)
}

export default Checkout
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ const CheckoutWrapper: FC<CheckoutWrapperProps> = ({
checkoutProductId,
stripePublishableKey,
}) => {
const { useSetupIntent, useGetPaymentMethod, useGetProduct } = useStripeHook()
const { useSetupIntent, useListPaymentMethods, useGetProduct } = useStripeHook()
const { mutate: createSetupIntent, data: setupIntent, isPending, isError } = useSetupIntent()

const {
data: paymentMethods,
isLoading: isLoadingMethods,
isError: isErrorMethods,
} = useGetPaymentMethod(checkoutCustomerId || '')
} = useListPaymentMethods(checkoutCustomerId || '')

const {
data: product,
Expand Down Expand Up @@ -72,4 +72,5 @@ const CheckoutWrapper: FC<CheckoutWrapperProps> = ({
</Elements>
)
}

export default CheckoutWrapper
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import { FC } from 'react'

import {
AddIcon,
CreditCardIcon,
MastercardCreditCardIcon,
VisaCreditCardIcon,
} from '@baseapp-frontend/design-system/components/web/icons'
import { AddIcon, CreditCardIcon } from '@baseapp-frontend/design-system/components/web/icons'

import { Box, FormControl, InputLabel, MenuItem, Select, Typography } from '@mui/material'

import AddCardModal from '../AddCardModal'
import { getCardIcon } from '../utils'
import { StyledButton } from './styled'
import { PaymentDropdownProps } from './types'

Expand All @@ -25,19 +21,6 @@ const PaymentDropdown: FC<PaymentDropdownProps> = ({
handleSetupSuccess,
}) => {
const isEmpty = !paymentMethods || paymentMethods.length === 0
const getCardIcon = (brand?: string) => {
const cardBrand = brand?.toLowerCase() || ''

switch (cardBrand) {
case 'visa':
return <VisaCreditCardIcon sx={{ mr: 1, fontSize: 28 }} />
case 'mastercard':
return <MastercardCreditCardIcon sx={{ mr: 1, fontSize: 28 }} />
default:
return <CreditCardIcon sx={{ mr: 1, color: 'primary.main' }} />
}
}

const handleOpenModal = () => {
setIsAddCardModalOpen(true)
}
Expand Down Expand Up @@ -109,7 +92,7 @@ const PaymentDropdown: FC<PaymentDropdownProps> = ({
<Box sx={{ mr: 2 }}>{getCardIcon(pm?.card?.brand)}</Box>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Typography variant="body2" fontWeight={500}>
{pm?.card?.brand?.toUpperCase() || 'CARD'} ••• ••• •••{pm?.card?.last4}
{pm?.card?.brand?.toUpperCase() ?? 'CARD'} ••• ••• •••{pm?.card?.last4}
</Typography>
<Typography variant="caption" color="text.secondary">
Expires: {pm?.card?.expMonth}/{pm?.card?.expYear}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import React from 'react'

import {
CreditCardIcon,
MastercardCreditCardIcon,
VisaCreditCardIcon,
} from '@baseapp-frontend/design-system/components/web/icons'

export const maskEmail = (
email: string | undefined,
maskDomain: boolean = false,
Expand Down Expand Up @@ -31,3 +39,16 @@ export const maskEmail = (

return `${maskedUsername}@${domain}`
}

export const getCardIcon = (brand?: string) => {
const cardBrand = brand?.toLowerCase() || ''

switch (cardBrand) {
case 'visa':
return <VisaCreditCardIcon sx={{ mr: 1, fontSize: 28 }} />
case 'mastercard':
return <MastercardCreditCardIcon sx={{ mr: 1, fontSize: 28 }} />
default:
return <CreditCardIcon sx={{ mr: 1, color: 'primary.main' }} />
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { FC } from 'react'

import { MoreVert } from '@mui/icons-material'
import { Box, Chip, Divider, IconButton, Typography } from '@mui/material'

import { getCardIcon } from '../../CheckoutComponent/utils'
import { PaymentMethodsItemProps } from '../types'

const PaymentMethodsItem: FC<PaymentMethodsItemProps> = ({
paymentMethod,
setIsMenuOpen,
setSelectedPaymentMethodId,
setAnchorEl,
isLast,
}) => {
const isExpired =
paymentMethod?.card?.expMonth &&
paymentMethod?.card?.expYear &&
new Date(paymentMethod?.card?.expYear, paymentMethod?.card?.expMonth) < new Date()
return (
<>
<Box
key={paymentMethod.id}
sx={{ display: 'flex', alignItems: 'center', width: '100%', gap: 2 }}
>
{getCardIcon(paymentMethod?.card?.brand)}
<Box sx={{ display: 'flex', flexDirection: 'column', flexGrow: 1 }}>
<Box sx={{ display: 'flex', gap: 2, mb: 1 }}>
{paymentMethod?.isDefault && <Chip color="default" label="Default" variant="soft" />}
{isExpired && <Chip color="error" label="Expired" variant="soft" />}
</Box>
<Typography variant="body2" fontWeight={500}>
{paymentMethod?.card?.brand?.toUpperCase() ?? 'CARD'} •••• •••• ••••{' '}
{paymentMethod?.card?.last4}
</Typography>
<Typography variant="caption" color="text.secondary">
{`${isExpired ? 'Expired' : 'Expires'}: ${paymentMethod?.card?.expMonth}/${paymentMethod?.card?.expYear}`}
</Typography>
</Box>
<IconButton
onClick={() => {
setIsMenuOpen(true)
setSelectedPaymentMethodId(paymentMethod.id)
setAnchorEl(document.activeElement as HTMLElement)
}}
sx={{ flexGrow: 0 }}
>
<MoreVert />
</IconButton>
</Box>
{!isLast && <Divider />}
</>
)
}

export default PaymentMethodsItem
Loading
Loading