lamassu-server/new-lamassu-admin/src/pages/Wallet/WizardStep.js

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