Skip to content

Commit

Permalink
tech(active-wallet): add spinner and error state
Browse files Browse the repository at this point in the history
  • Loading branch information
eliobricenov committed Dec 20, 2024
1 parent 1841cfe commit 3cfe470
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 163 deletions.
92 changes: 0 additions & 92 deletions src/components/ActiveWalletSection/ActiveWalletSection.stories.tsx

This file was deleted.

4 changes: 4 additions & 0 deletions src/components/ActiveWalletSection/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,7 @@
font-weight: var(--semibold);
color: var(--color-neutral-400);
}

.loadingSpinner {
font-size: var(--text-xs);
}
97 changes: 68 additions & 29 deletions src/components/ActiveWalletSection/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Button, Images, Alert } from '@hyperplay/ui'
import { Button, Images, Alert, LoadingSpinner, AlertCard } from '@hyperplay/ui'
import styles from './index.module.scss'
import cn from 'classnames'
import { useTranslation } from 'react-i18next'
import { TFunction } from 'i18next'
import { truncateEthAddress } from '../truncateAddress'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useQuestWrapper } from '@/state/QuestWrapperProvider'
import { useAccount } from 'wagmi'

function InfoAlert({
title,
Expand Down Expand Up @@ -59,22 +61,39 @@ function InputLikeContainer({
)
}

interface ActiveWalletSectionProps {
connectedWallet: string | null
activeWallet: string | null
setActiveWallet: () => void
tOverride?: TFunction<any, string>
}
export default function ActiveWalletSection() {
const queryClient = useQueryClient()
const { address: connectedWallet } = useAccount()
const { getActiveWallet, setActiveWallet, tOverride, openDiscordLink } =
useQuestWrapper()

export default function ActiveWalletSection({
connectedWallet,
activeWallet,
setActiveWallet,
tOverride
}: ActiveWalletSectionProps) {
const { t: tOriginal } = useTranslation()
const t = tOverride || tOriginal

const { data: activeWallet } = useQuery({
queryKey: ['activeWallet'],
queryFn: async () => {
return getActiveWallet()
}
})

const {
mutate: setActiveWalletMutation,
isPending,
error
} = useMutation({
mutationFn: async () => {
if (!connectedWallet) {
throw new Error('No address found')
}

await setActiveWallet(connectedWallet)
await queryClient.invalidateQueries({
queryKey: ['activeWallet']
})
}
})

const onlyConnectedWallet = (
<InfoAlert title={t('wallet.detected.title', 'Wallet Detected')}>
<span className="body-sm">
Expand Down Expand Up @@ -109,6 +128,21 @@ export default function ActiveWalletSection({
</InfoAlert>
)

const setButton = (
<Button
disabled={isPending}
type="secondaryGradient"
className={styles.setButton}
onClick={() => setActiveWalletMutation()}
>
{isPending ? (
<LoadingSpinner className={styles.loadingSpinner} />
) : (
t('wallet.action.set', 'Set')
)}
</Button>
)

const hasNoWallets = !connectedWallet && !activeWallet
const hasOnlyConnectedWallet = connectedWallet && !activeWallet
const hasOnlyActiveWallet = activeWallet && !connectedWallet
Expand Down Expand Up @@ -151,13 +185,7 @@ export default function ActiveWalletSection({
<InputLikeBox className={styles.setConnectedWalletInput}>
{truncateEthAddress(connectedWallet ?? '')}
</InputLikeBox>
<Button
type="secondaryGradient"
className={styles.setButton}
onClick={setActiveWallet}
>
{t('wallet.action.set', 'Set')}
</Button>
{setButton}
</div>
</InputLikeContainer>
</>
Expand Down Expand Up @@ -204,18 +232,29 @@ export default function ActiveWalletSection({
<InputLikeBox className={styles.setConnectedWalletInput}>
{truncateEthAddress(connectedWallet ?? '')}
</InputLikeBox>
<Button
type="secondaryGradient"
className={styles.setButton}
onClick={setActiveWallet}
>
{t('wallet.action.set', 'Set')}
</Button>
{setButton}
</div>
</InputLikeContainer>
</>
)
}

return <div className={styles.root}>{content}</div>
const alertProps = {
showClose: false,
title: t('wallet.error.title', 'Something went wrong'),
message: t(
'wallet.error.message',
"Please try once more. If it still doesn't work, create a Discord support ticket."
),
actionText: t('wallet.error.action', 'Create Discord Ticket'),
onActionClick: () => openDiscordLink(),
variant: 'danger' as const
}

return (
<div className={styles.root}>
{content}
{error && <AlertCard {...alertProps} />}
</div>
)
}
6 changes: 0 additions & 6 deletions src/components/ActiveWalletSection/story-styles.module.scss

This file was deleted.

37 changes: 3 additions & 34 deletions src/components/PlayStreakEligibilityWrapper/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,25 @@ import { useGetUserPlayStreak } from '@/hooks/useGetUserPlayStreak'
import { useHasPendingExternalSync } from '@/hooks/useHasPendingExternalSync'
import { useQuestWrapper } from '@/state/QuestWrapperProvider'
import { Button, Images, StreakProgress } from '@hyperplay/ui'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import styles from './index.module.scss'
import { useAccount } from 'wagmi'
import ActiveWalletSection from '../ActiveWalletSection'

export function PlayStreakEligibilityWrapper({
questId
}: {
questId: number | null
}) {
const queryClient = useQueryClient()

const {
syncPlayStreakWithExternalSource,
getPendingExternalSync,
getUserPlayStreak,
getQuest,
getActiveWallet,
setActiveWallet
getQuest
} = useQuestWrapper()
const { t } = useTranslation()
const { data: questMeta } = useGetQuest(questId, getQuest)
const { address } = useAccount()

const { data: activeWallet } = useQuery({
queryKey: ['activeWallet'],
queryFn: async () => {
return getActiveWallet()
}
})

const { mutateAsync: setActiveWalletMutation } = useMutation({
mutationFn: async () => {
if (!address) {
throw new Error('No address found')
}

await setActiveWallet(address)
await invalidateQuestPlayStreak()
await queryClient.invalidateQueries({
queryKey: ['activeWallet']
})
}
})

const {
data: questPlayStreakData,
Expand Down Expand Up @@ -124,11 +97,7 @@ export function PlayStreakEligibilityWrapper({

return (
<div className={styles.container}>
<ActiveWalletSection
connectedWallet={address ?? null}
activeWallet={activeWallet ?? null}
setActiveWallet={setActiveWalletMutation}
/>
<ActiveWalletSection />
<StreakProgress
{...getPlaystreakArgsFromQuestData({
questMeta: questMeta.data,
Expand Down
27 changes: 25 additions & 2 deletions src/components/QuestDetailsWrapper/PlayStreakQuest.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,10 @@ export const ActiveWalletConnectDefault: Story = {
<QuestDetailsWrapper
{...args}
getActiveWallet={async () => Promise.resolve(activeWallet)}
setActiveWallet={async (wallet) => setActiveWallet(wallet)}
setActiveWallet={async (wallet) => {
setActiveWallet(wallet)
await new Promise((resolve) => setTimeout(resolve, 2000))
}}
/>
)
}
Expand All @@ -260,7 +263,27 @@ export const ActiveWalletSwitchWallet: Story = {
<QuestDetailsWrapper
{...args}
getActiveWallet={async () => Promise.resolve(activeWallet)}
setActiveWallet={async (wallet) => setActiveWallet(wallet)}
setActiveWallet={async (wallet) => {
setActiveWallet(wallet)
await new Promise((resolve) => setTimeout(resolve, 2000))
}}
/>
)
}
}

export const ActiveWalletSwitchWalletError: Story = {
args: {
...mockProps
},
render: (args) => {
return (
<QuestDetailsWrapper
{...args}
setActiveWallet={async () => {
await new Promise((resolve) => setTimeout(resolve, 3000))
throw new Error('Error')
}}
/>
)
}
Expand Down

0 comments on commit 3cfe470

Please sign in to comment.