diff --git a/content/price.json b/content/price.json index c5362e16d..7c00d61a9 100644 --- a/content/price.json +++ b/content/price.json @@ -34,7 +34,8 @@ "titleIn": "You will receive", "titleOut": "You will earn" }, - "action": "Approve & Supply" + "action": "Approve & Supply", + "warning": "Use at your own risk. Please familiarize yourself [with the risks](https://blog.oceanprotocol.com/on-staking-on-data-in-ocean-market-3d8e09eb0a13) and the [Terms of Use](/terms)." }, "remove": { "title": "Remove Liquidity", diff --git a/src/components/atoms/Alert.module.css b/src/components/atoms/Alert.module.css index dd9ebd27b..e5bf6a611 100644 --- a/src/components/atoms/Alert.module.css +++ b/src/components/atoms/Alert.module.css @@ -8,6 +8,7 @@ border-bottom-left-radius: 0; padding-top: calc(var(--spacer) / 2); padding-bottom: calc(var(--spacer) / 2); + position: relative; } .alert + .alert { @@ -37,6 +38,24 @@ margin-top: calc(var(--spacer) / 2); } +.close { + position: absolute; + cursor: pointer; + background: none; + border: 0; + box-shadow: none; + outline: 0; + top: 0; + right: 0; + font-size: var(--font-size-large); + color: var(--brand-grey); +} + +.close:hover, +.close:focus { + opacity: 0.7; +} + /* States */ .error { border-color: var(--rbrand-alert-ed); diff --git a/src/components/atoms/Alert.tsx b/src/components/atoms/Alert.tsx index d313dfdb7..5a91bb2b2 100644 --- a/src/components/atoms/Alert.tsx +++ b/src/components/atoms/Alert.tsx @@ -1,36 +1,55 @@ import React, { ReactElement, FormEvent } from 'react' +import classNames from 'classnames/bind' import styles from './Alert.module.css' import Button from './Button' import Markdown from './Markdown' +const cx = classNames.bind(styles) + export default function Alert({ title, text, state, - action + action, + onDismiss, + className }: { title?: string text: string state: 'error' | 'warning' | 'info' | 'success' action?: { name: string + style?: 'text' | 'primary' | 'ghost' handleAction: (e: FormEvent) => void } + onDismiss?: () => void + className?: string }): ReactElement { + const styleClasses = cx({ + alert: true, + [state]: state, + [className]: className + }) + return ( -
+
{title &&

{title}

} {action && ( )} + {onDismiss && ( + + )}
) } diff --git a/src/components/organisms/AssetActions/Pool/Add/FormAdd.module.css b/src/components/organisms/AssetActions/Pool/Add/FormAdd.module.css index 655e4bda7..8d20018f3 100644 --- a/src/components/organisms/AssetActions/Pool/Add/FormAdd.module.css +++ b/src/components/organisms/AssetActions/Pool/Add/FormAdd.module.css @@ -1,23 +1,3 @@ -.addInput { - margin: 0 auto calc(var(--spacer) / 1.5) auto; - background: var(--brand-grey-dimmed); - padding: var(--spacer) calc(var(--spacer) * 2.5) calc(var(--spacer) * 1.2) - calc(var(--spacer) * 2.5); - border-bottom: 1px solid var(--brand-grey-lighter); - margin-top: -2rem; - margin-left: -2rem; - margin-right: -2rem; - position: relative; -} - -.addInput input { - text-align: center; -} - -.addInput div[class*='field'] { - margin-bottom: 0; -} - .buttonMax { position: absolute; font-size: var(--font-size-mini); @@ -41,22 +21,3 @@ transform: scale(0.8); transform-origin: right center; } - -.output { - display: grid; - gap: var(--spacer); - grid-template-columns: 1fr 1fr; -} - -.output p { - font-weight: var(--font-weight-bold); - margin-bottom: calc(var(--spacer) / 8); -} - -.output [class*='token'] { - white-space: normal; -} - -.output [class*='token'] > figure { - display: none; -} diff --git a/src/components/organisms/AssetActions/Pool/Add/FormAdd.tsx b/src/components/organisms/AssetActions/Pool/Add/FormAdd.tsx index 9feb69cc4..309ddb1dd 100644 --- a/src/components/organisms/AssetActions/Pool/Add/FormAdd.tsx +++ b/src/components/organisms/AssetActions/Pool/Add/FormAdd.tsx @@ -1,5 +1,5 @@ import PriceUnit from '../../../../atoms/Price/PriceUnit' -import React, { ChangeEvent, ReactElement, useEffect, useState } from 'react' +import React, { ChangeEvent, ReactElement, useEffect } from 'react' import styles from './FormAdd.module.css' import Input from '../../../../atoms/Input' import { @@ -9,14 +9,12 @@ import { useFormikContext } from 'formik' import Button from '../../../../atoms/Button' -import Token from '../Token' import CoinSelect from '../CoinSelect' import { FormAddLiquidity } from '.' import { useOcean } from '@oceanprotocol/react' import { Balance } from '..' export default function FormAdd({ - content, coin, dtBalance, dtSymbol, @@ -24,10 +22,10 @@ export default function FormAdd({ setCoin, totalPoolTokens, totalBalance, - swapFee, - poolAddress + poolAddress, + setNewPoolTokens, + setNewPoolShare }: { - content: any coin: string dtBalance: string dtSymbol: string @@ -35,8 +33,9 @@ export default function FormAdd({ setCoin: (value: string) => void totalPoolTokens: string totalBalance: Balance - swapFee: string poolAddress: string + setNewPoolTokens: (value: string) => void + setNewPoolShare: (value: string) => void }): ReactElement { const { ocean, balance } = useOcean() @@ -49,9 +48,6 @@ export default function FormAdd({ values }: FormikContextType = useFormikContext() - const [newPoolTokens, setNewPoolTokens] = useState('0') - const [newPoolShare, setNewPoolShare] = useState('0') - useEffect(() => { async function calculatePoolShares() { if (!values.amount) { @@ -80,71 +76,58 @@ export default function FormAdd({ return ( <> -
-
-
- Available: - {coin === 'OCEAN' ? ( - - ) : ( - - )} -
-
- Maximum: - -
-
- - {({ - field, - form - }: { - field: FieldInputProps - form: any - }) => ( - } - placeholder="0" - field={field} - form={form} - onChange={(e: ChangeEvent) => { - // Workaround so validation kicks in on first touch - !touched?.amount && setTouched({ amount: true }) - handleChange(e) - }} - disabled={!ocean} - /> +
+
+ Available: + {coin === 'OCEAN' ? ( + + ) : ( + )} - +
+
+ Maximum: + +
+
- {(Number(balance.ocean) || dtBalance) > (values.amount || 0) && ( - + + {({ + field, + form + }: { + field: FieldInputProps + form: any + }) => ( + } + placeholder="0" + field={field} + form={form} + onChange={(e: ChangeEvent) => { + // Workaround so validation kicks in on first touch + !touched?.amount && setTouched({ amount: true }) + handleChange(e) + }} + disabled={!ocean} + /> )} -
+ -
-
-

{content.output.titleIn}

- - -
-
-

{content.output.titleOut}

- -
-
+ {(Number(balance.ocean) || dtBalance) > (values.amount || 0) && ( + + )} ) } diff --git a/src/components/organisms/AssetActions/Pool/Add/index.module.css b/src/components/organisms/AssetActions/Pool/Add/index.module.css index e69de29bb..8d65015b2 100644 --- a/src/components/organisms/AssetActions/Pool/Add/index.module.css +++ b/src/components/organisms/AssetActions/Pool/Add/index.module.css @@ -0,0 +1,43 @@ +.addInput { + margin: 0 auto calc(var(--spacer) / 1.5) auto; + background: var(--brand-grey-dimmed); + padding: var(--spacer) calc(var(--spacer) * 2.5) calc(var(--spacer) * 1.2) + calc(var(--spacer) * 2.5); + border-bottom: 1px solid var(--brand-grey-lighter); + margin-top: -2rem; + margin-left: -2rem; + margin-right: -2rem; + position: relative; +} + +.addInput input { + text-align: center; +} + +.addInput div[class*='field'] { + margin-bottom: 0; +} + +.output { + display: grid; + gap: var(--spacer); + grid-template-columns: 1fr 1fr; +} + +.output p { + font-weight: var(--font-weight-bold); + margin-bottom: calc(var(--spacer) / 8); +} + +.output [class*='token'] { + white-space: normal; +} + +.output [class*='token'] > figure { + display: none; +} + +.warning { + margin-left: -3rem; + margin-right: -3rem; +} diff --git a/src/components/organisms/AssetActions/Pool/Add/index.tsx b/src/components/organisms/AssetActions/Pool/Add/index.tsx index bd252e3fd..21a0688ef 100644 --- a/src/components/organisms/AssetActions/Pool/Add/index.tsx +++ b/src/components/organisms/AssetActions/Pool/Add/index.tsx @@ -9,6 +9,8 @@ import * as Yup from 'yup' import { Formik } from 'formik' import FormAdd from './FormAdd' import styles from './index.module.css' +import Token from '../Token' +import Alert from '../../../../atoms/Alert' const contentQuery = graphql` query PoolAddQuery { @@ -24,6 +26,7 @@ const contentQuery = graphql` titleOut } action + warning } } } @@ -68,6 +71,9 @@ export default function Add({ const [coin, setCoin] = useState('OCEAN') const [dtBalance, setDtBalance] = useState() const [amountMax, setAmountMax] = useState() + const [newPoolTokens, setNewPoolTokens] = useState('0') + const [newPoolShare, setNewPoolShare] = useState('0') + const [isWarningAccepted, setIsWarningAccepted] = useState(false) // Live validation rules // https://github.com/jquense/yup#number @@ -150,18 +156,45 @@ export default function Add({ > {({ isSubmitting, submitForm }) => ( <> - +
+ {isWarningAccepted ? ( + + ) : ( + setIsWarningAccepted(true) + }} + /> + )} +
+ +
+
+

{content.output.titleIn}

+ + +
+
+

{content.output.titleOut}

+ +
+