lamassu-server/packages/admin-ui/src/pages/Services/FormRenderer.jsx
2025-05-23 16:53:04 +01:00

85 lines
2.4 KiB
JavaScript

import classnames from 'classnames'
import { Formik, Form, FastField } from 'formik'
import * as R from 'ramda'
import React, { useState } from 'react'
import ErrorMessage from '../../components/ErrorMessage'
import { Button } from '../../components/buttons'
import { SecretInput } from '../../components/inputs/formik'
const FormRenderer = ({
validationSchema,
elements,
value,
save,
buttonLabel = 'Save changes',
buttonClass,
}) => {
const initialValues = R.compose(
R.mergeAll,
R.map(({ code }) => ({ [code]: (value && value[code]) ?? '' })),
)(elements)
const values = R.mergeRight(initialValues, value)
const [saveError, setSaveError] = useState([])
const saveNonEmptySecret = it => {
const emptySecretFields = R.compose(
R.map(R.prop('code')),
R.filter(
elem =>
R.prop('component', elem) === SecretInput &&
R.isEmpty(it[R.prop('code', elem)]),
),
)(elements)
return save(R.omit(emptySecretFields, it)).catch(() => {
setSaveError({ save: 'Failed to save changes' })
})
}
return (
<Formik
validateOnBlur={false}
validateOnChange={false}
enableReinitialize
initialValues={values}
validationSchema={validationSchema}
onSubmit={saveNonEmptySecret}>
{({ errors }) => (
<Form className="flex flex-col flex-1">
<div className="flex flex-col gap-3 mb-6 mt-3">
{elements.map(
({ component, code, display, settings, inputProps }) => (
<div key={code}>
<FastField
component={component}
{...inputProps}
name={code}
label={display}
settings={settings}
fullWidth={true}
/>
</div>
),
)}
</div>
<div className="flex flex-row mt-auto mb-8">
{!R.isEmpty(R.mergeRight(errors, saveError)) && (
<ErrorMessage>
{R.head(R.values(R.mergeRight(errors, saveError)))}
</ErrorMessage>
)}
<Button
className={classnames('mt-auto ml-auto', buttonClass)}
type="submit">
{buttonLabel}
</Button>
</div>
</Form>
)}
</Formik>
)
}
export default FormRenderer