Skip to content
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

[PAY-2154] Implement add funds modal #6714

Merged
merged 3 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions packages/common/src/store/ui/modals/add-funds-modal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { createModal } from '../createModal'

export type AddFundsModalState = {
isOpen: boolean
}

const AddFundsModal = createModal<AddFundsModalState>({
reducerPath: 'AddFundsModal',
initialState: {
isOpen: false
},
sliceSelector: (state) => state.ui.modals
})

export const { hook: useAddFundsModal, reducer: addFundsModalReducer } =
AddFundsModal
1 change: 1 addition & 0 deletions packages/common/src/store/ui/modals/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ export * from './edit-playlist-modal'
export * from './edit-track-modal'
export * from './premium-content-purchase-modal'
export * from './usdc-manual-transfer-modal'
export * from './add-funds-modal'
3 changes: 2 additions & 1 deletion packages/common/src/store/ui/modals/parentSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ export const initialState: BasicModalsState = {
WithdrawUSDCModal: { isOpen: false },
USDCPurchaseDetailsModal: { isOpen: false },
USDCTransactionDetailsModal: { isOpen: false },
USDCManualTransferModal: { isOpen: false }
USDCManualTransferModal: { isOpen: false },
AddFundsModal: { isOpen: false }
}

const slice = createSlice({
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/store/ui/modals/reducers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Action, combineReducers, Reducer } from '@reduxjs/toolkit'

import { addFundsModalReducer } from './add-funds-modal'
import { createChatModalReducer } from './create-chat-modal'
import { BaseModalState } from './createModal'
import { editPlaylistModalReducer } from './edit-playlist-modal'
Expand Down Expand Up @@ -37,6 +38,7 @@ const combinedReducers = combineReducers({
WithdrawUSDCModal: withdrawUSDCModalReducer,
USDCPurchaseDetailsModal: usdcPurchaseDetailsModalReducer,
USDCManualTransferModal: usdcManualTransferModalReducer,
AddFundsModal: addFundsModalReducer,
USDCTransactionDetailsModal: usdcTransactionDetailsModalReducer,
PremiumContentPurchaseModal: premiumContentPurchaseModalReducer
})
Expand Down
3 changes: 3 additions & 0 deletions packages/common/src/store/ui/modals/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ModalSource } from 'models/Analytics'

import { AddFundsModalState } from './add-funds-modal'
import { CreateChatModalState } from './create-chat-modal'
import { BaseModalState } from './createModal'
import { EditPlaylistModalState } from './edit-playlist-modal'
Expand Down Expand Up @@ -60,6 +61,7 @@ export type Modals =
| 'USDCPurchaseDetailsModal'
| 'USDCTransactionDetailsModal'
| 'USDCManualTransferModal'
| 'AddFundsModal'

