Skip to content
Merged
8 changes: 6 additions & 2 deletions src/components/Icon.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { FC } from "react"
import { As, Icon as ChakraIcon, IconProps } from "@chakra-ui/react"
import {
As,
Icon as ChakraIcon,
IconProps,
} from "@threshold-network/components"
import IconEnum from "../enums/icon"
import iconMap from "../static/icons/iconMap"

Expand All @@ -10,7 +14,7 @@ const Icon: FC<IconProps & { as: As | IconEnum }> = ({ as, ...props }) => {
}

// @ts-ignore
return <ChakraIcon {...props} />
return <ChakraIcon as={as} {...props} />
}

export default Icon
201 changes: 201 additions & 0 deletions src/components/tBTC/BridgeActivity.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import { FC, createContext, useContext, ReactElement } from "react"
import {
Badge,
BodyMd,
Image,
List,
useColorModeValue,
Box,
LinkBox,
LinkOverlay,
Stack,
Skeleton,
ListProps,
HStack,
StackProps,
LabelSm,
} from "@threshold-network/components"
import {
BridgeActivityStatus,
BridgeActivity as BridgeActivityType,
} from "../../threshold-ts/tbtc"
import emptyHistoryImageSrcDark from "../../static/images/tBTC-bridge-no-history-dark.svg"
import emptyHistoryImageSrcLight from "../../static/images/tBTC-bridge-no-history-light.svg"
import { InlineTokenBalance } from "../TokenBalance"
import Link from "../Link"
import { OutlineListItem } from "../OutlineListItem"

export type BridgeActivityProps = {
data: BridgeActivityType[]
isFetching: boolean
emptyState?: ReactElement
}

type BridgeActivityContextValue = {
[Property in keyof BridgeActivityProps]-?: BridgeActivityProps[Property]
} & { isBridgeHistoryEmpty: boolean }

const BridgeActivityContext = createContext<
BridgeActivityContextValue | undefined
>(undefined)

const useBridgeActivityContext = () => {
const context = useContext(BridgeActivityContext)
if (!context) {
throw new Error(
"BridgeActivityContext used outside of the BridgeActivity component."
)
}

return context
}

export const BridgeActivity: FC<BridgeActivityProps> = ({
data,
isFetching,
emptyState,
children,
}) => {
const isBridgeHistoryEmpty = data.length === 0

return (
<BridgeActivityContext.Provider
value={{
data,
isBridgeHistoryEmpty,
isFetching,
emptyState: emptyState ?? <EmptyActivity />,
}}
>
{children}
</BridgeActivityContext.Provider>
)
}

export const BridgeAcivityHeader: FC<StackProps> = (props) => {
return (
<HStack justifyContent="space-between" mt="10" {...props}>
<LabelSm color="gray.500">tBTC</LabelSm>
<LabelSm color="gray.500">state</LabelSm>
</HStack>
)
}

export const BridgeActivityData: FC<ListProps> = (props) => {
const { data, isBridgeHistoryEmpty, isFetching, emptyState } =
useBridgeActivityContext()

return isFetching ? (
<BridgeActivityLoadingState />
) : (
<List spacing="1" mt="2" {...props}>
{isBridgeHistoryEmpty ? emptyState : data.map(renderActivityItem)}
</List>
)
}

const ActivityItem: FC<BridgeActivityType> = ({
amount,
status,
depositKey,
}) => {
return (
<ActivityItemWrapper>
<LinkOverlay
as={Link}
textDecoration="none"
_hover={{ textDecoration: "none" }}
color="inherit"
to={`/tBTC/mint/deposit/${depositKey}`}
>
<InlineTokenBalance tokenAmount={amount} />
</LinkOverlay>
<TBTCStatusBadge status={status} />
</ActivityItemWrapper>
)
}

const renderActivityItem = (item: BridgeActivityType) => (
<ActivityItem key={item.depositKey} {...item} />
)

const bridgeActivityStatusToBadgeProps: Record<
BridgeActivityStatus,
{ colorScheme: string }
> = {
[BridgeActivityStatus.MINTED]: {
colorScheme: "green",
},
[BridgeActivityStatus.PENDING]: {
colorScheme: "yellow",
},
[BridgeActivityStatus.ERROR]: {
colorScheme: "red",
},
}

