diff --git a/src/custom/assets/cow-swap/arrow.svg b/src/custom/assets/cow-swap/arrow.svg
new file mode 100644
index 0000000000..511d2a92a9
--- /dev/null
+++ b/src/custom/assets/cow-swap/arrow.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/src/custom/assets/cow-swap/cow_v2.svg b/src/custom/assets/cow-swap/cow_v2.svg
new file mode 100644
index 0000000000..2fd9cdbc69
--- /dev/null
+++ b/src/custom/assets/cow-swap/cow_v2.svg
@@ -0,0 +1,19 @@
+
\ No newline at end of file
diff --git a/src/custom/assets/cow-swap/question.ts b/src/custom/assets/cow-swap/question.ts
new file mode 100644
index 0000000000..83e560e424
--- /dev/null
+++ b/src/custom/assets/cow-swap/question.ts
@@ -0,0 +1,10 @@
+export function questionIcon(darkMode: boolean): string {
+ return ``
+}
diff --git a/src/custom/assets/cow-swap/vCOW.png b/src/custom/assets/cow-swap/vCOW.png
new file mode 100644
index 0000000000..4feb81be05
Binary files /dev/null and b/src/custom/assets/cow-swap/vCOW.png differ
diff --git a/src/custom/components/Page/index.tsx b/src/custom/components/Page/index.tsx
index a12ac3a913..9b5a4cc599 100644
--- a/src/custom/components/Page/index.tsx
+++ b/src/custom/components/Page/index.tsx
@@ -3,6 +3,29 @@ import { PropsWithChildren } from 'react'
import styled, { css } from 'styled-components/macro'
import AppBody from 'pages/AppBody'
import { WithClassName } from 'types'
+import { useIsDarkMode } from 'state/user/hooks'
+import SVG from 'react-inlinesvg'
+import { questionIcon } from 'assets/cow-swap/question'
+
+const HelpCircleWrapper = styled.div`
+ > svg {
+ opacity: 0.5;
+ transition: opacity 0.2s ease-in-out;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+`
+
+export function HelpCircle({ size }: { size: number }) {
+ const darkMode = useIsDarkMode()
+ return (
+
+
+
+ )
+}
export const PageWrapper = styled(AppBody)`
padding: 0 24px 24px;
@@ -14,11 +37,17 @@ export const Title = styled.h1`
font-size: 32px;
margin: 24px 0 16px;
color: ${({ theme }) => theme.text1};
+
${({ theme }) => theme.mediaWidth.upToVerySmall`
font-size: 24px;
`}
`
+export const SectionTitle = styled(Title)`
+ font-size: 21px;
+ margin: 12px 0 16px;
+`
+
export const Content = styled.div`
font-size: 15px;
margin: 0 0 28px;
diff --git a/src/custom/pages/Profile/index.tsx b/src/custom/pages/Profile/index.tsx
index 2b471cfa50..dd1362595d 100644
--- a/src/custom/pages/Profile/index.tsx
+++ b/src/custom/pages/Profile/index.tsx
@@ -12,16 +12,22 @@ import {
ChildWrapper,
Loader,
ExtLink,
- ProfileWrapper,
- ProfileGridWrap,
+ CardsWrapper,
+ Card,
+ BannerCard,
+ BalanceDisplay,
+ ConvertWrapper,
} from 'pages/Profile/styled'
import { useActiveWeb3React } from 'hooks/web3'
import Copy from 'components/Copy/CopyMod'
-import { HelpCircle, RefreshCcw } from 'react-feather'
+import { RefreshCcw } from 'react-feather'
import Web3Status from 'components/Web3Status'
import useReferralLink from 'hooks/useReferralLink'
import useFetchProfile from 'hooks/useFetchProfile'
-import { formatSmartLocaleAware, numberFormatter } from 'utils/format'
+import {
+ // formatSmartLocaleAware,
+ numberFormatter,
+} from 'utils/format'
import { getExplorerAddressLink } from 'utils/explorer'
import useTimeAgo from 'hooks/useTimeAgo'
import { MouseoverTooltipContent } from 'components/Tooltip'
@@ -29,13 +35,17 @@ import NotificationBanner from 'components/NotificationBanner'
import { SupportedChainId, SupportedChainId as ChainId } from 'constants/chains'
import AffiliateStatusCheck from 'components/AffiliateStatusCheck'
import { useHasOrders } from 'api/gnosisProtocol/hooks'
-import { Title } from 'components/Page'
-import { useTokenBalance } from 'state/wallet/hooks'
-import { useVCowData } from 'state/claim/hooks'
-import { V_COW, COW } from 'constants/tokens'
-import VCOWDropdown from './VCOWDropdown'
-import { isPr, isLocal } from 'utils/environments'
-import { IS_CLAIMING_ENABLED } from 'pages/Claim/const'
+import { Title, SectionTitle, HelpCircle } from 'components/Page'
+import { ButtonPrimary } from 'custom/components/Button'
+import vCOWImage from 'assets/cow-swap/vCOW.png'
+import SVG from 'react-inlinesvg'
+import ArrowIcon from 'assets/cow-swap/arrow.svg'
+import CowImage from 'assets/cow-swap/cow_v2.svg'
+import CowProtocolImage from 'assets/cow-swap/cowprotocol.svg'
+// import { useTokenBalance } from 'state/wallet/hooks'
+// import { useVCowData } from 'state/claim/hooks'
+// import { V_COW, COW } from 'constants/tokens'
+// import { isPr, isLocal } from 'utils/environments'
export default function Profile() {
const referralLink = useReferralLink()
@@ -45,17 +55,41 @@ export default function Profile() {
const isTradesTooltipVisible = account && chainId === SupportedChainId.MAINNET && !!profileData?.totalTrades
const hasOrders = useHasOrders(account)
- const vCowBalance = useTokenBalance(account || undefined, chainId ? V_COW[chainId] : undefined)
- const cowBalance = useTokenBalance(account || undefined, chainId ? COW[chainId] : undefined)
+ // const vCowBalance = useTokenBalance(account || undefined, chainId ? V_COW[chainId] : undefined)
+ const vCowBalance = '10,240,800.32'
+ // const cowBalance = useTokenBalance(account || undefined, chainId ? COW[chainId] : undefined)
+ const cowBalance = '0'
- const { vested, total, unvested } = useVCowData()
+ // const { vested, total, unvested } = useVCowData()
+ const unvested = '9,240,800.32'
+ const vested = '1,240,800.32'
// TODO: remove once this is not needed anymore
- if (isPr || isLocal) {
- console.force.log('vested', formatSmartLocaleAware(vested, vested?.currency.decimals))
- console.force.log('total', formatSmartLocaleAware(total, total?.currency.decimals))
- console.force.log('unvested', formatSmartLocaleAware(unvested, unvested?.currency.decimals))
- console.force.log('cowBalance', formatSmartLocaleAware(cowBalance, cowBalance?.currency.decimals))
+ // if (isPr || isLocal) {
+ // console.force.log('vested', formatSmartLocaleAware(vested, vested?.currency.decimals))
+ // console.force.log('total', formatSmartLocaleAware(total, total?.currency.decimals))
+ // console.force.log('unvested', formatSmartLocaleAware(unvested, unvested?.currency.decimals))
+ // console.force.log('cowBalance', formatSmartLocaleAware(cowBalance, cowBalance?.currency.decimals))
+ // }
+
+ const tooltipText = {
+ balanceBreakdown: (
+
+ Unvested {unvested} vCOW Vested {vested} vCOW
+
+ ),
+ vested: (
+
+
+ Vested vCOW is the portion of your vCOW token balance, which is fully available to convert to
+ COW token.
+
+
+ This includes any vCOW received through an airdrop.
+
+
When converting your vested vCOW balance to COW, your entire vested balance will be converted.
+
+ ),
}
const renderNotificationMessages = (
@@ -76,18 +110,70 @@ export default function Profile() {
return (
{chainId && chainId === ChainId.MAINNET && }
-
-
-
- Profile
-
- {IS_CLAIMING_ENABLED && vCowBalance && }
-
-
+ Profile
+
+
+ {vCowBalance && (
+
+
+
+
+ Total vCOW balance
+
+ {vCowBalance} vCOW{' '}
+
+
+
+
+
+
+
+
+
+ Vested{' '}
+
+
+
+
+ {vested}
+
+
+ Convert to COW
+
+
+
+ )}
+
+ {cowBalance && (
+
+
+
+
+ Available COW balance
+ {cowBalance} COW
+
+
+
+ )}
+
+
+
+ CoW DAO Governance
+ Use your (v)COW balance to vote on important proposals or participate in forum discussions.
+
+ {' '}
+ View proposals ↗
+ CoW Forum ↗
+
+
+
+
+
+
- Affiliate Program
+ Affiliate Program
{account && (
diff --git a/src/custom/pages/Profile/styled.tsx b/src/custom/pages/Profile/styled.tsx
index b5ca6911be..984895b4a3 100644
--- a/src/custom/pages/Profile/styled.tsx
+++ b/src/custom/pages/Profile/styled.tsx
@@ -1,5 +1,7 @@
import styled, { css } from 'styled-components/macro'
import Page, { GdocsListStyle } from 'components/Page'
+import { ButtonPrimary } from 'custom/components/Button'
+import { BannerExplainer } from 'pages/Claim/styled'
import * as CSS from 'csstype'
import { transparentize } from 'polished'
import { ExternalLink } from 'theme'
@@ -8,6 +10,7 @@ export const Container = styled.div`
max-width: 910px;
width: 100%;
`
+
export const Wrapper = styled(Page)`
${GdocsListStyle}
@@ -19,14 +22,17 @@ export const Wrapper = styled(Page)`
justify-content: flex-end;
flex-direction: column;
margin: 0;
- background: ${({ theme }) => transparentize(0.5, theme.bg1)};
+ background: ${({ theme }) => transparentize(0.3, theme.bg1)};
box-shadow: none;
border: 1px solid ${({ theme }) => theme.cardBorder};
+
${({ theme }) => theme.mediaWidth.upToSmall`
padding: 16px;
`}
+
span[role='img'] {
font-size: 55px;
+
${({ theme }) => theme.mediaWidth.upToSmall`
font-size: 30px;
`}
@@ -96,6 +102,7 @@ export const ItemTitle = styled.h3`
font-size: 18px;
line-height: 1.21;
color: ${({ theme }) => theme.text1};
+
${({ theme }) => theme.mediaWidth.upToSmall`
margin: 0 0 10px 0;
font-size: 16px;
@@ -126,11 +133,12 @@ export const FlexWrap = styled.div`
`
export const StyledContainer = styled.div`
- display: flex;
- flex:1;
- align-items:center;
- justify-content: space-between;
+ display: flex;
+ flex:1;
+ align-items:center;
+ justify-content: space-between;
}
+
${({ theme }) => theme.mediaWidth.upToSmall`
flex-wrap: wrap;
flex-direction: column;
@@ -196,15 +204,6 @@ export const Loader = styled.div<{ isLoading: boolean }>`
`}
`
-export const ProfileWrapper = styled(Wrapper)`
- margin: 16px 0 16px 0;
- padding: 16px 24px;
- z-index: 2;
- ${({ theme }) => theme.mediaWidth.upToVerySmall`
- padding: 0 16px 16px;
- `};
-`
-
export const ProfileGridWrap = styled(GridWrap)`
grid-template-columns: 1fr auto;
justify-content: space-between;
@@ -225,3 +224,232 @@ export const ProfileGridWrap = styled(GridWrap)`
grid-row-gap: 0px;
`};
`
+
+export const CardsWrapper = styled.div`
+ display: flex;
+ flex-flow: row wrap;
+ gap: 16px;
+ margin: 16px 0 16px 0;
+ padding: 0;
+ z-index: 2;
+
+ > div:nth-of-type(3n) {
+ flex: 1 1 100%;
+ }
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ display: flex;
+ flex-flow: column wrap;
+ `};
+`
+
+export const Card = styled.div`
+ display: flex;
+ flex-flow: row wrap;
+ flex: 1;
+ min-height: 192px;
+ margin: 0;
+ background: ${({ theme }) => transparentize(0.3, theme.bg1)};
+ box-shadow: none;
+ padding: 24px;
+ gap: 24px 0;
+ border-radius: 16px;
+ border: 1px solid ${({ theme }) => theme.cardBorder};
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ min-height: 130px;
+ padding: 24px 16px;
+ `};
+
+ ${ButtonPrimary} {
+ height: 52px;
+
+ > svg {
+ height: 100%;
+ width: auto;
+ object-fit: contain;
+ margin: 0 0 0 6px;
+ transform: translateX(0);
+ transition: transform 0.2s ease-in-out;
+ }
+
+ &:hover > svg {
+ transform: translateX(2px);
+ }
+ }
+`
+
+export const BannerCard = styled(BannerExplainer)`
+ min-height: 192px;
+ border-radius: 16px;
+ border: 0;
+ padding: 0 100px 0 24px;
+ flex: 1;
+ overflow: hidden;
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ text-align: center;
+ padding: 24px 16px;
+ `}
+
+ &:hover {
+ border: 0;
+ }
+
+ > span {
+ align-items: flex-start;
+ justify-content: space-between;
+ height: 100%;
+ padding: 24px 0;
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ padding: 0;
+ `}
+
+ > b {
+ font-size: 24px;
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ text-align: center;
+ margin: 0 auto;
+ `};
+ }
+
+ > small {
+ font-size: 14px;
+ line-height: 1.5;
+ text-align: left;
+ padding: 0;
+ margin: 8px 0 auto;
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ text-align: center;
+ margin: 16px auto;
+ `}
+ }
+
+ > span {
+ display: flex;
+ margin: 8px 0 0;
+ gap: 0 16px;
+ width: 100%;
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ flex-flow: column wrap;
+ gap: 16px 0;
+ justify-content: center;
+ margin: 24px 0 12px;
+ `}
+ }
+
+ > span > a,
+ > span > a:link {
+ font-size: 15px;
+ color: ${({ theme }) => theme.white};
+
+ &:hover {
+ color: ${({ theme }) => theme.primary1};
+ }
+ }
+ }
+
+ > svg {
+ left: initial;
+ right: -190px;
+ transform: scale(-1, 1); // flip mirror
+ opacity: 0.25;
+ mix-blend-mode: initial;
+ }
+`
+
+export const BalanceDisplay = styled.div<{ titleSize?: number; altColor?: boolean; hAlign?: string }>`
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center;
+ align-content: center;
+ justify-content: ${({ hAlign }) => (hAlign === 'left' ? 'flex-start' : 'center')};
+ gap: 3px 12px;
+ width: 100%;
+ font-size: 14px;
+ color: ${({ theme }) => transparentize(0.3, theme.text1)};
+
+ ${({ theme }) => theme.mediaWidth.upToMedium`
+ gap: 12px;
+ flex-flow: column wrap;
+ `};
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ justify-content: center;
+ `};
+
+ > img {
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ height: 56px;
+ width: 56px;
+ object-fit: contain;
+ `};
+ }
+
+ > span {
+ display: flex;
+ flex-flow: column wrap;
+ gap: 3px 0;
+ }
+
+ i {
+ display: flex;
+ align-items: center;
+ gap: 0 3px;
+ width: 100%;
+ font-style: normal;
+
+ ${({ theme }) => theme.mediaWidth.upToMedium`
+ justify-content: center;
+ `};
+ }
+
+ b {
+ width: 100%;
+ display: flex;
+ align-items: center;
+ gap: 0 6px;
+ color: ${({ theme, altColor }) => (altColor ? theme.primary1 : theme.text1)};
+ font-size: ${({ titleSize }) => (titleSize ? `${titleSize}px` : '21px')};
+
+ ${({ theme }) => theme.mediaWidth.upToMedium`
+ justify-content: center;
+ `};
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ font-size: 18px;
+ `};
+
+ > div {
+ cursor: pointer;
+ }
+
+ // Todo: Prevent requiring overriding tooltip padding with important!
+ > div > div {
+ padding: 0 !important;
+ }
+ }
+`
+
+export const ConvertWrapper = styled.div`
+ display: grid;
+ grid-template-columns: 1fr 200px;
+ align-items: center;
+ ${({ theme }) => theme.neumorphism.boxShadow};
+ background: ${({ theme }) => theme.bg7};
+ border-radius: 16px;
+ padding: 16px;
+ width: 100%;
+
+ ${({ theme }) => theme.mediaWidth.upToMedium`
+ display: flex;
+ flex-flow: column wrap;
+ gap: 16px 0;
+
+ > div { gap: 6px 12px; }
+ `};
+`