199 lines
5.4 KiB
JavaScript
199 lines
5.4 KiB
JavaScript
import { makeStyles } from '@material-ui/core'
|
|
import classnames from 'classnames'
|
|
import { Formik, Form, Field } from 'formik'
|
|
import * as R from 'ramda'
|
|
import React, { useReducer, useEffect } from 'react'
|
|
|
|
import ErrorMessage from 'src/components/ErrorMessage'
|
|
import Stepper from 'src/components/Stepper'
|
|
import { Button } from 'src/components/buttons'
|
|
import { RadioGroup, Autocomplete } from 'src/components/inputs'
|
|
import { NumberInput } from 'src/components/inputs/formik'
|
|
import { H4, Info2 } from 'src/components/typography'
|
|
import FormRenderer from 'src/pages/Services/FormRenderer'
|
|
import schema from 'src/pages/Services/schemas'
|
|
import { startCase } from 'src/utils/string'
|
|
|
|
import styles from './WizardStep.styles'
|
|
|
|
const useStyles = makeStyles(styles)
|
|
|
|
const initialState = {
|
|
form: null,
|
|
selected: null,
|
|
isNew: false,
|
|
iError: false
|
|
}
|
|
|
|
const reducer = (state, action) => {
|
|
switch (action.type) {
|
|
case 'select':
|
|
return {
|
|
form: null,
|
|
selected: action.selected,
|
|
isNew: null,
|
|
iError: false
|
|
}
|
|
case 'new':
|
|
return { form: state.form, selected: null, isNew: true, iError: false }
|
|
case 'form':
|
|
return {
|
|
form: action.form,
|
|
selected: action.form.code,
|
|
isNew: true,
|
|
iError: false
|
|
}
|
|
case 'error':
|
|
return R.merge(state, { innerError: true })
|
|
case 'reset':
|
|
return initialState
|
|
default:
|
|
throw new Error()
|
|
}
|
|
}
|
|
|
|
const WizardStep = ({
|
|
type,
|
|
schema: stepSchema,
|
|
coin,
|
|
name,
|
|
error,
|
|
step,
|
|
maxSteps,
|
|
lastStep,
|
|
isLastStep,
|
|
onContinue,
|
|
fiatCurrency,
|
|
filled,
|
|
unfilled,
|
|
getValue
|
|
}) => {
|
|
const classes = useStyles()
|
|
const [{ innerError, selected, form, isNew }, dispatch] = useReducer(
|
|
reducer,
|
|
initialState
|
|
)
|
|
|
|
useEffect(() => {
|
|
dispatch({ type: 'reset' })
|
|
}, [step])
|
|
|
|
const innerContinue = (config, account) => {
|
|
if (!config || !config[type]) {
|
|
return dispatch({ type: 'error' })
|
|
}
|
|
onContinue(config, account)
|
|
}
|
|
|
|
const label = isLastStep ? 'Finish' : 'Next'
|
|
const displayName = name ?? type
|
|
const subtitleClass = {
|
|
[classes.subtitle]: true,
|
|
[classes.error]: innerError
|
|
}
|
|
return (
|
|
<>
|
|
<Info2 className={classes.title}>{startCase(displayName)}</Info2>
|
|
<Stepper steps={lastStep} currentStep={step} />
|
|
<H4 className={classnames(subtitleClass)}>
|
|
{step < maxSteps - 1
|
|
? `Select a ${displayName} or set up a new one`
|
|
: `Select ${displayName} for ${coin}`}
|
|
</H4>
|
|
{!(isLastStep && step === maxSteps) && (
|
|
<RadioGroup
|
|
options={filled}
|
|
value={selected}
|
|
className={classes.radioGroup}
|
|
onChange={(evt, it) => {
|
|
dispatch({ type: 'select', selected: it })
|
|
}}
|
|
labelClassName={classes.radioLabel}
|
|
radioClassName={classes.radio}
|
|
/>
|
|
)}
|
|
{type === 'zeroConfLimit' && (
|
|
<Formik
|
|
validateOnBlur={false}
|
|
validateOnChange={true}
|
|
initialValues={{ zeroConfLimit: '' }}
|
|
enableReinitialize
|
|
validationSchema={stepSchema}>
|
|
{({ values, setFieldValue }) => (
|
|
<Form>
|
|
<div
|
|
className={classnames(
|
|
classes.horizontalAlign,
|
|
classes.lineAlignment
|
|
)}>
|
|
<Field
|
|
component={NumberInput}
|
|
decimalPlaces={0}
|
|
width={50}
|
|
placeholder={'0'}
|
|
name={`zeroConfLimit`}
|
|
onChange={event => {
|
|
dispatch({
|
|
type: 'select',
|
|
selected: event.target.value
|
|
})
|
|
setFieldValue(event.target.id, event.target.value)
|
|
}}
|
|
className={classes.zeroConfLimit}
|
|
/>
|
|
<Info2>{fiatCurrency}</Info2>
|
|
</div>
|
|
</Form>
|
|
)}
|
|
</Formik>
|
|
)}
|
|
<div className={classes.setupNew}>
|
|
{!R.isEmpty(unfilled) && !R.isNil(unfilled) && (
|
|
<RadioGroup
|
|
value={isNew}
|
|
onChange={(evt, it) => {
|
|
dispatch({ type: 'new' })
|
|
}}
|
|
labelClassName={classes.radioLabel}
|
|
radioClassName={classes.radio}
|
|
options={[{ display: 'Set up new', code: true }]}
|
|
/>
|
|
)}
|
|
{isNew && (
|
|
<Autocomplete
|
|
fullWidth
|
|
label={`Select ${displayName}`}
|
|
className={classes.picker}
|
|
getOptionSelected={R.eqProps('code')}
|
|
labelProp={'display'}
|
|
options={unfilled}
|
|
onChange={(evt, it) => {
|
|
dispatch({ type: 'form', form: it })
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
{form && (
|
|
<FormRenderer
|
|
save={it => innerContinue({ [type]: form.code }, { [form.code]: it })}
|
|
elements={schema[form.code].elements}
|
|
validationSchema={schema[form.code].validationSchema}
|
|
value={getValue(form.code)}
|
|
buttonLabel={label}
|
|
/>
|
|
)}
|
|
{!form && (
|
|
<div className={classes.submit}>
|
|
{error && <ErrorMessage>Failed to save</ErrorMessage>}
|
|
<Button
|
|
className={classes.button}
|
|
onClick={() => innerContinue({ [type]: selected })}>
|
|
{label}
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default WizardStep
|