1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

lots of pricve refactor, build out advanced UI

This commit is contained in:
Matthias Kretschmann 2020-07-29 10:04:09 +02:00
parent 576b9f4c2e
commit cbee8a714d
Signed by: m
GPG Key ID: 606EEEF3C479A91F
13 changed files with 183 additions and 64 deletions

View File

@ -37,7 +37,6 @@
{ {
"name": "price", "name": "price",
"label": "Price", "label": "Price",
"help": "Set your price for accessing this data set in Ocean Tokens.",
"type": "price", "type": "price",
"required": true "required": true
}, },

View File

@ -1,9 +1,23 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import styles from './Help.module.css' import styles from './Help.module.css'
import Markdown from '../Markdown' import Markdown from '../Markdown'
import classNames from 'classnames/bind'
const FormHelp = ({ children }: { children: string }): ReactElement => ( const cx = classNames.bind(styles)
<Markdown className={styles.help} text={children} />
) const FormHelp = ({
children,
className
}: {
children: string
className?: string
}): ReactElement => {
const styleClasses = cx({
help: true,
[className]: className
})
return <Markdown className={styleClasses} text={children} />
}
export default FormHelp export default FormHelp

View File

@ -33,7 +33,8 @@
.input[readonly], .input[readonly],
.input[disabled] { .input[disabled] {
background-color: var(--brand-grey-lighter); background-color: var(--brand-grey-dimmed);
color: var(--brand-grey-light);
cursor: not-allowed; cursor: not-allowed;
pointer-events: none; pointer-events: none;
} }
@ -84,6 +85,56 @@
padding-left: 0.5rem; padding-left: 0.5rem;
} }
.prefixGroup,
.postfixGroup {
display: flex;
align-items: center;
}
.prefixGroup input,
.postfixGroup input {
width: auto;
}
.prefixGroup input {
border-left: 0;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.postfixGroup input {
border-right: 0;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.prefix,
.postfix {
border: 1px solid var(--brand-grey-lighter);
min-height: 43px;
display: flex;
align-items: center;
padding-left: calc(var(--spacer) / 2);
padding-right: calc(var(--spacer) / 2);
color: var(--color-secondary);
font-size: var(--font-size-small);
transition: border 0.2s ease-out;
}
.prefix {
border-top-left-radius: var(--border-radius);
border-bottom-left-radius: var(--border-radius);
}
.postfix {
border-top-right-radius: var(--border-radius);
border-bottom-right-radius: var(--border-radius);
}
.input:focus + .postfix {
border-color: var(--brand-grey);
}
/* Size modifiers */ /* Size modifiers */
.small { .small {

View File

@ -7,7 +7,7 @@ import Terms from '../../molecules/FormFields/Terms'
import Price from '../../molecules/FormFields/Price' import Price from '../../molecules/FormFields/Price'
export default function InputElement(props: InputProps): ReactElement { export default function InputElement(props: InputProps): ReactElement {
const { type, options, rows, name, value } = props const { type, options, rows, name, prefix, postfix } = props
switch (type) { switch (type) {
case 'select': case 'select':
@ -62,7 +62,19 @@ export default function InputElement(props: InputProps): ReactElement {
case 'terms': case 'terms':
return <Terms name={name} {...props} /> return <Terms name={name} {...props} />
default: default:
return ( return prefix || postfix ? (
<div className={`${prefix ? styles.prefixGroup : styles.postfixGroup}`}>
{prefix && <div className={styles.prefix}>{prefix}</div>}
<input
id={name}
className={styles.input}
name={name}
{...props}
type={type || 'text'}
/>
{postfix && <div className={styles.postfix}>{postfix}</div>}
</div>
) : (
<input <input
id={name} id={name}
className={styles.input} className={styles.input}

View File

@ -1,4 +1,4 @@
import React, { FormEvent, ChangeEvent, ReactElement } from 'react' import React, { FormEvent, ChangeEvent, ReactElement, ReactNode } from 'react'
import InputElement from './InputElement' import InputElement from './InputElement'
import Help from './Help' import Help from './Help'
import Label from './Label' import Label from './Label'
@ -31,8 +31,12 @@ export interface InputProps {
pattern?: string pattern?: string
min?: string min?: string
disabled?: boolean disabled?: boolean
readOnly?: boolean
field?: any field?: any
form?: any form?: any
prefix?: string
postfix?: string
step?: string
} }
export default function Input(props: Partial<InputProps>): ReactElement { export default function Input(props: Partial<InputProps>): ReactElement {

View File

@ -2,19 +2,29 @@ import React, { useEffect, useState, ReactElement } from 'react'
import useSWR from 'swr' import useSWR from 'swr'
import { fetchData, isBrowser } from '../../../utils' import { fetchData, isBrowser } from '../../../utils'
import styles from './Conversion.module.css' import styles from './Conversion.module.css'
import classNames from 'classnames/bind'
const cx = classNames.bind(styles)
const currencies = 'EUR' // comma-separated list const currencies = 'EUR' // comma-separated list
const url = `https://api.coingecko.com/api/v3/simple/price?ids=ocean-protocol&vs_currencies=${currencies}&include_24hr_change=true` const url = `https://api.coingecko.com/api/v3/simple/price?ids=ocean-protocol&vs_currencies=${currencies}&include_24hr_change=true`
export default function Conversion({ export default function Conversion({
price, price,
update = true update = true,
className
}: { }: {
price: string // expects price in OCEAN, not wei price: string // expects price in OCEAN, not wei
update?: boolean update?: boolean
className?: string
}): ReactElement { }): ReactElement {
const [priceEur, setPriceEur] = useState('0.00') const [priceEur, setPriceEur] = useState('0.00')
const styleClasses = cx({
conversion: true,
[className]: className
})
const onSuccess = async (data: { 'ocean-protocol': { eur: number } }) => { const onSuccess = async (data: { 'ocean-protocol': { eur: number } }) => {
if (!data) return if (!data) return
if (!price || price === '' || price === '0') { if (!price || price === '' || price === '0') {
@ -45,5 +55,5 @@ export default function Conversion({
}) })
} }
return <span className={styles.conversion}> EUR {priceEur}</span> return <span className={styleClasses}> EUR {priceEur}</span>
} }

View File

@ -1,9 +1,8 @@
.advancedInput { .advanced {
display: flex;
gap: calc(var(--spacer) / 2);
justify-content: center;
flex-wrap: wrap;
} }
.advancedInput label { .advanced > div:last-child {
display: grid;
gap: calc(var(--spacer) / 2);
grid-template-columns: 1fr 1fr;
} }

View File

@ -1,4 +1,4 @@
import React, { ReactElement } from 'react' import React, { ReactElement, useState, ChangeEvent } from 'react'
import { InputProps } from '../../../atoms/Input' import { InputProps } from '../../../atoms/Input'
import InputElement from '../../../atoms/Input/InputElement' import InputElement from '../../../atoms/Input/InputElement'
import stylesIndex from './index.module.css' import stylesIndex from './index.module.css'
@ -6,21 +6,62 @@ import styles from './Advanced.module.css'
import Label from '../../../atoms/Input/Label' import Label from '../../../atoms/Input/Label'
import { MetadataPublishForm } from '../../../../@types/MetaData' import { MetadataPublishForm } from '../../../../@types/MetaData'
import Cost from './Cost' import Cost from './Cost'
import Conversion from '../../../atoms/Price/Conversion'
import FormHelp from '../../../atoms/Input/Help'
export default function Advanced(props: InputProps): ReactElement { export default function Advanced(props: InputProps): ReactElement {
const { price } = props.form.values as MetadataPublishForm const { price } = props.form.values as MetadataPublishForm
const [weight, setWeight] = useState('10')
const liquidity = (price.cost * Number(weight)).toString()
function handleWeightChange(event: ChangeEvent<HTMLInputElement>) {
setWeight(event.target.value)
}
return ( return (
<div className={`${stylesIndex.content} ${styles.advancedInput}`}> <div className={stylesIndex.content}>
<Cost {...props} /> <div className={styles.advanced}>
<div> <FormHelp className={stylesIndex.help}>
<Label htmlFor="price.tokensToMint">Tokens to Mint</Label> Set your price for accessing this data set. A Data Token for this data
<InputElement set worth the entered amount of OCEAN, and a Data Token/OCEAN
{...props.field} liquidity pool will be created with Balancer.
value={(price && price.tokensToMint) || 1} </FormHelp>
name="price.tokensToMint"
type="number" <div>
/> <Cost {...props} />
<div>
<Label htmlFor="weight">Weight on Data Token</Label>
<InputElement
value={weight}
name="weight"
type="number"
onChange={handleWeightChange}
step="10"
postfix="%"
/>
</div>
<div className={styles.liquidity}>
<Label htmlFor="liquidity">Liquidity</Label>
<InputElement
value={liquidity}
name="liquidity"
readOnly
prefix="OCEAN"
/>
<Conversion price={liquidity} className={stylesIndex.conversion} />
</div>
<div>
<Label htmlFor="price.tokensToMint">Tokens to Mint</Label>
<InputElement
{...props.field}
value={(price && price.tokensToMint) || 1}
name="price.tokensToMint"
type="number"
disabled
/>
</div>
</div>
</div> </div>
</div> </div>
) )

View File

@ -1,28 +0,0 @@
.cost {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.cost label {
width: 100%;
}
.cost input {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.prefix {
border: 1px solid var(--brand-grey-lighter);
min-height: 43px;
display: flex;
align-items: center;
padding-left: calc(var(--spacer) / 2);
padding-right: calc(var(--spacer) / 2);
color: var(--color-secondary);
font-size: var(--font-size-small);
margin-right: -2px;
border-top-left-radius: var(--border-radius);
border-bottom-left-radius: var(--border-radius);
}

View File

@ -1,26 +1,30 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import InputElement from '../../../atoms/Input/InputElement' import InputElement from '../../../atoms/Input/InputElement'
import styles from './Cost.module.css'
import { MetadataPublishForm } from '../../../../@types/MetaData' import { MetadataPublishForm } from '../../../../@types/MetaData'
import Conversion from '../../../atoms/Price/Conversion' import Conversion from '../../../atoms/Price/Conversion'
import { InputProps } from '../../../atoms/Input' import { InputProps } from '../../../atoms/Input'
import Label from '../../../atoms/Input/Label' import Label from '../../../atoms/Input/Label'
import stylesIndex from './index.module.css'
export default function Cost(props: InputProps): ReactElement { export default function Cost(props: InputProps): ReactElement {
const { price } = props.form.values as MetadataPublishForm const { price } = props.form.values as MetadataPublishForm
return ( return (
<div className={styles.cost}> <div>
<Label htmlFor="price.cost">Cost</Label> <Label htmlFor="price.cost">Cost</Label>
<div className={styles.prefix}>OCEAN</div>
<InputElement <InputElement
{...props.field} {...props.field}
value={(price && price.cost) || 0} value={(price && price.cost) || 0}
name="price.cost" name="price.cost"
type="number" type="number"
prefix="OCEAN"
/>
<Conversion
price={price.cost.toString()}
className={stylesIndex.conversion}
/> />
<Conversion price={price.cost.toString()} />
</div> </div>
) )
} }

View File

@ -1,10 +1,9 @@
.simple { .simple {
margin-bottom: calc(var(--spacer) / 2);
text-align: center;
} }
.simple > div { .simple > div:last-child {
justify-content: center; max-width: 13.25rem;
margin: 0 auto;
} }
.simple label { .simple label {

View File

@ -9,9 +9,12 @@ export default function Simple(props: InputProps): ReactElement {
return ( return (
<div className={stylesIndex.content}> <div className={stylesIndex.content}>
<div className={styles.simple}> <div className={styles.simple}>
<FormHelp className={stylesIndex.help}>
Set your price for accessing this data set. A Data Token for this data
set worth the entered amount of OCEAN will be created.
</FormHelp>
<Cost {...props} /> <Cost {...props} />
</div> </div>
{props.help && <FormHelp>{props.help}</FormHelp>}
</div> </div>
) )
} }

View File

@ -20,3 +20,14 @@
.content p { .content p {
margin-bottom: 0; margin-bottom: 0;
} }
.conversion {
display: block;
padding-left: 5rem;
margin-top: calc(var(--spacer) / 6);
}
.help {
text-align: center;
margin-bottom: calc(var(--spacer) / 2);
}