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

Dashboard: CurrentSeasonCard component #378

Merged
merged 27 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
045f6ca
Implement `PageLayout` component
kpyszkowski Apr 24, 2024
2f19593
Implement `CurrentSeasonCard` component structure
kpyszkowski Apr 24, 2024
be5ccd8
Add base styling of "current-season" Card variant
kpyszkowski Apr 24, 2024
e7ceadc
Make TVL and joined users optional
kpyszkowski May 6, 2024
7b94f63
Define styles as props
kpyszkowski May 6, 2024
d677b3f
Remove use of `CardFooter` component
kpyszkowski May 6, 2024
012625b
Resolve Eslint error
kpyszkowski May 6, 2024
18f33a8
Merge branch 'main' into dashboard/current-season-card
kpyszkowski May 9, 2024
fb945a2
Revert page changes
kpyszkowski May 6, 2024
0718b10
Delete `PageLayout` component
kpyszkowski May 9, 2024
2ef4980
Remove unused breakpoint
kpyszkowski May 9, 2024
10406c3
Merge branch 'main' into dashboard/current-season-card
kpyszkowski May 9, 2024
2e0b511
Add `CountdownTimer` component
kpyszkowski May 9, 2024
fe3c459
Add `LiveTag` component
kpyszkowski May 9, 2024
2270e3f
Add background
kpyszkowski May 9, 2024
fb212e1
Use `CurrencyBalance` to display TVL
kpyszkowski May 9, 2024
fe7d1cf
Use `numberToLocaleString` function
kpyszkowski May 13, 2024
a308b28
Remove redundant Box element
kpyszkowski May 13, 2024
3c28cb7
Change type of heading element
kpyszkowski May 13, 2024
e78bb06
Update `letter-spacing` property value
kpyszkowski May 13, 2024
72f9384
Remove `radius` property on container
kpyszkowski May 13, 2024
10ac8b5
Refactor to remove `Card` component
kpyszkowski May 14, 2024
99624fb
Remove redundant style properties
kpyszkowski May 14, 2024
bc6a405
Refactor `CountdownTimer` styles
kpyszkowski May 14, 2024
76f4794
Merge branch 'main' into dashboard/current-season-card
kpyszkowski May 14, 2024
115320f
Remove `CurrentSeasonCard` props
kpyszkowski May 14, 2024
f2a5f44
Merge branch 'main' into dashboard/current-season-card
kkosiorowska May 14, 2024
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: 2 additions & 1 deletion dapp/src/components/shared/CurrencyBalance/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export function CurrencyBalance({
balanceFontWeight = "bold",
symbolFontWeight = "bold",
symbolPosition = "suffix",
as,
...textProps
}: CurrencyBalanceProps) {
const styles = useMultiStyleConfig("CurrencyBalance", {
Expand All @@ -53,7 +54,7 @@ export function CurrencyBalance({
}, [amount, decimals, desiredDecimals, shouldBeFormatted])

return (
<Box __css={styles.container}>
<Box as={as} __css={styles.container}>
<Box
as="span"
fontWeight={balanceFontWeight}
Expand Down
102 changes: 79 additions & 23 deletions dapp/src/components/shared/SeasonCountdownSection/CountdownTimer.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,76 @@
import React, { useMemo } from "react"
import React from "react"
import { useCountdown } from "#/hooks"
import { Tuple } from "#/types"
import {
Box,
BoxProps,
HStack,
Grid,
Box,
HStack,
StackProps,
Text,
TextProps,
StackProps,
} from "@chakra-ui/react"
import { AnimatePresence, motion } from "framer-motion"
import { Tuple } from "#/types"

const MotionBox = motion(Box)
type SizeType = "sm" | "md"

const sizeStyles = {
digit: {
sm: {
px: 1,
w: 6,
py: 1,
rounded: "base",
},
md: {
px: 5,
w: 14,
py: 4,
rounded: "xl",
},
},

segment: {
sm: {
fontSize: "sm",
lineHeight: 5,
},
md: {
fontSize: "2xl",
lineHeight: 8,
},
},

segmentWrapper: {
sm: {
gap: "px",
},
md: {
gap: 2,
},
},

segmentSeparator: {
md: {
content: '":"',
},
},
}

type CountdownTimerDigitProps = Omit<BoxProps, "children"> & {
children: number
size: SizeType
}
function CountdownTimerDigit(props: CountdownTimerDigitProps) {
const { children, ...restProps } = props
const { children, size, ...restProps } = props
return (
<MotionBox
px={5}
w={14}
py={4}
rounded="xl"
<Box
as={motion.div}
sx={sizeStyles.digit[size]}
color="gold.200"
bg="grey.700"
overflow="hidden"
textAlign="center"
initial={{ opacity: 0 }}
animate={{ opacity: 1, transition: { staggerChildren: 0.1 } }}
{...restProps}
Expand All @@ -43,7 +86,7 @@ function CountdownTimerDigit(props: CountdownTimerDigitProps) {
{children}
</motion.div>
</AnimatePresence>
</MotionBox>
</Box>
)
}

Expand All @@ -64,39 +107,47 @@ function CountdownTimerSegmentLabel(props: TextProps) {
type CountdownTimerSegmentProps = Omit<BoxProps, "children"> & {
label: string
value: Tuple<number>
size: SizeType
}
function CountdownTimerSegment(props: CountdownTimerSegmentProps) {
const { label, value, ...restProps } = props
const { label, value, size, ...restProps } = props
return (
<HStack
sx={sizeStyles.segment[size]}
spacing={2}
alignItems="baseline"
color="gold.200"
fontSize="2xl"
fontWeight="bold"
_notLast={{
_after: {
content: '":"',
content: size === "md" ? '":"' : undefined,
},
}}
>
<Grid templateColumns="repeat(2, 1fr)" gap={2} {...restProps}>
<CountdownTimerDigit>{value[0]}</CountdownTimerDigit>
<CountdownTimerDigit>{value[1]}</CountdownTimerDigit>
<CountdownTimerSegmentLabel>{label}</CountdownTimerSegmentLabel>
<Grid
templateColumns="repeat(2, 1fr)"
sx={sizeStyles.segmentWrapper[size]}
{...restProps}
>
<CountdownTimerDigit size={size}>{value[0]}</CountdownTimerDigit>
<CountdownTimerDigit size={size}>{value[1]}</CountdownTimerDigit>
{size === "md" && (
<CountdownTimerSegmentLabel>{label}</CountdownTimerSegmentLabel>
)}
</Grid>
</HStack>
)
}

type CountdownTimerProps = Omit<StackProps, "children"> & {
timestamp: number
size?: SizeType
}
export function CountdownTimer(props: CountdownTimerProps) {
const { timestamp, ...restProps } = props
const { timestamp, size = "md", ...restProps } = props
const countdown = useCountdown(timestamp)

const parsedCountdown = useMemo(
const parsedCountdown = React.useMemo(
() =>
Object.entries(countdown).reduce<[string, Tuple<number>][]>(
(accumulator, currentValue) => {
Expand All @@ -120,7 +171,12 @@ export function CountdownTimer(props: CountdownTimerProps) {
return (
<HStack spacing={2} userSelect="none" {...restProps}>
{parsedCountdown.map(([label, value]) => (
<CountdownTimerSegment key={label} label={label} value={value} />
<CountdownTimerSegment
key={label}
label={label}
value={value}
size={size}
/>
))}
</HStack>
)
Expand Down
42 changes: 24 additions & 18 deletions dapp/src/components/shared/SeasonCountdownSection/LiveTag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,37 @@ export function LiveTag(props: TagProps) {
rounded="3xl"
bg="grey.700"
variant="solid"
pos="relative"
fontSize="md"
lineHeight={5}
fontWeight="bold"
gap={3}
{...props}
>
<Box rounded="full" w={2} h={2} mr={3} bg="brand.400" />
<MotionBox
pos="absolute"
rounded="full"
w={2}
h={2}
bg="brand.400"
animate={{ scale: [1, 6], opacity: [0.5, 0] }}
transition={{
duration: 2,
ease: "easeInOut",
repeat: Infinity,
}}
/>
<Box pos="relative">
<Box rounded="full" w={2} h={2} bg="brand.400" />
<MotionBox
pos="absolute"
top={0}
rounded="full"
w={2}
h={2}
bg="brand.400"
animate={{ scale: [1, 6], opacity: [0.5, 0] }}
transition={{
duration: 2,
ease: "easeInOut",
repeat: Infinity,
}}
/>
</Box>
<TagLabel
color="gold.200"
textTransform="uppercase"
fontStyle="italic"
overflow="visible"
fontSize="md"
lineHeight={5}
fontWeight="bold"
fontSize="inherit"
fontWeight="inherit"
lineHeight="inherit"
>
Live
</TagLabel>
Expand Down
2 changes: 2 additions & 0 deletions dapp/src/constants/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export const ONE_DAY_IN_SECONDS = ONE_HOUR_IN_SECONDS * 24
export const ONE_WEEK_IN_SECONDS = ONE_DAY_IN_SECONDS * 7
export const ONE_MONTH_IN_SECONDS = ONE_DAY_IN_SECONDS * 30
export const ONE_YEAR_IN_SECONDS = ONE_DAY_IN_SECONDS * 365

export const SEASON_DUE_TIMESTAMP = new Date(2024, 5, 9).getTime() / 1000
77 changes: 77 additions & 0 deletions dapp/src/pages/DashboardPage/CurrentSeasonCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React from "react"
import { StackProps, Flex, VStack, Heading } from "@chakra-ui/react"
import { numberToLocaleString } from "#/utils"
import { TextMd } from "#/components/shared/Typography"
import {
CountdownTimer,
LiveTag,
SeasonCountdownSectionBackground,
} from "#/components/shared/SeasonCountdownSection"
import { CurrencyBalance } from "#/components/shared/CurrencyBalance"
import { SEASON_DUE_TIMESTAMP } from "#/constants"

type CurrentSeasonCardProps = StackProps & {
showSeasonStats?: boolean
}

export function CurrentSeasonCard(props: CurrentSeasonCardProps) {
const { showSeasonStats = true, ...restProps } = props

const totalJoined = 3045 // TODO: fetch from API
const tvl = 144500000000 // TODO: fetch from API

return (
<VStack
spacing={4}
px={5}
py={4}
w="full"
align="stretch"
position="relative"
{...restProps}
>
<LiveTag fontSize="sm" px={3} py={1} gap={2} />

<Heading
as="p"
color="gold.100"
fontSize="2xl"
lineHeight={1}
letterSpacing="-0.03rem" // -0.48px
>
Season 1 <br />
Pre-launch staking
</Heading>

<CountdownTimer size="sm" timestamp={SEASON_DUE_TIMESTAMP} />

{showSeasonStats && (
<Flex align="baseline" justify="space-between" color="white">
<TextMd fontWeight="medium">
Total joined&nbsp;
<TextMd as="span" fontWeight="bold">
{numberToLocaleString(totalJoined)}
</TextMd>
</TextMd>

<TextMd display="flex" fontWeight="medium">
TVL&nbsp;
<CurrencyBalance
as="span"
amount={tvl}
currency="bitcoin"
fontSize="md"
fontWeight="bold"
/>
</TextMd>
</Flex>
)}

<SeasonCountdownSectionBackground
position="absolute"
inset={0}
zIndex={-1}
/>
</VStack>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import {
SeasonCountdownSectionBackground,
CountdownTimer,
} from "#/components/shared/SeasonCountdownSection"

const SEASON_DUE_TIMESTAMP = new Date(2024, 5, 9).getTime() / 1000
import { SEASON_DUE_TIMESTAMP } from "#/constants"

export default function SeasonCountdownSection() {
return (
Expand Down
Loading