const TBTCStatusBadge: FC<{ status: BridgeActivityStatus }> = ({ status }) => {
return (
<Badge
variant="subtle"
{...bridgeActivityStatusToBadgeProps[status]}
size="sm"
display="flex"
alignItems="center"
>
{status}
</Badge>
)
}

export const ActivityItemWrapper: FC = ({ children }) => (
<LinkBox as={OutlineListItem} pl="6" pr="3">
{children}
</LinkBox>
)

export const BridgeActivityEmptyHistoryImg: FC = () => {
const { isBridgeHistoryEmpty, isFetching } = useBridgeActivityContext()
const epmtyHistoryImg = useColorModeValue(
emptyHistoryImageSrcLight,
emptyHistoryImageSrcDark
)

return isBridgeHistoryEmpty && !isFetching ? (
<>
<Image alt="no-history" src={epmtyHistoryImg} mx="auto" mt={16} mb={4} />
<BodyMd textAlign="center">You have no history yet.</BodyMd>
</>
) : (
<></>
)
}

const EmptyActivityItem: FC = () => (
<ActivityItemWrapper>
<Box as="span" color="gray.700">
-.--
</Box>
<Box as="span" color="gray.700">
-.--
</Box>
</ActivityItemWrapper>
)
const EmptyActivity: FC = () => {
return (
<>
<EmptyActivityItem />
<EmptyActivityItem />
</>
)
}

const BridgeActivityLoadingState = () => {
return (
<Stack>
<Skeleton height="20px" />
<Skeleton height="20px" />
<Skeleton height="20px" />
</Stack>
)
}
2 changes: 2 additions & 0 deletions src/components/tBTC/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from "./TakeNoteList"
export * from "./Links"
export * from "./Stats"
export * from "./tBTCText"
export * from "./BridgeActivity"
13 changes: 13 additions & 0 deletions src/components/tBTC/tBTCText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { FC } from "react"
import { Box, BoxProps } from "@threshold-network/components"

export const TBTCText: FC<BoxProps> = (props) => {
return (
<Box as="span" {...props}>
<Box as="span" textTransform="lowercase">
t
</Box>
BTC
</Box>
)
}
4 changes: 1 addition & 3 deletions src/pages/Overview/Network/CardTemplate.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { FC } from "react"
import { LabelSm, Card, LineDivider } from "@threshold-network/components"
import { BoxProps } from "@chakra-ui/react"
import { LabelSm, Card, BoxProps } from "@threshold-network/components"

