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

Web referral challenge UI updates #11476

Merged
merged 9 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from 5 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
3 changes: 0 additions & 3 deletions packages/common/src/models/AudioRewards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ export enum ChallengeName {

export type ChallengeRewardID =
| 'track-upload'
| 'referrals'
| 'ref-v'
| 'referred'
| 'mobile-install'
| 'connect-verified'
| 'listen-streak'
Expand Down
46 changes: 6 additions & 40 deletions packages/common/src/utils/challenges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,61 +27,27 @@ export const challengeRewardsConfig: Record<
ChallengeRewardID,
ChallengeRewardsInfo
> = {
referrals: {
id: 'referrals',
title: 'Invite Your Friends!',
description: (challenge) =>
`Earn ${challenge?.amount} $AUDIO for you and your friend.`,
fullDescription: (challenge) =>
`Invite your Friends! You’ll earn ${challenge?.amount} $AUDIO for each friend who joins with your link (and they’ll get an $AUDIO too)`,
progressLabel: '%0/%1 Invites Accepted',
remainingLabel: '%0/%1 Invites Remain',
panelButtonText: 'Invite Your Friends'
},
[ChallengeName.Referrals]: {
id: ChallengeName.Referrals,
title: 'Invite Your Friends!',
description: (challenge) =>
`Earn ${challenge?.amount} $AUDIO for you and your friend.`,
fullDescription: (challenge) =>
`Invite your Friends! You’ll earn ${challenge?.amount} $AUDIO for each friend who joins with your link (and they’ll get an $AUDIO too)`,
progressLabel: '%0/%1 Invites Accepted',
remainingLabel: '%0/%1 Invites Remain',
progressLabel: '%0 Invites Accepted',
remainingLabel: '%0 Invites Remain',
panelButtonText: 'Invite Your Friends'
},
'ref-v': {
id: 'ref-v',
title: 'Invite your Fans',
description: (challenge) =>
`Earn up to ${formatNumberCommas(challenge?.totalAmount ?? '')} $AUDIO`,
fullDescription: (challenge) =>
`Invite your fans! You’ll earn ${challenge?.amount} $AUDIO for each fan who joins with your link (and they’ll get an $AUDIO too)`,
progressLabel: '%0/%1 Invites Accepted',
remainingLabel: '%0/%1 Invites Remain',
panelButtonText: 'Invite your Fans',
isVerifiedChallenge: true
},
[ChallengeName.ReferralsVerified]: {
id: ChallengeName.ReferralsVerified,
title: 'Invite your Fans',
description: (challenge) =>
`Earn up to ${formatNumberCommas(challenge?.totalAmount ?? '')} $AUDIO`,
fullDescription: (challenge) =>
`Invite your fans! You’ll earn ${challenge?.amount} $AUDIO for each fan who joins with your link (and they’ll get an $AUDIO too)`,
progressLabel: '%0/%1 Invites Accepted',
remainingLabel: '%0/%1 Invites Remain',
panelButtonText: 'Invite your Fans',
isVerifiedChallenge: true
},
referred: {
id: 'referred',
title: 'You Accepted An Invite',
description: (challenge) =>
`You earned ${challenge?.totalAmount ?? ''} $AUDIO for being invited.`,
fullDescription: (challenge) =>
`You earned ${challenge?.totalAmount ?? ''} $AUDIO for being invited.`,
progressLabel: 'Not Earned',
panelButtonText: 'More Info'
progressLabel: '%0 Invites Accepted',
remainingLabel: '%0 Invites Remain',
panelButtonText: 'Invite your Fans'
},
[ChallengeName.Referred]: {
id: ChallengeName.Referred,
Expand Down Expand Up @@ -470,7 +436,7 @@ export const getChallengeStatusLabel = (

case ChallengeName.Referrals:
case ChallengeName.ReferralsVerified:
return `${challenge.current_step_count ?? 0}/${challenge.max_steps ?? 0} Invites Remaining`
return `${(challenge?.max_steps ?? 0) - (challenge?.current_step_count ?? 0)} Invites Remaining`

case ChallengeName.ProfileCompletion:
return `${challenge.current_step_count ?? 0}/7 Complete`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export const DefaultChallengeContent = ({
const config = challengeRewardsConfig[challengeName] ?? {
fullDescription: () => '',
completedLabel: '',
isVerifiedChallenge: false,
progressLabel: ''
}
const { fullDescription } = config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,8 @@ export const RewardPanel = ({
/>
</Flex>
<Flex column h='100%' gap='l' ph='xl' pv='unit9'>
<Flex
column
alignItems='flex-start'
justifyContent='space-between'
w='100%'
gap='s'
>
<Text variant='heading' size='s'>
<Flex column alignItems='flex-start' w='100%' gap='s'>
<Text variant='heading' size='s' textAlign='left'>
{title}
</Text>
<Flex css={{ minHeight: 40 }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,14 @@ import {
musicConfettiActions
} from '@audius/common/store'
import { getAAOErrorEmojis } from '@audius/common/utils'
import { ModalContent, IconCopy, Button } from '@audius/harmony'
import { ModalContent } from '@audius/harmony'
import { useDispatch, useSelector } from 'react-redux'

import { useModalState } from 'common/hooks/useModalState'
import ModalDrawer from 'components/modal-drawer/ModalDrawer'
import Toast from 'components/toast/Toast'
import { ToastContext } from 'components/toast/ToastContext'
import Tooltip from 'components/tooltip/Tooltip'
import { ComponentPlacement, MountPlacement } from 'components/types'
import { useWithMobileStyle } from 'hooks/useWithMobileStyle'
import { getChallengeConfig } from 'pages/rewards-page/config'
import { copyToClipboard, getCopyableLink } from 'utils/clipboardUtil'
import { CLAIM_REWARD_TOAST_TIMEOUT_MILLIS } from 'utils/constants'

import { getChallengeContent } from './challengeContentRegistry'
Expand All @@ -32,18 +28,8 @@ const { getAAOErrorCode, getChallengeRewardsModalType, getClaimStatus } =
const { resetAndCancelClaimReward } = audioRewardsPageActions
const { getOptimisticUserChallenges } = challengesSelectors

const inviteLink = getCopyableLink('/signup?rf=%0')

const messages = {
close: 'Close',
audio: '$AUDIO',
everyDollarSpent: ' Every Dollar Spent',
copyLabel: 'Copy to Clipboard',
copiedLabel: 'Copied to Clipboard',
inviteLabel: 'Copy Invite to Clipboard',
inviteLink,
qrText: 'Download the App',
qrSubtext: 'Scan This QR Code with Your Phone Camera',
rewardClaimed: 'Reward claimed successfully!',
rewardAlreadyClaimed: 'Reward already claimed!',
claimError:
Expand Down Expand Up @@ -87,43 +73,6 @@ const messages = {
ineligible: 'Ineligible'
}

type InviteLinkProps = {
className?: string
inviteLink: string
}

export const InviteLink = ({ className, inviteLink }: InviteLinkProps) => {
const wm = useWithMobileStyle(styles.mobile)

const onButtonClick = useCallback(() => {
copyToClipboard(inviteLink)
}, [inviteLink])

return (
<Tooltip text={messages.copyLabel} placement={'top'} mount={'parent'}>
<div className={wm(styles.toastContainer, { [className!]: !!className })}>
<Toast
text={messages.copiedLabel}
delay={2000}
placement={ComponentPlacement.TOP}
mount={MountPlacement.PARENT}
>
<div className={wm(styles.inviteButtonContainer)}>
<Button
variant='primary'
iconRight={IconCopy}
onClick={onButtonClick}
fullWidth
>
{messages.inviteLabel}
</Button>
</div>
</Toast>
</div>
</Tooltip>
)
}

const getErrorMessage = (aaoErrorCode?: number) => {
if (aaoErrorCode !== undefined) {
return (
Expand Down Expand Up @@ -186,16 +135,11 @@ export const ChallengeRewardsModal = () => {
dispatch(resetAndCancelClaimReward())
}, [dispatch, setOpen])

const { title, icon } = getChallengeConfig(modalType)
const { title } = getChallengeConfig(modalType)

return (
<ModalDrawer
title={
<>
{icon}
{title}
</>
}
title={<>{title}</>}
showTitleHeader
isOpen={isOpen}
onClose={onClose}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
challengeRewardsConfig,
getChallengeStatusLabel
} from '@audius/common/utils'
import { Button, Flex, IconVerified, Text, IconCheck } from '@audius/harmony'
import { Button, Flex, IconCheck, Text } from '@audius/harmony'
import { useDispatch, useSelector } from 'react-redux'

import { push as pushRoute } from 'utils/navigation'
Expand All @@ -23,7 +23,6 @@ const { getClaimStatus, getUndisbursedUserChallenges } =

const messages = {
audio: '$AUDIO',
verifiedChallenge: 'VERIFIED CHALLENGE',
cooldownDescription:
'Note: There is a 7 day waiting period from completion until you can claim your reward.'
}
Expand All @@ -43,10 +42,9 @@ export const DefaultChallengeContent = ({

const config = challengeRewardsConfig[challengeName as ChallengeName] ?? {
fullDescription: () => '',
completedLabel: '',
isVerifiedChallenge: false
completedLabel: ''
}
const { fullDescription, completedLabel, isVerifiedChallenge } = config
const { fullDescription, completedLabel } = config

const isProgressBarVisible =
challenge &&
Expand All @@ -56,12 +54,6 @@ export const DefaultChallengeContent = ({

const progressDescription = (
<Flex column gap='m' w='100%'>
{isVerifiedChallenge ? (
<Flex gap='s'>
<IconVerified />
{messages.verifiedChallenge}
</Flex>
) : null}
<Text variant='body'>{fullDescription?.(challenge)}</Text>
{challenge?.cooldown_days ? (
<Text variant='body' color='subdued'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,6 @@ export const ListenStreakChallengeModalContent = ({
</Flex>
) : null}
</Flex>
{userChallenge.claimableAmount ? (
<Flex
backgroundColor='surface1'
ph='xl'
pv='m'
borderRadius='s'
border='default'
justifyContent='space-between'
>
<Text variant='title'>{messages.readyToClaim}</Text>
<Text variant='title'>{userChallenge?.claimableAmount}</Text>
</Flex>
) : null}
</Flex>
) : null

Expand Down
Loading