Skip to content

Commit

Permalink
feat(*): swap deposit (#10)
Browse files Browse the repository at this point in the history
* swap deposit feature
---------

Co-authored-by: Adam Clarke <[email protected]>
Co-authored-by: Oluwakorede Fashokun <[email protected]>
  • Loading branch information
3 people authored Sep 20, 2023
1 parent 2882aa8 commit 49e7f5f
Show file tree
Hide file tree
Showing 65 changed files with 2,220 additions and 570 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules/
.vscode/
.vscode/
.DS_Store
12 changes: 12 additions & 0 deletions packages/app/src/__tests__/pages/smartMargin.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,18 @@ describe('Futures market page - smart margin', () => {
keeperEthBal: wei('0.1'),
walletEthBal: wei('1'),
allowance: wei('1000'),
balances: {
SUSD: wei('100000'),
USDC: wei('100000'),
DAI: wei('100000'),
// LUSD: wei('100000'),
},
allowances: {
SUSD: wei('100000'),
USDC: wei('100000'),
DAI: wei('100000'),
// LUSD: wei('100000'),
},
})

const store = setupStore(preloadedStateWithSmartMarginAccount(mockSmartMarginAccount('100000')))
Expand Down
Binary file added packages/app/src/assets/png/tokens/DAI.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app/src/assets/png/tokens/LUSD.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app/src/assets/png/tokens/USDC.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app/src/assets/png/tokens/USDT.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app/src/assets/png/tokens/sUSD-Black.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app/src/assets/png/tokens/sUSD-White.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
116 changes: 116 additions & 0 deletions packages/app/src/components/BigToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import Image from 'next/image'
import { useCallback, useReducer } from 'react'
import styled, { css } from 'styled-components'

import { StyledCaretDownIcon } from './Select'

type BigToggleProps<T extends string> = {
value: T
options: T[]
onOptionClick(value: T): void
iconMap?: Record<T, string>
}

const BigToggle = <T extends string>({
options,
value,
onOptionClick,
iconMap,
}: BigToggleProps<T>) => {
const [expanded, toggleExpanded] = useReducer((s) => !s, false)

const handleOptionClick = useCallback(
(option: T) => () => {
onOptionClick(option)
toggleExpanded()
},
[onOptionClick]
)

return (
<BigToggleContainer>
<BigToggleButton onClick={toggleExpanded}>
{iconMap?.[value] && <Image alt={value} src={iconMap[value]} width={15} height={15} />}
{value}
<StyledCaretDownIcon $flip={expanded} style={{ marginLeft: 7 }} />
</BigToggleButton>
{expanded && (
<BigToggleListContainer>
{options
.filter((o) => o !== value)
.map((option) => (
<BigToggleListOption key={option} onClick={handleOptionClick(option)}>
{iconMap?.[option] && (
<Image alt={option} src={iconMap[option]} width={15} height={15} />
)}
{option}
</BigToggleListOption>
))}
</BigToggleListContainer>
)}
</BigToggleContainer>
)
}

const BigToggleContainer = styled.div`
position: relative;
`

const BigToggleButton = styled.button`
display: flex;
align-items: center;
border-radius: 40px;
padding: 7px;
font-size: 16px;
cursor: pointer;
line-height: 1;
img {
margin-right: 7px;
}
${(props) => css`
border: ${props.theme.colors.selectedTheme.newTheme.button.default.border};
background-color: ${props.theme.colors.selectedTheme.newTheme.button.default.background};
color: ${props.theme.colors.selectedTheme.newTheme.button.default.color};
`}
`

const BigToggleListContainer = styled.div`
position: absolute;
top: 40px;
border: ${(props) => props.theme.colors.selectedTheme.newTheme.button.default.border};
border-radius: 8px;
overflow: hidden;
width: 100%;
`

const BigToggleListOption = styled.button`
border: none;
width: 100%;
padding: 7px;
cursor: pointer;
line-height: 1;
display: flex;
img {
margin-right: 7px;
}
${(props) => css`
background-color: ${props.theme.colors.selectedTheme.newTheme.button.default.background};
color: ${props.theme.colors.selectedTheme.newTheme.button.default.color};
font-size: 16px;
&:not(:last-of-type) {
border-bottom: ${props.theme.colors.selectedTheme.newTheme.button.default.border};
}
&:hover {
background-color: ${props.theme.colors.selectedTheme.newTheme.button.default.hover
.background};
}
`}
`

export default BigToggle
13 changes: 10 additions & 3 deletions packages/app/src/components/InfoBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { Body } from 'components/Text'
import { BodyProps } from 'components/Text/Body'
import { NO_VALUE } from 'constants/placeholder'

import { FlexDivRow } from './layout/flex'

type InfoBoxRowProps = {
children?: React.ReactNode
title: string
Expand Down Expand Up @@ -52,9 +54,10 @@ export const InfoBoxRow: FC<InfoBoxRowProps> = memo(
$isSubItem={isSubItem}
onClick={expandable ? () => onToggleExpand?.(title) : undefined}
>
<InfoBoxKey>
{title}: {keyNode} {expandable ? expanded ? <HideIcon /> : <ExpandIcon /> : null}
</InfoBoxKey>
<InfoBoxKeyContainer>
<InfoBoxKey>{title}: </InfoBoxKey>
{keyNode} {expandable ? expanded ? <HideIcon /> : <ExpandIcon /> : null}
</InfoBoxKeyContainer>
{nodeValue ? (
nodeValue
) : (
Expand Down Expand Up @@ -98,6 +101,10 @@ export const InfoBoxContainer = styled.div`
padding: 12px 14px;
`

const InfoBoxKeyContainer = styled(FlexDivRow)`
align-items: center;
`

const InfoBoxKey = styled(Body)`
color: ${(props) => props.theme.colors.selectedTheme.text.label};
text-transform: capitalize;
Expand Down
7 changes: 2 additions & 5 deletions packages/app/src/components/Input/NumericInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FC, memo, useCallback } from 'react'
import styled, { css } from 'styled-components'

import Spacer from 'components/Spacer'
import { isInvalidNumber } from 'utils/input'

type NumericInputProps = Omit<
React.InputHTMLAttributes<HTMLInputElement>,
Expand All @@ -22,10 +23,6 @@ type NumericInputProps = Omit<
noShadow?: boolean
}

const INVALID_CHARS = ['-', '+', 'e']

const isInvalid = (key: string) => INVALID_CHARS.includes(key)

const NumericInput: FC<NumericInputProps> = memo(
({
value,
Expand Down Expand Up @@ -86,7 +83,7 @@ const NumericInput: FC<NumericInputProps> = memo(
inputMode="decimal"
onChange={handleChange}
onKeyDown={(e) => {
if (isInvalid(e.key)) {
if (isInvalidNumber(e.key)) {
e.preventDefault()
}
}}
Expand Down
24 changes: 12 additions & 12 deletions packages/app/src/components/Nav/NavLink.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Link from 'next/link'
import React, { ReactNode } from 'react'
import styled from 'styled-components'
import styled, { css } from 'styled-components'

import LinkIconLight from 'assets/svg/app/link-light.svg'
import { FlexDivRowCentered } from 'components/layout/flex'
Expand Down Expand Up @@ -31,17 +31,15 @@ const NavButton: React.FC<NavButtonProps> = ({ title, href, external, disabled,
</FlexDivRowCentered>
</StyledLink>
) : (
<Link href={href} passHref>
<StyledLink className={disabled ? 'disabled' : undefined} {...props}>
{title}
</StyledLink>
</Link>
<StyledLink href={href} {...props}>
{title}
</StyledLink>
)}
</div>
)
}

const StyledLink = styled.a<{ isActive: boolean; disabled?: boolean }>`
const StyledLink = styled(Link)<{ isActive: boolean; disabled?: boolean }>`
${linkCSS};
display: inline-block;
padding: 10px 14px;
Expand All @@ -60,11 +58,13 @@ const StyledLink = styled.a<{ isActive: boolean; disabled?: boolean }>`
background: ${(props) => props.theme.colors.selectedTheme.button.fill};
}
&.disabled {
color: ${(props) => props.theme.colors.selectedTheme.button.disabled.text};
background: transparent;
pointer-events: none;
}
${(props) =>
props.disabled &&
css`
color: ${props.theme.colors.selectedTheme.button.disabled.text};
background: transparent;
pointer-events: none;
`}
`

export default NavButton
123 changes: 123 additions & 0 deletions packages/app/src/components/SmallToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import Image from 'next/image'
import { useCallback, useReducer } from 'react'
import styled from 'styled-components'

import { StyledCaretDownIcon } from 'components/Select'
import { HOURS_TOGGLE_HEIGHT, zIndex } from 'constants/ui'

type SmallToggleProps<T extends string> = {
value: T
options: T[]
getLabelByValue?: (value: T) => string
iconMap?: Record<T, string>
onOptionClick: (value: T) => void
}

const SmallToggle = <T extends string>({
value,
options,
getLabelByValue,
iconMap,
onOptionClick,
}: SmallToggleProps<T>) => {
const [open, toggleOpen] = useReducer((o) => !o, false)

const handleOptionClick = useCallback(
(option: T) => () => {
onOptionClick(option)
toggleOpen()
},
[onOptionClick, toggleOpen]
)

return (
<ToggleContainer open={open}>
<ToggleTable $open={open}>
<ToggleTableHeader onClick={toggleOpen}>
{iconMap?.[value] && <Image alt={value} src={iconMap[value]} width={11} height={11} />}
{getLabelByValue?.(value) ?? value}
<StyledCaretDownIcon width={12} $flip={open} style={{ marginLeft: 2 }} />
</ToggleTableHeader>
{open && (
<ToggleTableRows>
{options
.filter((o) => o !== value)
.map((option) => (
<ToggleTableRow key={option} onClick={handleOptionClick(option)}>
{iconMap?.[option] && (
<Image alt={value} src={iconMap[option]} width={11} height={11} />
)}
{option}
</ToggleTableRow>
))}
</ToggleTableRows>
)}
</ToggleTable>
</ToggleContainer>
)
}

const ToggleTableRow = styled.div`
display: flex;
align-items: center;
margin: auto;
padding: 1.5px 6px;
height: ${HOURS_TOGGLE_HEIGHT};
background: ${(props) => props.theme.colors.selectedTheme.newTheme.pill.gray.background};
:last-child {
border-radius: 0px 0px 9px 9px;
}
img {
margin-right: 3px;
}
:hover {
color: ${(props) => props.theme.colors.selectedTheme.newTheme.text.primary};
background: ${(props) =>
props.theme.colors.selectedTheme.newTheme.pill['gray'].hover.background};
:last-child {
border-radius: 0px 0px 9px 9px;
}
}
`

const ToggleTableRows = styled.div`
width: 100%;
position: absolute;
top: 20px;
color: ${(props) => props.theme.colors.selectedTheme.newTheme.text.secondary};
z-index: ${zIndex.HEADER};
`

const ToggleTableHeader = styled.div`
display: flex;
justify-content: space-evenly;
align-items: center;
padding: 3px 5px;
font-size: 12px;
img {
margin-right: 3px;
}
`

const ToggleTable = styled.div<{ $open?: boolean }>`
display: flex;
flex-direction: column;
background: ${(props) => props.theme.colors.selectedTheme.newTheme.pill['gray'].background};
color: ${(props) => props.theme.colors.selectedTheme.newTheme.text.primary};
border-radius: 9px;
font-size: 12px;
font-family: ${(props) => props.theme.fonts.bold};
${(props) => props.$open && `border-radius: 9px 9px 0px 0px;`}
`

const ToggleContainer = styled.div<{ open: boolean }>`
margin-left: 8px;
cursor: pointer;
position: relative;
`

export default SmallToggle
Loading

0 comments on commit 49e7f5f

Please sign in to comment.