1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-11-15 09:44:53 +01:00

construct pricing form data flow

This commit is contained in:
Matthias Kretschmann 2020-10-20 14:28:51 +02:00
parent 9ce1358fe1
commit de421d3c00
Signed by: m
GPG Key ID: 606EEEF3C479A91F
14 changed files with 41 additions and 66 deletions

View File

@ -4,7 +4,6 @@ import styles from './InputElement.module.css'
import { InputProps } from '.' import { InputProps } from '.'
import FilesInput from '../../molecules/FormFields/FilesInput' import FilesInput from '../../molecules/FormFields/FilesInput'
import Terms from '../../molecules/FormFields/Terms' import Terms from '../../molecules/FormFields/Terms'
import Price from '../../molecules/FormFields/Price'
import Datatoken from '../../molecules/FormFields/Datatoken' import Datatoken from '../../molecules/FormFields/Datatoken'
const DefaultInput = ({ const DefaultInput = ({
@ -88,8 +87,6 @@ export default function InputElement({
) )
case 'files': case 'files':
return <FilesInput name={name} {...field} {...props} /> return <FilesInput name={name} {...field} {...props} />
case 'price':
return <Price name={name} {...field} {...props} />
case 'datatoken': case 'datatoken':
return <Datatoken name={name} {...field} {...props} /> return <Datatoken name={name} {...field} {...props} />
case 'terms': case 'terms':

View File

@ -20,6 +20,7 @@ export default function Coin({
readOnly?: boolean readOnly?: boolean
}): ReactElement { }): ReactElement {
const [field, meta] = useField(name) const [field, meta] = useField(name)
console.log(field)
return ( return (
<div className={styles.coin}> <div className={styles.coin}>
@ -41,6 +42,8 @@ export default function Coin({
readOnly={readOnly} readOnly={readOnly}
prefix={datatokenOptions?.symbol || 'DT'} prefix={datatokenOptions?.symbol || 'DT'}
min="1" min="1"
name={name}
value={field.value}
{...field} {...field}
/> />
{datatokenOptions?.symbol === 'OCEAN' && ( {datatokenOptions?.symbol === 'OCEAN' && (

View File

@ -1,32 +1,28 @@
import { DataTokenOptions, useOcean } from '@oceanprotocol/react' import { DataTokenOptions, useOcean } from '@oceanprotocol/react'
import PriceUnit from '../../../atoms/Price/PriceUnit' import PriceUnit from '../../../atoms/Price/PriceUnit'
import React, { ReactElement, useEffect, useState } from 'react' import React, { ReactElement, useEffect, useState } from 'react'
import { PriceOptionsMarket } from '../../../../@types/MetaData'
import { useSiteMetadata } from '../../../../hooks/useSiteMetadata' import { useSiteMetadata } from '../../../../hooks/useSiteMetadata'
import { isCorrectNetwork } from '../../../../utils/wallet' import { isCorrectNetwork } from '../../../../utils/wallet'
import Alert from '../../../atoms/Alert' import Alert from '../../../atoms/Alert'
import FormHelp from '../../../atoms/Input/Help' import FormHelp from '../../../atoms/Input/Help'
import Tooltip from '../../../atoms/Tooltip' import Tooltip from '../../../atoms/Tooltip'
import Wallet from '../../Wallet' import Wallet from '../../../molecules/Wallet'
import Coin from './Coin' import Coin from './Coin'
import styles from './Dynamic.module.css' import styles from './Dynamic.module.css'
import Fees from './Fees' import Fees from './Fees'
import stylesIndex from './index.module.css' import stylesIndex from './index.module.css'
import { useFormikContext } from 'formik'
export default function Dynamic({ export default function Dynamic({
ocean,
priceOptions,
datatokenOptions, datatokenOptions,
content content
}: { }: {
ocean: number
priceOptions: PriceOptionsMarket
datatokenOptions: DataTokenOptions datatokenOptions: DataTokenOptions
content: any content: any
}): ReactElement { }): ReactElement {
const { appConfig } = useSiteMetadata() const { appConfig } = useSiteMetadata()
const { account, balance, networkId, refreshBalance } = useOcean() const { account, balance, networkId, refreshBalance } = useOcean()
const { weightOnDataToken } = priceOptions const { values } = useFormikContext()
const [error, setError] = useState<string>() const [error, setError] = useState<string>()
const correctNetwork = isCorrectNetwork(networkId) const correctNetwork = isCorrectNetwork(networkId)
@ -40,12 +36,19 @@ export default function Dynamic({
setError(`No account connected. Please connect your Web3 wallet.`) setError(`No account connected. Please connect your Web3 wallet.`)
} else if (!correctNetwork) { } else if (!correctNetwork) {
setError(`Wrong Network. Please connect to ${desiredNetworkName}.`) setError(`Wrong Network. Please connect to ${desiredNetworkName}.`)
} else if (Number(balance.ocean) < Number(ocean)) { } else if (Number(balance.ocean) < Number(values.price)) {
setError(`Insufficient balance. You need at least ${ocean} OCEAN`) setError(`Insufficient balance. You need at least ${values.price} OCEAN`)
} else { } else {
setError(undefined) setError(undefined)
} }
}, [ocean, networkId, account, balance, correctNetwork, desiredNetworkName]) }, [
values.price,
networkId,
account,
balance,
correctNetwork,
desiredNetworkName
])
// refetch balance periodically // refetch balance periodically
useEffect(() => { useEffect(() => {
@ -57,7 +60,7 @@ export default function Dynamic({
return () => { return () => {
clearInterval(balanceInterval) clearInterval(balanceInterval)
} }
}, [ocean, networkId, account]) }, [networkId, account])
return ( return (
<div className={styles.dynamic}> <div className={styles.dynamic}>
@ -81,14 +84,14 @@ export default function Dynamic({
<div className={styles.tokens}> <div className={styles.tokens}>
<Coin <Coin
name="price.price" name="price"
datatokenOptions={{ symbol: 'OCEAN', name: 'Ocean Token' }} datatokenOptions={{ symbol: 'OCEAN', name: 'Ocean Token' }}
weight={`${100 - Number(Number(weightOnDataToken) * 10)}%`} weight={`${100 - Number(Number(values.weightOnDataToken) * 10)}%`}
/> />
<Coin <Coin
name="price.tokensToMint" name="dtAmount"
datatokenOptions={datatokenOptions} datatokenOptions={datatokenOptions}
weight={`${Number(weightOnDataToken) * 10}%`} weight={`${Number(values.weightOnDataToken) * 10}%`}
readOnly readOnly
/> />
</div> </div>

View File

@ -1,7 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import Tooltip from '../../../atoms/Tooltip' import Tooltip from '../../../atoms/Tooltip'
import styles from './Fees.module.css' import styles from './Fees.module.css'
import { useSiteMetadata } from '../../../../hooks/useSiteMetadata'
import { useField } from 'formik' import { useField } from 'formik'
import Input from '../../../atoms/Input' import Input from '../../../atoms/Input'
import Error from './Error' import Error from './Error'
@ -11,8 +10,7 @@ export default function Fees({
}: { }: {
tooltips: { [key: string]: string } tooltips: { [key: string]: string }
}): ReactElement { }): ReactElement {
const { appConfig } = useSiteMetadata() const [field, meta] = useField('swapFee')
const [field, meta] = useField('price.swapFee')
return ( return (
<> <>

View File

@ -8,7 +8,7 @@ import Input from '../../../atoms/Input'
import Error from './Error' import Error from './Error'
export default function Fixed({ content }: { content: any }): ReactElement { export default function Fixed({ content }: { content: any }): ReactElement {
const [field, meta] = useField('price.price') const [field, meta] = useField('price')
return ( return (
<div className={styles.fixed}> <div className={styles.fixed}>
@ -19,7 +19,7 @@ export default function Fixed({ content }: { content: any }): ReactElement {
<Input <Input
label="Ocean Token" label="Ocean Token"
value={field.value} value={field.value}
name="price.price" name="price"
type="number" type="number"
prefix="OCEAN" prefix="OCEAN"
min="1" min="1"

View File

@ -1,12 +1,12 @@
import React, { ReactElement, useState, useEffect } from 'react' import React, { ReactElement, useEffect } from 'react'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import { InputProps } from '../../../atoms/Input'
import styles from './index.module.css' import styles from './index.module.css'
import Tabs from '../../../atoms/Tabs' import Tabs from '../../../atoms/Tabs'
import Fixed from './Fixed' import Fixed from './Fixed'
import Dynamic from './Dynamic' import Dynamic from './Dynamic'
import { useField } from 'formik' import { useFormikContext } from 'formik'
import { useUserPreferences } from '../../../../providers/UserPreferences' import { useUserPreferences } from '../../../../providers/UserPreferences'
import ddo from '../../../../../tests/unit/__fixtures__/ddo'
import { PriceOptionsMarket } from '../../../../@types/MetaData' import { PriceOptionsMarket } from '../../../../@types/MetaData'
const query = graphql` const query = graphql`
@ -38,26 +38,23 @@ const query = graphql`
} }
` `
export default function Price(props: InputProps): ReactElement { export default function Price(): ReactElement {
const { debug } = useUserPreferences() const { debug } = useUserPreferences()
const data = useStaticQuery(query) const data = useStaticQuery(query)
const content = data.content.edges[0].node.childPagesJson.price const content = data.content.edges[0].node.childPagesJson.price
const [field, meta, helpers] = useField(props.name) const { values, setFieldValue } = useFormikContext()
const { price }: PriceOptionsMarket = field.value const { price, weightOnDataToken, type } = values as PriceOptionsMarket
const [tokensToMint, setTokensToMint] = useState<number>()
function handleTabChange(tabName: string) { function handleTabChange(tabName: string) {
const type = tabName.toLowerCase() const type = tabName.toLowerCase()
helpers.setValue({ ...field.value, type }) setFieldValue('type', type)
} }
// Always update everything when amountOcean changes // Always update everything when price changes
useEffect(() => { useEffect(() => {
const tokensToMint = Number(price) * Number(field.value.weightOnDataToken) const dtAmount = Number(price) * Number(weightOnDataToken)
setTokensToMint(tokensToMint) setFieldValue('dtAmount', dtAmount)
helpers.setValue({ ...field.value, tokensToMint })
}, [price]) }, [price])
const tabs = [ const tabs = [
@ -69,9 +66,7 @@ export default function Price(props: InputProps): ReactElement {
title: content.dynamic.title, title: content.dynamic.title,
content: ( content: (
<Dynamic <Dynamic
ocean={price} datatokenOptions={ddo.dataTokenInfo}
priceOptions={{ ...field.value, tokensToMint }}
datatokenOptions={field.value.datatoken}
content={content.dynamic} content={content.dynamic}
/> />
) )
@ -83,11 +78,11 @@ export default function Price(props: InputProps): ReactElement {
<Tabs <Tabs
items={tabs} items={tabs}
handleTabChange={handleTabChange} handleTabChange={handleTabChange}
defaultIndex={field?.value?.type === 'fixed' ? 0 : 1} defaultIndex={type === 'fixed' ? 0 : 1}
/> />
{debug === true && ( {debug === true && (
<pre> <pre>
<code>{JSON.stringify(field.value, null, 2)}</code> <code>{JSON.stringify(values, null, 2)}</code>
</pre> </pre>
)} )}
</div> </div>

View File

@ -7,6 +7,7 @@ import { usePricing } from '@oceanprotocol/react'
import { PriceOptionsMarket } from '../../../@types/MetaData' import { PriceOptionsMarket } from '../../../@types/MetaData'
import Alert from '../../atoms/Alert' import Alert from '../../atoms/Alert'
import styles from './Pricing.module.css' import styles from './Pricing.module.css'
import Price from './Price'
export default function Pricing({ ddo }: { ddo: DDO }): ReactElement { export default function Pricing({ ddo }: { ddo: DDO }): ReactElement {
const { createPricing } = usePricing(ddo) const { createPricing } = usePricing(ddo)
@ -32,27 +33,7 @@ export default function Pricing({ ddo }: { ddo: DDO }): ReactElement {
setSubmitting(false) setSubmitting(false)
}} }}
> >
{() => ( {(props) => <Price name="price" {...props} />}
<>
<Field name="price">
{({
field,
form
}: {
field: FieldInputProps<PriceOptionsMarket>
form: any
}) => (
<Input
type="price"
name="price"
label="Create Price"
field={field}
form={form}
/>
)}
</Field>
</>
)}
</Formik> </Formik>
) : ( ) : (
<Alert <Alert

View File

@ -3,9 +3,7 @@ import * as Yup from 'yup'
export const validationSchema = Yup.object().shape<PriceOptionsMarket>({ export const validationSchema = Yup.object().shape<PriceOptionsMarket>({
price: Yup.number().min(1, 'Must be greater than 0').required('Required'), price: Yup.number().min(1, 'Must be greater than 0').required('Required'),
tokensToMint: Yup.number() dtAmount: Yup.number().min(1, 'Must be greater than 0').required('Required'),
.min(1, 'Must be greater than 0')
.required('Required'),
type: Yup.string() type: Yup.string()
.matches(/fixed|dynamic/g) .matches(/fixed|dynamic/g)
.required('Required'), .required('Required'),
@ -20,7 +18,7 @@ export const validationSchema = Yup.object().shape<PriceOptionsMarket>({
export const initialValues: Partial<PriceOptionsMarket> = { export const initialValues: Partial<PriceOptionsMarket> = {
price: 1, price: 1,
type: 'dynamic', type: 'dynamic',
tokensToMint: 1, dtAmount: 1,
weightOnDataToken: '9', // 90% on data token weightOnDataToken: '9', // 90% on data token
swapFee: 0.1 // in % swapFee: 0.1 // in %
} }