const CardTemplate: FC<{ title: string | JSX.Element } & BoxProps> = ({
title,
Expand All @@ -10,7 +9,6 @@ const CardTemplate: FC<{ title: string | JSX.Element } & BoxProps> = ({
return (
<Card h="100%" w="100%" {...boxProps}>
{typeof title === "string" ? <LabelSm>{title}</LabelSm> : title}
<LineDivider borderColor="gray.300" />
{children}
</Card>
)
Expand Down
6 changes: 4 additions & 2 deletions src/pages/Overview/Network/StakingOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ const StakingOverview: FC = () => {

return (
<CardTemplate title="STAKING" height="fit-content">
<BodyMd mb={2}>Staked Balance</BodyMd>
<InfoBox mt={4}>
<BodyMd mb={3} mt={4}>
My Staked Balance
</BodyMd>
<InfoBox>
<TokenBalance
icon={t.icon}
tokenAmount={stakedBalance.toString()}
Expand Down
11 changes: 4 additions & 7 deletions src/pages/Overview/Network/TotalValueLocked.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { FC } from "react"
import { Flex } from "@chakra-ui/react"
import CardTemplate from "./CardTemplate"
import { H1 } from "@threshold-network/components"
import { formatFiatCurrencyAmount } from "../../../utils/formatAmount"
Expand All @@ -10,12 +9,10 @@ const TotalValueLocked: FC<{ totalValueLocked: number | string }> = ({
const tvl = formatFiatCurrencyAmount(totalValueLocked)

return (
<CardTemplate title="TOTAL VALUE LOCKED" h="auto">
<Flex justifyContent="center">
<H1 fontSize={{ base: "4xl", lg: "6xl" }} fontWeight="700">
{tvl}
</H1>
</Flex>
<CardTemplate title="TOTAL VALUE LOCKED">
<H1 mt="10" mb="9" textAlign="center">
{tvl}
</H1>
</CardTemplate>
)
}
Expand Down
61 changes: 57 additions & 4 deletions src/pages/Overview/Network/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,46 @@
import { useEffect } from "react"
import { SimpleGrid, Stack } from "@threshold-network/components"
import {
Box,
Card,
HStack,
SimpleGrid,
Image,
H5,
BodyMd,
VStack,
} from "@threshold-network/components"
import { useWeb3React } from "@web3-react/core"
import TotalValueLocked from "./TotalValueLocked"
import StakingOverview from "./StakingOverview"
import { useFetchTvl } from "../../../hooks/useFetchTvl"
import { PageComponent } from "../../../types"
import { TBTCBrdigeStats } from "./tBTCBridgeStats"
import { useFetchRecentDeposits } from "../../../hooks/tbtc"
import { TBTCUserStats } from "./tBTCUserStats"
import { useAppDispatch, useAppSelector } from "../../../hooks/store"
import { selectBridgeActivity, tbtcSlice } from "../../../store/tbtc"
import ButtonLink from "../../../components/ButtonLink"
import upgradeToTIcon from "../../../static/images/upgrade-to-t.svg"

const Network: PageComponent = () => {
const [tvlInUSD, fetchtTvlData, tvlInTokenUnits] = useFetchTvl()
const [deposits, isFetching, error] = useFetchRecentDeposits()
const { account } = useWeb3React()
const dispatch = useAppDispatch()
const bridgeActivity = useAppSelector(selectBridgeActivity)
const isBridgeActivityFetching = useAppSelector(
(state) => state.tbtc.bridgeActivity.isFetching
)

useEffect(() => {
if (!account) return

dispatch(
tbtcSlice.actions.requestBridgeActivity({
depositor: account,
})
)
}, [dispatch, account])

useEffect(() => {
fetchtTvlData()
Expand All @@ -22,10 +53,32 @@ const Network: PageComponent = () => {
tvlInUSD={tvlInUSD.tBTC}
deposits={deposits}
/>
<Stack spacing={4}>
<StakingOverview />
<TBTCUserStats
bridgeActivity={bridgeActivity}
isBridgeActivityFetching={isBridgeActivityFetching}
/>
<VStack spacing="4">
<TotalValueLocked totalValueLocked={tvlInUSD.total} />
</Stack>
<Card>
<HStack spacing="6">
<Image src={upgradeToTIcon} />
<Box>
<H5>Do you own KEEP or NU tokens?</H5>
<BodyMd>Upgrade your tokens to T.</BodyMd>
</Box>
</HStack>
<ButtonLink
to="/upgrade"
variant="outline"
size="lg"
isFullWidth
mt="9"
>
Upgrade
</ButtonLink>
</Card>
</VStack>
<StakingOverview />
</SimpleGrid>
)
}
Expand Down
5 changes: 4 additions & 1 deletion src/pages/Overview/Network/tBTCBridgeStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Card, Divider, LabelSm } from "@threshold-network/components"
import {
DefaultProtocolHistory,
ProtocolHistoryProps,
TBTCText,
TVL,
TVLProps,
} from "../../../components/tBTC"
Expand All @@ -16,7 +17,9 @@ export const TBTCBrdigeStats: FC<TBTCBrdigeStatsProps> = ({
}) => {
return (
<Card>
<LabelSm mb="4">tBTC Bridge Stats</LabelSm>
<LabelSm mb="4">
<TBTCText /> Bridge Stats
</LabelSm>
<TVL tvl={tvl} tvlInUSD={tvlInUSD} />
<Divider my="6" />
<DefaultProtocolHistory deposits={deposits} />
Expand Down
Loading