export type BasicModalsState = {
[modal in Modals]: BaseModalState
Expand All @@ -75,6 +77,7 @@ export type StatefulModalsState = {
USDCPurchaseDetailsModal: USDCPurchaseDetailsModalState
USDCTransactionDetailsModal: USDCTransactionDetailsModalState
USDCManualTransferModal: USDCManualTransferModalState
AddFundsModal: AddFundsModalState
PremiumContentPurchaseModal: PremiumContentPurchaseModalState
}

Expand Down
5 changes: 5 additions & 0 deletions packages/harmony/src/assets/icons/CreditCard.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ export const BaseButton = forwardRef<HTMLButtonElement, BaseButtonProps>(
whiteSpace: 'nowrap',
transition: `
transform ${motion.hover},
border-color ${motion.hover},
background-color ${motion.hover}
border-color ${motion.hover}
`,

...(fullWidth && {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export const FilterButton = forwardRef<HTMLButtonElement, FilterButtonProps>(
: color.text.default,
gap: spacing.xs,
fontSize: typography.size.s,
fontWeight: typography.weight.medium,
fontWeight: typography.weight.demiBold,
lineHeight: typography.lineHeight.s,

'&:hover': {
Expand Down
1 change: 1 addition & 0 deletions packages/harmony/src/icons/utilityIcons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,4 @@ export { default as IconHeadphones } from '../assets/icons/Headphones.svg'
export { default as IconValidationCheck } from '../assets/icons/ValidationCheck.svg'
export { default as IconValidationX } from '../assets/icons/ValidationX.svg'
export { default as IconSoundwave } from '../assets/icons/Soundwave.svg'
export { default as IconCreditCard } from '../assets/icons/CreditCard.svg'
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const messages = {
addFunds: 'Add Funds'
}

const useStyles = makeStyles(({ spacing, palette, typography }) => ({
const useStyles = makeStyles(({ spacing, palette }) => ({
root: {
paddingVertical: spacing(8),
paddingHorizontal: spacing(3)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.modal {
width: 720px;
}

.modalHeader {
text-align: center;
}

.modalHeader.mobile {
margin: 0;
padding: 0;
border: none;
}
80 changes: 80 additions & 0 deletions packages/web/src/components/add-funds-modal/AddFundsModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { useCallback, useState } from 'react'

import { useAddFundsModal } from '@audius/common'
import { ModalContent, ModalHeader } from '@audius/stems'
import cn from 'classnames'

import { AddFunds, Method } from 'components/add-funds/AddFunds'
import { Text } from 'components/typography'
import { USDCManualTransfer } from 'components/usdc-manual-transfer/USDCManualTransfer'
import ModalDrawer from 'pages/audio-rewards-page/components/modals/ModalDrawer'
import { isMobile } from 'utils/clientUtil'
import zIndex from 'utils/zIndex'

import styles from './AddFundsModal.module.css'

const messages = {
addFunds: 'Add Funds',
cryptoTransfer: 'Crypto Transfer'
}

type Page = 'add-funds' | 'crypto-transfer'

export const AddFundsModal = () => {
const { isOpen, onClose } = useAddFundsModal()
const mobile = isMobile()

const [page, setPage] = useState<Page>('add-funds')

const handleClose = useCallback(() => {
onClose()
}, [onClose])

const handleClosed = useCallback(() => {
setPage('add-funds')
}, [setPage])

const handleContinue = useCallback(
(method: Method) => {
setPage('crypto-transfer')
},
[setPage]
)

return (
<ModalDrawer
zIndex={zIndex.ADD_FUNDS_MODAL}
size={'small'}
onClose={handleClose}
isOpen={isOpen}
onClosed={handleClosed}
bodyClassName={styles.modal}
useGradientTitle={false}
dismissOnClickOutside
isFullscreen={false}
>
<ModalHeader
className={cn(styles.modalHeader, { [styles.mobile]: mobile })}
onClose={onClose}
showDismissButton={!mobile}
>
<Text
variant='label'
color='neutralLight2'
size='xLarge'
strength='strong'
className={styles.title}
>
{page === 'add-funds' ? messages.addFunds : messages.cryptoTransfer}
</Text>
</ModalHeader>
<ModalContent>
{page === 'add-funds' ? (
<AddFunds onContinue={handleContinue} />
) : (
<USDCManualTransfer onClose={handleClose} />
)}
</ModalContent>
</ModalDrawer>
)
}
15 changes: 15 additions & 0 deletions packages/web/src/components/add-funds/AddFunds.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.root {
display: flex;
flex-direction: column;
gap: var(--unit-6);
}

.buttonContainer {
display: flex;
flex-direction: row;
gap: var(--unit-2);
}

.buttonContainer.mobile {
flex-direction: column;
}
128 changes: 128 additions & 0 deletions packages/web/src/components/add-funds/AddFunds.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { ChangeEvent, useCallback, useState } from 'react'

import {
BNUSDC,
decimalIntegerToHumanReadable,
formatUSDCWeiToFloorCentsNumber,
useCreateUserbankIfNeeded,
useUSDCBalance
} from '@audius/common'
import {
Box,
Button,
ButtonType,
Flex,
Text,
IconLogoCircleUSDC,
IconCreditCard,
IconTransaction,
FilterButton,
FilterButtonType
} from '@audius/harmony'
import { BN } from 'bn.js'
import cn from 'classnames'

import { SummaryTable, SummaryTableItem } from 'components/summary-table'
import { track } from 'services/analytics'
import { audiusBackendInstance } from 'services/audius-backend/audius-backend-instance'
import { isMobile } from 'utils/clientUtil'

import styles from './AddFunds.module.css'

const messages = {
usdcBalance: 'USDC Balance',
paymentMethod: 'Payment Method',
withCard: 'Add funds with Card',
withCrypto: 'Add funds with crypto transfer',
continue: 'Continue'
}

export type Method = 'card' | 'crypto'

export const AddFunds = ({
onContinue
}: {
onContinue: (method: Method) => void
}) => {
useCreateUserbankIfNeeded({
recordAnalytics: track,
audiusBackendInstance,
mint: 'usdc'
})
const [selectedMethod, setSelectedMethod] = useState<Method>('card')
const mobile = isMobile()
const { data: balance } = useUSDCBalance()
const balanceNumber = formatUSDCWeiToFloorCentsNumber(
(balance ?? new BN(0)) as BNUSDC
)
const balanceFormatted = decimalIntegerToHumanReadable(balanceNumber)

const items: SummaryTableItem[] = [
{
id: 'card',
label: messages.withCard,
icon: IconCreditCard,
value: (
<FilterButton
initialSelectionIndex={0}
variant={FilterButtonType.REPLACE_LABEL}
options={[{ label: 'Stripe' }]}
/>
)
},
{
id: 'crypto',
label: messages.withCrypto,
icon: IconTransaction
}
]

const handleChangeOption = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
setSelectedMethod(e.target.value as Method)
},
[setSelectedMethod]
)

return (
<div className={styles.root}>
<div
className={cn(styles.buttonContainer, {
[styles.mobile]: mobile
})}
>
<Flex direction='column' w='100%' gap='xl'>
<Box h='unit6' border='strong' p='m'>
<Flex alignItems='center' justifyContent='space-between'>
<Flex alignItems='center'>
<IconLogoCircleUSDC />
<Box pl='s'>
<Text variant='title' size='m'>
{messages.usdcBalance}
</Text>
</Box>
</Flex>
<Text variant='title' size='l' strength='strong'>
{`$${balanceFormatted}`}
</Text>
</Flex>
</Box>
<SummaryTable
title={messages.paymentMethod}
items={items}
withRadioOptions
onRadioChange={handleChangeOption}
selectedRadioOption={selectedMethod}
/>
<Button
variant={ButtonType.PRIMARY}
fullWidth
onClick={() => onContinue(selectedMethod)}
>
{messages.continue}
</Button>
</Flex>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@
.rowGrayBackground {
background: var(--background-surface-1);
}

.radioGroup {
width: 100%;
}
Loading