Skip to content

Commit

Permalink
Update UI of SuccessModal (#820)
Browse files Browse the repository at this point in the history
Closes #812
Closes #815

The current UI of the Withdrawal/Deposit Initiated screen is outdated
and requires content updates and a style refresh. This PR updates the
content on the screen to ensure it is accurate and relevant and
redesigns the screen to match the latest UI style.

## UI

**Before**
<img width="250" alt="Screenshot 2024-10-30 at 10 43 58"
src="https://github.com/user-attachments/assets/31715d22-0578-42fc-8fe0-f6e4d86a01f4">

<img width="250" alt="Screenshot 2024-10-30 at 10 55 15"
src="https://github.com/user-attachments/assets/72bb7e50-2b21-4128-af8d-92236a366622">


**After**
<img width="250" alt="Screenshot 2024-10-30 at 10 50 33"
src="https://github.com/user-attachments/assets/8b57485d-26b6-454b-9c22-581ea94091a8">

<img width="250" alt="Screenshot 2024-10-30 at 10 49 07"
src="https://github.com/user-attachments/assets/fd9de500-4032-487b-a125-08b684605ec6">
  • Loading branch information
kpyszkowski authored Oct 31, 2024
2 parents f05d840 + 26b00b3 commit 6836277
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 147 deletions.
43 changes: 32 additions & 11 deletions dapp/src/assets/icons/LoadingSpinnerSuccessIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,47 @@
import React from "react"
import { createIcon } from "@chakra-ui/react"

export const LoadingSpinnerSuccessIcon = createIcon({
export default createIcon({
displayName: "LoadingSpinnerSuccessIcon",
viewBox: "0 0 48 48",
viewBox: "0 0 56 56",
defaultProps: {
fill: "none",
},
path: [
<g filter="url(#filter0_b_55_2073)">
<circle cx="28" cy="28" r="28" fill="#33A321" fillOpacity="0.15" />
</g>,
<path
d="M45.75 24C45.75 26.8563 45.1874 29.6845 44.0944 32.3234C43.0013 34.9622 41.3992 37.3599 39.3796 39.3796C37.3599 41.3992 34.9622 43.0013 32.3234 44.0944C29.6845 45.1874 26.8562 45.75 24 45.75C21.1437 45.75 18.3155 45.1874 15.6766 44.0944C13.0378 43.0013 10.6401 41.3992 8.62042 39.3796C6.60075 37.3599 4.99866 34.9622 3.90562 32.3234C2.81258 29.6845 2.25 26.8562 2.25 24C2.25 21.1437 2.81258 18.3155 3.90562 15.6766C4.99866 13.0378 6.60076 10.6401 8.62043 8.62042C10.6401 6.60075 13.0378 4.99866 15.6766 3.90562C18.3155 2.81258 21.1438 2.25 24 2.25C26.8563 2.25 29.6845 2.81258 32.3234 3.90562C34.9622 4.99867 37.3599 6.60076 39.3796 8.62044C41.3993 10.6401 43.0013 13.0378 44.0944 15.6766C45.1874 18.3155 45.75 21.1438 45.75 24L45.75 24Z"
stroke="#EDD8A2"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
/>,
<path
d="M31.2008 19.2002L21.6008 28.8002L16.8008 24.4002"
stroke="#318401"
d="M37 22L25 34L19 28.5"
stroke="#33A321"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
/>,
<defs>
<filter
id="filter0_b_55_2073"
x="-16"
y="-16"
width="88"
height="88"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation="8" />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_55_2073"
/>
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_backgroundBlur_55_2073"
result="shape"
/>
</filter>
</defs>,
],
})
2 changes: 1 addition & 1 deletion dapp/src/assets/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export * from "./Info"
export * from "./ArrowUpRight"
export * from "./AcreLogo"
export * from "./Pause"
export * from "./LoadingSpinnerSuccessIcon"
export { default as LoadingSpinnerSuccessIcon } from "./LoadingSpinnerSuccessIcon"
export * from "./BitcoinIcon"
export * from "./CableWithPlugIcon"
export * from "./MezoSignIcon"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
useActionFlowTxHash,
useAppDispatch,
useExecuteFunction,
useFetchActivities,
useStakeFlowContext,
} from "#/hooks"
import { PROCESS_STATUSES } from "#/types"
Expand All @@ -21,16 +20,14 @@ export default function StakingErrorModal({
}) {
const { stake } = useStakeFlowContext()
const dispatch = useAppDispatch()
const fetchActivities = useFetchActivities()
const txHash = useActionFlowTxHash()

const [isLoading, setIsLoading] = useState(false)
const [isServerError, setIsServerError] = useState(false)

const onStakeBTCSuccess = useCallback(() => {
logPromiseFailure(fetchActivities())
dispatch(setStatus(PROCESS_STATUSES.SUCCEEDED))
}, [dispatch, fetchActivities])
}, [dispatch])

const onStakeBTCError = useCallback(() => setIsServerError(true), [])

Expand Down
189 changes: 64 additions & 125 deletions dapp/src/components/TransactionModal/SuccessModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { ReactNode } from "react"
import React from "react"
import {
Button,
HStack,
Icon,
ModalBody,
Expand All @@ -10,146 +9,86 @@ import {
VStack,
} from "@chakra-ui/react"
import { LoadingSpinnerSuccessIcon } from "#/assets/icons"
import {
useActionFlowTokenAmount,
useActionFlowTxHash,
useModal,
useAllActivitiesCount,
useFetchActivities,
useAppNavigate,
} from "#/hooks"
import { useActionFlowTokenAmount, useActionFlowTxHash } from "#/hooks"
import { CurrencyBalanceWithConversion } from "#/components/shared/CurrencyBalanceWithConversion"
import { ACTION_FLOW_TYPES, ActionFlowType, MODAL_TYPES } from "#/types"
import { routerPath } from "#/router/path"
import { ACTION_FLOW_TYPES, ActionFlowType } from "#/types"
import { IconArrowUpRight } from "@tabler/icons-react"
import { logPromiseFailure } from "#/utils"
import { featureFlags } from "#/constants"
import { TextMd } from "../shared/Typography"
import Spinner from "../shared/Spinner"
import { getEstimatedDuration } from "#/utils"
import { Alert, AlertIcon, AlertDescription } from "#/components/shared/Alert"
import { TextMd, TextSm } from "../shared/Typography"
import BlockExplorerLink from "../shared/BlockExplorerLink"

function StakeContent() {
const tokenAmount = useActionFlowTokenAmount()
const txHash = useActionFlowTxHash()

return (
<>
{tokenAmount && (
<VStack spacing={0}>
<CurrencyBalanceWithConversion
from={{
currency: tokenAmount.currency,
amount: tokenAmount.amount.toString(),
size: "4xl",
}}
to={{
currency: "usd",
size: "lg",
color: "grey.500",
fontWeight: "semibold",
}}
/>
</VStack>
)}
{/* TODO: Update styles */}
{txHash && (
<BlockExplorerLink
id={txHash}
type="transaction"
chain="bitcoin"
mt={2}
>
<HStack gap={1}>
<TextMd fontWeight="semibold">View on Mempool</TextMd>
<Icon as={IconArrowUpRight} color="brand.400" boxSize={5} />
</HStack>
</BlockExplorerLink>
)}
</>
)
}

function UnstakeContent() {
return (
<TextMd>
You’ll receive your funds once the unstaking process is completed. Follow
the progress in your dashboard.
</TextMd>
)
}

const CONTENT: Record<
ActionFlowType,
{
heading: string
footer: string
renderComponent: () => ReactNode
}
> = {
[ACTION_FLOW_TYPES.STAKE]: {
heading: "Deposit received",
renderComponent: StakeContent,
footer: "The staking will continue in the background",
},
[ACTION_FLOW_TYPES.UNSTAKE]: {
heading: "Withdrawal initiated",
renderComponent: UnstakeContent,
footer: "The unstaking will continue in the background",
},
}

type SuccessModalProps = {
type: ActionFlowType
}

export default function SuccessModal({ type }: SuccessModalProps) {
const { closeModal, openModal } = useModal()
const fetchActivities = useFetchActivities()
const navigate = useAppNavigate()
const allActivitiesCount = useAllActivitiesCount()

const { heading, footer, renderComponent } = CONTENT[type]

const handleCloseModal = () => {
closeModal()
navigate(routerPath.home)

if (featureFlags.GAMIFICATION_ENABLED) {
// TODO: Temporary solution - Showing the welcome window should be done
// only once a season for new users. "New" can also refer to users who,
// in the past, may have deposited but withdrew their funds, losing their rewards.
// By making a new deposit, they will get their rewards back.
if (allActivitiesCount === 0) {
openModal(MODAL_TYPES.WELCOME)
}
}
const tokenAmount = useActionFlowTokenAmount()
const txHash = useActionFlowTxHash()

logPromiseFailure(fetchActivities())
}
// TODO: We should use one type for flow and activity
const activityType = type === ACTION_FLOW_TYPES.STAKE ? "deposit" : "withdraw"

return (
<>
{type === ACTION_FLOW_TYPES.UNSTAKE && <ModalCloseButton />}
<ModalHeader>{heading}</ModalHeader>
<ModalCloseButton />
<ModalHeader textAlign="center" pt={16}>
{ACTION_FLOW_TYPES.UNSTAKE === type
? "Withdrawal initiated!"
: "Deposit received!"}
</ModalHeader>
<ModalBody gap={10}>
<VStack gap={4}>
<LoadingSpinnerSuccessIcon boxSize={20} />
{renderComponent()}
<LoadingSpinnerSuccessIcon boxSize={14} />

{tokenAmount && (
<VStack spacing={0} mb={9}>
<CurrencyBalanceWithConversion
from={{
currency: tokenAmount.currency,
amount: tokenAmount.amount.toString(),
size: "4xl",
fontWeight: "semibold",
}}
to={{
currency: "usd",
size: "md",
fontWeight: "medium",
}}
/>
</VStack>
)}
{ACTION_FLOW_TYPES.UNSTAKE === type && (
<TextMd>
Funds will arrive in your wallet once the withdrawal is complete.
Track progress in your dashboard.
</TextMd>
)}
{ACTION_FLOW_TYPES.STAKE === type && txHash && (
/* TODO: Update styles */
<BlockExplorerLink id={txHash} type="transaction" chain="bitcoin">
<HStack gap={1}>
<TextSm color="grey.600" fontWeight="semibold">
View on Mempool
</TextSm>
<Icon as={IconArrowUpRight} color="brand.400" boxSize={4} />
</HStack>
</BlockExplorerLink>
)}
</VStack>
</ModalBody>
<ModalFooter pt={0}>
<Button
size="lg"
width="100%"
variant="outline"
onClick={handleCloseModal}
>
Go to dashboard
</Button>
<HStack spacing={2}>
<Spinner borderWidth={2} variant="filled" />
<TextMd>{footer}</TextMd>
</HStack>
<ModalFooter pt={2}>
<Alert variant="elevated">
<AlertIcon status="loading" />
<AlertDescription>
<TextSm>You can close this window.</TextSm>
<TextSm>The process will continue in the background.</TextSm>
<TextSm color="#7D6A4B">
Estimated duration&nbsp; ~{" "}
{getEstimatedDuration(tokenAmount?.amount ?? 0n, activityType)}
</TextSm>
</AlertDescription>
</Alert>
</ModalFooter>
</>
)
Expand Down
6 changes: 5 additions & 1 deletion dapp/src/components/TransactionModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import React, { useEffect } from "react"
import { StakeFlowProvider } from "#/contexts"
import {
useAppDispatch,
useFetchActivities,
useIsSignedMessage,
useSidebar,
useTransactionModal,
} from "#/hooks"
import { ActionFlowType, BaseModalProps } from "#/types"
import { resetState, setType } from "#/store/action-flow"
import { logPromiseFailure } from "#/utils"
import ModalContentWrapper from "./ModalContentWrapper"
import { ActiveFlowStep } from "./ActiveFlowStep"
import withBaseModal from "../ModalRoot/withBaseModal"
Expand All @@ -18,6 +20,7 @@ type TransactionModalProps = { type: ActionFlowType } & BaseModalProps
function TransactionModalBase({ type, closeModal }: TransactionModalProps) {
const { onOpen: openSideBar, onClose: closeSidebar } = useSidebar()
const dispatch = useAppDispatch()
const fetchActivities = useFetchActivities()

useEffect(() => {
dispatch(setType(type))
Expand All @@ -27,8 +30,9 @@ function TransactionModalBase({ type, closeModal }: TransactionModalProps) {
useEffect(() => {
return () => {
dispatch(resetState())
logPromiseFailure(fetchActivities())
}
}, [dispatch])
}, [dispatch, fetchActivities])

useEffect(() => {
openSideBar()
Expand Down
3 changes: 2 additions & 1 deletion dapp/src/components/shared/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const STATUSES = {
},
loading: {
icon: Spinner,
colorScheme: "grey",
colorScheme: "brand",
},
}

Expand All @@ -56,6 +56,7 @@ function AlertIcon(props: AlertProps) {
? {
...styles.spinner,
...styles.icon,
color: `${getStatusColorScheme(status)}.400`,
}
: styles.icon

Expand Down
4 changes: 2 additions & 2 deletions dapp/src/theme/Alert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ const variantSubtle = multiStyleConfig.definePartsStyle(({ colorScheme }) => {
const variantElevated = multiStyleConfig.definePartsStyle(({ colorScheme }) => {
const backgroundColor = getColorLevel(colorScheme, 200)
const foregroundColor = getColorLevel("grey", 700)
const borderColor = getColorLevel(colorScheme, 300)

return {
container: {
[$backgroundColor.variable]: backgroundColor,
[$borderColor.variable]: borderColor,
[$foregroundColor.variable]: foregroundColor,
border: "none",
},
}
})
Expand Down
4 changes: 2 additions & 2 deletions dapp/src/theme/Modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ const baseStyleOverlay = defineStyle({

const baseStyleHeader = defineStyle({
textAlign: "left",
fontSize: "lg",
lineHeight: "lg",
fontSize: "xl",
lineHeight: "xl",
fontWeight: "bold",
pt: 10,
px: 10,
Expand Down

0 comments on commit 6836277

Please sign in to comment.