PGS staking UI

This commit is contained in:
john 2022-05-13 11:43:44 +07:00
parent 6bcf6cf3ad
commit 8dd9a96d07
11 changed files with 392 additions and 122 deletions

View File

@ -20,7 +20,7 @@ const Row = ({ children }) => {
)
}
const CardRow = ({ title, value, compond = false }) => {
export const CardRow = ({ title, value, compond = false }) => {
return (
<Row>

View File

@ -1,13 +1,216 @@
import React from "react"
import {
VStack, Image, Text, HStack,
Button, Flex, Slider,
SliderTrack, SliderFilledTrack,
useColorModeValue, Badge,
VStack, Image, Text, Stack, HStack,
Button, Tag, Box,
useColorModeValue, Badge, Divider, Icon,
} from "@chakra-ui/react"
import { StateCard } from './NumCard'
import { useTranslation } from 'react-i18next'
import { ModalBox } from "./alert"
import { CardRow } from './FarmCoinCard'
import { FiLock, FiUnlock } from "react-icons/fi"
import { HBetween, HFStack, VFStack } from "./base"
export const StakingCoinCard = ({ symbol, icon, index, apy, vl, assets }) => {
/**
* Special Modal Box, Why not ask who is your daddy ???
*/
export const StakingModalStrategy = ({ isOpen, onClose,
icon, symbol, amount, percentage, address,
nodesStaked, nodesNominations, share, status }) => {
return (
<ModalBox
title="Strategy"
isOpen={isOpen}
onClose={onClose}
showFooter={false}
>
<VStack>
{/* title */}
<HStack
w="full"
align="center"
justify="space-between"
>
<HStack
>
<Image w="10" h="10" borderRadius="50%" src={icon} alt={symbol} />
<Text fontSize="22" fontWeight="900">
{symbol}
</Text>
</HStack>
<VStack>
<Text
fontSize="18"
fontWeight="700"
>
{amount}
</Text>
<Text
fontSize="12"
color="gray.400"
>
Staked
</Text>
</VStack>
</HStack>
{/* tips */}
<HStack>
<Text
color="yellow.400"
fontSize="14"
>
Note:The pledged amount of the node includes the pledged
amount of CoinWind's entire network staking
</Text>
</HStack>
{/* body */}
<VStack
w="full"
>
<CardRow title="Staking funds" value={amount} />
<CardRow title="Proportion of funds" value={percentage} />
<CardRow title="Staking Address" value={address?.substring(0, 6) + '...'} />
<CardRow title="Nodes Staked" value={nodesStaked} />
<CardRow title="Node Nominations" value={nodesNominations} />
<CardRow title="My share" value={share + '%'} />
<CardRow title="Status" value={status} />
</VStack>
</VStack>
</ModalBox>
)
}
export const StakingModalCertificate = ({ isOpen, onClose, onConfirm,
icon, symbol, index, assets, apy, income, start, days, authorized }) => {
const Row2Text = ({ row1, row2 }) => {
return (
<VStack
fontSize="14"
fontWeight="700"
align="start"
>
<Text>
{row1}
</Text>
<Text>
{row2}
</Text>
</VStack>
)
}
return (
<ModalBox
title="Certificate"
isOpen={isOpen}
onClose={onClose}
showCancel={false}
textConfirm="Certificate"
onConfirm={() => { onConfirm(index) }}
>
<VStack>
{/* title */}
<HStack
w="full"
align="center"
justify="space-between"
>
<HStack>
<Image w="10" h="10" borderRadius="50%" src={icon} alt={symbol} />
<Text fontSize="22" fontWeight="900">
{symbol}
</Text>
</HStack>
<VStack>
<Text
fontSize="16"
fontWeight="700"
color="gray.400"
>
{'Assets ' + assets}
</Text>
</VStack>
</HStack>
{/* tag */}
<HFStack py="4">
<Tag colorScheme="orange" variant="solid" size="lg">Current</Tag>
</HFStack>
<HBetween>
<Text
color="gray.400"
>
APY
</Text>
<Text
color="green.500"
fontSize="20"
fontWeight="700"
>
{apy}
</Text>
</HBetween>
<VFStack
borderWidth="1px"
borderRadius="lg"
boxShadow="lg"
p="4"
>
{/* progressing */}
<HFStack
color="green.400"
justify="center"
>
<Icon as={FiLock} />
<Box h="2px" w="40%" bg="green.400" />
<Icon as={FiUnlock} />
<Box h="2px" w="40%" bg="green.400" />
<Icon as={FiUnlock} />
</HFStack>
{/* intro */}
<HBetween py="4">
<Row2Text
row1={start}
row2="Deposite"
/>
<Row2Text
row1="At any time"
row2="Unlock"
/>
<Row2Text
row1={days + ' days after'}
row2="Claim"
/>
</HBetween>
</VFStack>
<HBetween pt="4">
<Text color="gray.400">Income</Text>
<Text fontWeight="700">{income}</Text>
</HBetween>
</VStack>
</ModalBox>
)
}
export const StakingCoinCard = ({
symbol, icon, index,
apy, vl, assets,
onStrategy,
onCertificate,
}) => {
const { t } = useTranslation()
const bg = useColorModeValue('white', 'gray.900')
@ -42,14 +245,63 @@ export const StakingCoinCard = ({ symbol, icon, index, apy, vl, assets }) => {
/>
</HStack>
{/* body */}
<VStack
<Divider />
{/* body */}
<Stack
py="2"
w="full"
direction="row"
>
<HStack>
<Badge colorScheme="orange">Current</Badge>
</Stack>
<HStack
py="2"
w="full"
justify="space-between"
>
<Text
color="gray.500"
>
{t('apy')}
</Text>
<Text
fontSize="22"
fontWeight="700"
color="green.500"
>
{apy}%
</Text>
</HStack>
<HStack
w="full"
>
<StateCard title={t('vl') + '(' + symbol + ')'} num={vl} />
<StateCard title={t('assets') + '(' + symbol + ')'} num={assets} />
</HStack>
<HStack
w="full"
justify="space-around"
align="center"
>
<Button
colorScheme="orange"
variant="outline"
onClick={() => { onStrategy(index) }}
>
{t('strategy')}
</Button>
<Button
colorScheme="orange"
onClick={() => { onCertificate(index) }}
>
{t('certificate')}
</Button>
</HStack>
</VStack>
</VStack>
)
}

View File

@ -1,7 +1,10 @@
import React from 'react'
import { Button, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay } from '@chakra-ui/react'
export const ModalBox = ({ title, isOpen, onClose, children, onConfirm = null, focusRef = null }) => {
export const ModalBox = ({ title, isOpen, onClose, children,
showFooter = true, showCancel = true, showConfirm = true,
textCancel = 'Cancel', textConfirm = 'OK',
onConfirm = null, focusRef = null }) => {
return (
<Modal
@ -18,14 +21,25 @@ export const ModalBox = ({ title, isOpen, onClose, children, onConfirm = null, f
{children}
</ModalBody>
<ModalFooter>
<Button colorScheme="blue" onClick={() => {
<ModalFooter display={showFooter ? 'flex' : 'none'}>
<Button
display={showConfirm ? 'flex' : 'none'}
colorScheme="blue"
onClick={() => {
onConfirm && onConfirm()
onClose()
}} mr={3}>
OK
}}
mr={3}
>
{textConfirm}
</Button>
<Button
display={showCancel ? 'flex' : 'none'}
onClick={onClose}
>
{textCancel}
</Button>
<Button onClick={onClose}>Cancel</Button>
</ModalFooter>
</ModalContent>
</Modal>

View File

@ -0,0 +1,8 @@
import { VStack } from "@chakra-ui/react"
export const VFStack = ({ children, ...rest }) => ((
<VStack w="full" {...rest}>
{children}
</VStack>
))

View File

@ -0,0 +1,2 @@
export * from './row'
export * from './col'

View File

@ -0,0 +1,25 @@
import { HStack, Stack } from "@chakra-ui/react"
export const HFStack = ({ children, ...rest }) => ((
<HStack w="full" {...rest}>
{children}
</HStack>
))
export const HBetween = ({ children, ...rest }) => ((
<HStack
w="full"
justify="space-between"
align="center"
{...rest}
>
{children}
</HStack>
))
export const AutoRowCol = () => ((
<Stack>
</Stack>
))

View File

@ -11,3 +11,4 @@ export * from './ColorModeSwitcher'
export * from './Placeholder'
export * from './Panel'
export * from './alert'
export * from './base'

View File

@ -35,4 +35,9 @@ export const en = {
notFound: 'Page Not Found',
notFoundContent: "The page you're looking for does not seem to exist",
goHome: 'Go to Home',
current: 'Current',
strategy: 'Stragety',
certificate: 'Certificate',
assets: 'Assets',
}

View File

@ -35,4 +35,9 @@ export const fr = {
notFound: 'Page Not Found',
notFoundContent: "The page you're looking for does not seem to exist",
goHome: 'Go to Home',
current: 'Current',
strategy: 'Stragety',
certificate: 'Certificate',
assets: 'Assets',
}

View File

@ -35,4 +35,9 @@ export const tw = {
notFound: 'Page Not Found',
notFoundContent: "The page you're looking for does not seem to exist",
goHome: 'Go to Home',
current: 'Current',
strategy: 'Stragety',
certificate: 'Certificate',
assets: 'Assets',
}

View File

@ -1,47 +1,39 @@
import React from "react"
import {
Stack, Image, HStack,
AspectRatio, Input,
FormControl, Box,
AspectRatio, useColorModeValue,
useDisclosure, useToast,
useColorModeValue,
} from "@chakra-ui/react"
import { StateCard, StakingCoinCard } from "../components"
import { StateCard, StakingCoinCard, StakingModalStrategy, StakingModalCertificate } from "../components"
import { useApp } from "../AppContext"
import { config } from "../config"
import { ABI } from "../data"
import {
get_staking_balance,
get_coins_platform_all,
get_coins_staking,
get_ether, get_authorization_v,
get_authorization_one, get_authorization_search, get_upBalance,
get_authorization_one, get_authorization_search,
} from "../api"
import { approve, transfer } from '../lib'
import { ModalBox } from '../components'
import { Images } from '../data'
export const Staking = () => {
const [balance, setBalance] = React.useState({})
const [lock, setLock] = React.useState([])
const [coins, setCoins] = React.useState([])
const [depositeIndex, setDepositeIndex] = React.useState(-1)
const [strategyIndex, setStrategyIndex] = React.useState(-1)
const [certificateIndex, setCertificateIndex] = React.useState(-1)
const app = useApp()
const toast = useToast()
const bg = useColorModeValue('white', 'gray.900')
const { isOpen: isWithdrawalOpen, onOpen: onWithdrawalOpen, onClose: onWithdrawalClose } = useDisclosure()
const { isOpen: isDepositeOpen, onOpen: onDepositeOpen, onClose: onDepositeClose } = useDisclosure()
const withdrawalRef = React.useRef()
const depositeRef = React.useRef()
const { isOpen: isOpenStrategy, onOpen: onOpenStrategy, onClose: onCloseStrategy } = useDisclosure()
const { isOpen: isOpenCertificate, onOpen: onOpenCertificate, onClose: onCloseCertificate } = useDisclosure()
const _getVaultBalance = () => {
if (!app.balance) {
if (!app.address) {
return false
}
@ -51,52 +43,18 @@ export const Staking = () => {
})
}
const onWithdrawalConfirmed = () => {
// click Strategy
const onStrategy = (index) => {
setStrategyIndex(index)
onOpenStrategy()
}
const onDepositeConfirmed = () => {
if (depositeIndex < 0 || depositeIndex >= coins.length) {
console.error('index out of range')
return
const onCertificate = (index) => {
setCertificateIndex(index)
onOpenCertificate()
}
const amount = depositeRef.current.value
transfer(ABI, coins[depositeIndex].address, app.appAddress, amount, app.address, (err, res) => {
if (!err) {
toast({
title: 'Succeed',
description: "You have successfully deposited " + amount + " " + coins[depositeIndex].name,
status: 'success',
duration: 9000,
isClosable: true,
})
// TODO 提交充值记录
get_upBalance(app.address).then(res => {
}).catch(err => {
console.error('get_upBalance() error:' + err.message)
})
} else {
toast({
title: 'Failed',
description: "Your operation has not been completed.",
status: 'info',
duration: 9000,
isClosable: true,
})
console.error('transfer() error:' + err.message)
}
})
}
// click withdrawal
const onBtnWithdrawal = (index) => {
onWithdrawalOpen()
}
// clicked minming
const onBtnMining = (index) => {
// clicked Certificate
const onConfirmCertificate = (index) => {
if (index < 0 || index >= coins.length) {
console.error('index out of range')
return
@ -105,8 +63,7 @@ export const Staking = () => {
let _coins = [...coins]
if (_coins[index].authorized) {
setDepositeIndex(index)
onDepositeOpen()
} else {
if (!app.address) {
toast({
@ -158,7 +115,6 @@ export const Staking = () => {
get_coins_staking().then(res => {
setCoins(res.data)
console.log(res.data)
}).catch(err => {
console.error('get_coins_staking() error:' + err.message)
})
@ -202,15 +158,15 @@ export const Staking = () => {
<HStack
flex={1}
>
<StateCard title="TVL($)" num={app.rewards[7]} />
<StateCard title="Total Users Earned($)" num={app.rewards[8]} />
<StateCard title="TVL($)" num={app.rewards[16]} />
<StateCard title="Total Users Earned($)" num={app.rewards[17]} />
</HStack>
<HStack
flex={1}
>
<StateCard title="Personal TVL($)" num={lock.count} />
<StateCard title="Total Personal Earned($)" num={lock.income} />
<StateCard title="Personal TVL($)" num={balance.USDC} />
<StateCard title="Total Personal Earned($)" num={balance.USDC_T} />
</HStack>
</Stack>
@ -224,46 +180,43 @@ export const Staking = () => {
icon={config.ENDPOINT + 'upload/' + coin.name_img}
symbol={coin.name}
apy={coin.yield}
deposited={coin.count_use}
vl={coin.count}
remaining={coin.count - coin.count_use}
loading={coin.loading}
isNew={coin.new}
authorized={coin.authorized ?? false}
onWithdrawal={onBtnWithdrawal}
onMining={onBtnMining}
vl={coin.count_use}
assets={0.00}
onStrategy={onStrategy}
onCertificate={onCertificate}
/>
))
}
{/* withdrawal box */}
<ModalBox
title="Withdrawal"
isOpen={isWithdrawalOpen}
onClose={onWithdrawalClose}
onConfirm={onWithdrawalConfirmed}
focusRef={withdrawalRef}
>
<FormControl>Amount</FormControl>
<Input ref={withdrawalRef} placeholder="withdrawal amount" />
<StakingModalStrategy
isOpen={isOpenStrategy}
onClose={onCloseStrategy}
icon={config.ENDPOINT + 'upload/' + coins[strategyIndex]?.name_img}
symbol={coins[strategyIndex]?.name}
amount={coins[strategyIndex]?.count_use}
percentage={coins[strategyIndex]?.yield}
address={coins[strategyIndex]?.address}
nodesStaked={coins[strategyIndex]?.count}
nodesNominations={coins[strategyIndex]?.count}
share={0.58}
status='normal'
/>
</ModalBox>
{/* deposite box */}
<ModalBox
title="Deposite"
isOpen={isDepositeOpen}
onClose={onDepositeClose}
onConfirm={onDepositeConfirmed}
focusRef={depositeRef}
>
<Box>
<FormControl>Amount</FormControl>
<Input ref={depositeRef} placeholder="deposite amount" />
</Box>
</ModalBox>
<StakingModalCertificate
isOpen={isOpenCertificate}
onClose={onCloseCertificate}
icon={config.ENDPOINT + 'upload/' + coins[certificateIndex]?.name_img}
symbol={coins[certificateIndex]?.name}
apy={coins[certificateIndex]?.yield}
authorized={coins[certificateIndex]?.authorized}
index={certificateIndex}
onConfirm={onConfirmCertificate}
assets={0.00}
income={0.00}
start="2022-04-01"
days="22"
/>
</>
)
}