Skip to content

Commit

Permalink
feat: provide
Browse files Browse the repository at this point in the history
  • Loading branch information
honeymaro committed Jan 6, 2023
1 parent 785b3de commit c714d72
Show file tree
Hide file tree
Showing 6 changed files with 345 additions and 19 deletions.
4 changes: 4 additions & 0 deletions src/assets/icons/icon-provide.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
93 changes: 83 additions & 10 deletions src/pages/Pool/PoolList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import iconDefaultToken from "assets/icons/icon-default-token.svg";
import { Col, Row } from "react-grid-system";
import { amountToValue, formatDecimals, formatNumber } from "utils";
import { LP_DECIMALS } from "constants/dezswap";
import Typography from "components/Typography";
import Button from "components/Button";
import { Link } from "react-router-dom";
import Expand from "./Expand";
import { PoolWithPair } from ".";

Expand Down Expand Up @@ -100,6 +103,20 @@ const AssetIcon = styled.div<{ src?: string }>`

const PoolItem = styled(Box)``;

const Label = styled(Typography)`
margin-bottom: 15px;
`;

const LinkButton = styled(Button.withComponent(Link))`
text-decoration: none;
`;

Label.defaultProps = {
size: 14,
weight: 900,
color: "primary",
};

function PoolList({ pools }: PoolListProps) {
const { getAsset } = useAssets();
return (
Expand Down Expand Up @@ -151,16 +168,72 @@ function PoolList({ pools }: PoolListProps) {
}
extra={[<div>1</div>, <div>2</div>]}
>
<div
key={pool.pair.contract_addr}
css={css`
width: 120px;
position: relative;
display: inline-block;
`}
>
<SimplePieChart data={[50, 50]} />
</div>
<Row justify="between" align="start" gutterWidth={0}>
<Col width={360}>
<Label
css={css`
margin-bottom: 10px;
`}
>
Liquidity Ratio
</Label>
<Row justify="between" align="center" gutterWidth={10}>
<Col width={80}>
<div
key={pool.pair.contract_addr}
css={css`
width: 60px;
position: relative;
display: inline-block;
`}
>
<SimplePieChart data={[50, 50]} />
</div>
</Col>
<Col>
<Typography>
0000 {asset1?.symbol} {formatNumber(50)}%
</Typography>
<Typography>
0000 {asset2?.symbol} {formatNumber(50)}%
</Typography>
</Col>
</Row>
</Col>
<Col width={210}>
<Label>Your Liquidity</Label>
</Col>
<Col width={210}>
<Label>Asset Pooled</Label>
</Col>
<Col width={80}>
<Label>Your Share</Label>
</Col>
<Col
width={150}
onClick={(event) => {
event.stopPropagation();
}}
>
<LinkButton
to={`/pool/add-liquidity/${pool.pair.contract_addr}`}
variant="primary"
block
css={css`
margin-bottom: 10px;
`}
>
Add liquidity
</LinkButton>
<LinkButton
to={`/pool/withdraw/${pool.pair.contract_addr}`}
variant="secondary"
block
>
Remove liquidity
</LinkButton>
</Col>
</Row>
</Expand>
);
})}
Expand Down
127 changes: 127 additions & 0 deletions src/pages/Pool/Provide/InputGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { forwardRef } from "react";
import { css } from "@emotion/react";
import styled from "@emotion/styled";
import Box from "components/Box";
import Button from "components/Button";
import Copy from "components/Copy";
import { NumberInput } from "components/Input";
import Typography from "components/Typography";
import { Col, Row, useScreenClass } from "react-grid-system";
import theme from "styles/theme";
import { Asset } from "types/common";
import { formatNumber, formatDecimals, amountToValue } from "utils";
import iconDefaultToken from "assets/icons/icon-default-token.svg";

interface InputGroupProps extends React.HTMLAttributes<HTMLInputElement> {
asset?: Partial<Asset>;
onBalanceClick?(
value: string,
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
): void;
}

const AssetButton = styled(Button)<{ iconSrc?: string }>`
pointer-events: none;
border-radius: 30px;
height: 38px;
padding: 0 9px;
justify-content: flex-start;
&::before {
content: "";
width: 24px;
height: 24px;
background-image: ${({ iconSrc }) => `url(${iconSrc || iconDefaultToken})`};
background-size: cover;
background-position: 50% 50%;
border-radius: 50%;
margin-right: 4px;
}
`;
const InputGroup = forwardRef<HTMLInputElement, InputGroupProps>(
({ asset, onBalanceClick, style, ...inputProps }, ref) => {
const screenClass = useScreenClass();

return (
<Box style={style}>
<Row justify="between" align="center" style={{ gap: 3 }}>
<Col xs={12} sm="content">
<Row gutterWidth={4} justify="start" align="center" wrap="nowrap">
<Col xs="content" style={screenClass === "xs" ? { flex: 1 } : {}}>
<AssetButton
block={screenClass === "xs"}
iconSrc={asset?.iconSrc}
>
{asset?.symbol}
</AssetButton>
</Col>
<Col xs="content">
<Copy size={38} value={asset?.address} />
</Col>
</Row>
</Col>
<Col xs={12} sm="content">
<Typography
css={css`
opacity: 0.5;
line-height: 38px;
text-align: right;
cursor: pointer;
`}
onClick={(event) => {
if (onBalanceClick) {
onBalanceClick(
amountToValue(asset?.balance, asset?.decimals) || "",
event,
);
}
}}
>
Balance:&nbsp;
<span
css={css`
color: ${theme.colors.primary};
text-decoration: underline;
text-underline-offset: 3px;
`}
>
{formatNumber(
formatDecimals(
amountToValue(asset?.balance, asset?.decimals) || 0,
3,
),
)}
</span>
</Typography>
</Col>
</Row>
<Row>
<Col xs={24}>
<NumberInput
ref={ref}
variant="base"
size="large"
placeholder="0"
align="right"
{...inputProps}
/>
</Col>
</Row>
<Row>
<Col xs={24}>
<Typography
size={14}
css={css`
opacity: 0.7;
text-align: right;
`}
>
-
</Typography>
</Col>
</Row>
</Box>
);
},
);

export default InputGroup;
134 changes: 128 additions & 6 deletions src/pages/Pool/Provide/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,141 @@
import { FormEventHandler, useCallback } from "react";
import Typography from "components/Typography";
import { FormEventHandler, useCallback, useEffect, useMemo } from "react";
import Modal from "components/Modal";
import { useNavigate, useParams } from "react-router-dom";
import usePairs from "hooks/usePair";
import useAssets from "hooks/useAssets";
import { useForm } from "react-hook-form";
import { useScreenClass } from "react-grid-system";
import { css } from "@emotion/react";
import iconProvide from "assets/icons/icon-provide.svg";
import Expand from "components/Expanded";
import { MOBILE_SCREEN_CLASS } from "constants/layout";
import InputGroup from "./InputGroup";

enum FormKey {
asset1Value = "asset1Value",
asset2Value = "asset2Value",
}

function ProvidePage() {
const { pairAddress } = useParams<{ pairAddress: string }>();
const navigate = useNavigate();
const screenClass = useScreenClass();
const { getPair, pairs } = usePairs();
const { getAsset } = useAssets();
const pair = useMemo(
() => (pairAddress ? getPair(pairAddress) : undefined),
[getPair, pairAddress],
);
const [asset1, asset2] = useMemo(
() => (pair?.asset_addresses || []).map((address) => getAsset(address)),
[getAsset, pair?.asset_addresses],
);

const form = useForm<Record<FormKey, string>>({
criteriaMode: "all",
mode: "all",
});
const formData = form.watch();
const { register, formState } = form;

const handleSubmit = useCallback<FormEventHandler<HTMLFormElement>>(
(event) => {
/* TODO: implement */
},
[],
);

const handleModalClose = useCallback(() => {
navigate("/pool", { replace: true });
}, [navigate]);

useEffect(() => {
const timerId = setTimeout(() => {
if (pairs?.length && !pair) {
handleModalClose();
}
}, 500); // wait for 500ms to make sure the pair is loaded
return () => {
clearTimeout(timerId);
};
}, [handleModalClose, pair, pairs?.length]);

return (
<>
<form onSubmit={handleSubmit} />
<Typography>Add Liquidity</Typography>
</>
<Modal
isOpen
title="Add liquidity"
hasCloseButton
drawer={screenClass === MOBILE_SCREEN_CLASS}
onRequestClose={() => handleModalClose()}
>
<form onSubmit={handleSubmit}>
<InputGroup
{...register(FormKey.asset1Value)}
asset={asset1}
onBalanceClick={(value) => {
form.setValue(FormKey.asset1Value, value, {
shouldValidate: true,
shouldDirty: true,
shouldTouch: true,
});
}}
/>
<div
css={css`
position: relative;
width: 100%;
height: 28px;
margin-top: -9px;
margin-bottom: -9px;
background-image: url(${iconProvide});
background-repeat: no-repeat;
background-position: 50%;
background-size: contain;
z-index: 1;
`}
/>
<InputGroup
{...register(FormKey.asset2Value)}
asset={asset2}
onBalanceClick={(value) => {
form.setValue(FormKey.asset2Value, value, {
shouldValidate: true,
shouldDirty: true,
shouldTouch: true,
});
}}
style={{ marginBottom: 10 }}
/>
<Expand
label="Summary"
preview={
<div>
Preview
<br />
Preview
<br />
Preview
<br />
Preview
<br />
</div>
}
>
Children
<br />
Children
<br />
Children
<br />
Children
<br />
Children
<br />
Children
<br />
</Expand>
</form>
</Modal>
);
}

Expand Down
Loading

0 comments on commit c714d72

Please sign in to comment.