feat: allow for multifield inputs in EditableTable

This commit is contained in:
Sérgio Salgado 2023-05-29 17:47:27 +01:00
parent 6fbb2b4c5b
commit e194509d10
3 changed files with 120 additions and 73 deletions

View file

@ -120,6 +120,7 @@ const ActionCol = ({ disabled, editing }) => {
const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => { const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
const { const {
name, name,
names,
bypassField, bypassField,
input, input,
editable = true, editable = true,
@ -128,6 +129,8 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
width, width,
textAlign, textAlign,
editingAlign = textAlign, editingAlign = textAlign,
prefix,
PrefixComponent = Label2,
suffix, suffix,
SuffixComponent = Label2, SuffixComponent = Label2,
textStyle = it => {}, textStyle = it => {},
@ -136,6 +139,8 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
inputProps = {} inputProps = {}
} = config } = config
const fields = names ?? [name]
const { values } = useFormikContext() const { values } = useFormikContext()
const isEditable = editable => { const isEditable = editable => {
if (typeof editable === 'function') return editable(values) if (typeof editable === 'function') return editable(values)
@ -159,25 +164,35 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
} }
return ( return (
<div className={classes.fields}>
{R.map(f => (
<Td <Td
className={{ className={{
[classes.extraPaddingRight]: extraPaddingRight, [classes.extraPaddingRight]: extraPaddingRight,
[classes.extraPadding]: extraPadding, [classes.extraPadding]: extraPadding,
[classes.withSuffix]: suffix [classes.withSuffix]: suffix,
[classes.withPrefix]: prefix
}} }}
width={width} width={width}
size={size} size={size}
bold={bold} bold={bold}
textAlign={textAlign}> textAlign={textAlign}>
{prefix && !isHidden(values) && (
<PrefixComponent
className={classes.prefix}
style={isEditing ? {} : textStyle(values, isEditing)}>
{typeof prefix === 'function' ? prefix(f) : prefix}
</PrefixComponent>
)}
{isEditing && isField && !isHidden(values) && ( {isEditing && isField && !isHidden(values) && (
<Field name={name} component={input} {...innerProps} /> <Field name={f} component={input} {...innerProps} />
)} )}
{isEditing && !isField && !isHidden(values) && ( {isEditing && !isField && !isHidden(values) && (
<config.input name={name} /> <config.input name={f} />
)} )}
{!isEditing && values && !isHidden(values) && ( {!isEditing && values && !isHidden(values) && (
<div style={textStyle(values, isEditing)}> <div style={textStyle(values, isEditing)}>
{view(values[name], values)} {view(values[f], values)}
</div> </div>
)} )}
{suffix && !isHidden(values) && ( {suffix && !isHidden(values) && (
@ -189,6 +204,8 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
)} )}
{isHidden(values) && <StripesSvg />} {isHidden(values) && <StripesSvg />}
</Td> </Td>
))(fields)}
</div>
) )
} }

View file

@ -25,6 +25,21 @@ export default {
suffix: { suffix: {
margin: [[0, 0, 0, 7]] margin: [[0, 0, 0, 7]]
}, },
withPrefix: ({ textAlign }) => {
const justifyContent = textAlign === 'right' ? 'flex-end' : textAlign
return {
display: 'flex',
alignItems: 'center',
justifyContent
}
},
prefix: {
margin: [[0, 7, 0, 0]]
},
size: ({ size }) => bySize(size), size: ({ size }) => bySize(size),
bold bold,
fields: {
display: 'flex',
flexDirection: 'column'
}
} }

View file

@ -14,8 +14,7 @@ const widthsByNumberOfCassettes = {
4: { machine: 195, cassette: 190 }, 4: { machine: 195, cassette: 190 },
5: { machine: 175, cassette: 155 }, 5: { machine: 175, cassette: 155 },
6: { machine: 170, cassette: 130 }, 6: { machine: 170, cassette: 130 },
7: { machine: 140, cassette: 125 }, 7: { machine: 140, cassette: 125 }
8: { machine: 120, cassette: 125 }
} }
const DenominationsSchema = Yup.object().shape({ const DenominationsSchema = Yup.object().shape({
@ -41,6 +40,42 @@ const DenominationsSchema = Yup.object().shape({
.min(1) .min(1)
.max(CURRENCY_MAX) .max(CURRENCY_MAX)
.nullable() .nullable()
.transform(transformNumber),
stacker1f: Yup.number()
.label('Stacker 1')
.min(1)
.max(CURRENCY_MAX)
.nullable()
.transform(transformNumber),
stacker1r: Yup.number()
.label('Stacker 1')
.min(1)
.max(CURRENCY_MAX)
.nullable()
.transform(transformNumber),
stacker2f: Yup.number()
.label('Stacker 2')
.min(1)
.max(CURRENCY_MAX)
.nullable()
.transform(transformNumber),
stacker2r: Yup.number()
.label('Stacker 2')
.min(1)
.max(CURRENCY_MAX)
.nullable()
.transform(transformNumber),
stacker3f: Yup.number()
.label('Stacker 3')
.min(1)
.max(CURRENCY_MAX)
.nullable()
.transform(transformNumber),
stacker3r: Yup.number()
.label('Stacker 3')
.min(1)
.max(CURRENCY_MAX)
.nullable()
.transform(transformNumber) .transform(transformNumber)
}) })
@ -55,7 +90,7 @@ const getElements = (machines, locale = {}, classes) => {
0 0
) )
const maxNumberOfCashUnits = Math.max( const maxNumberOfCashUnits = Math.max(
...R.map(it => it.numberOfCassettes + it.numberOfStackers * 2, machines), ...R.map(it => it.numberOfCassettes + it.numberOfStackers, machines),
0 0
) )
@ -96,7 +131,7 @@ const getElements = (machines, locale = {}, classes) => {
view: it => it, view: it => it,
input: options?.length > 0 ? Autocomplete : NumberInput, input: options?.length > 0 ? Autocomplete : NumberInput,
inputProps: cassetteProps, inputProps: cassetteProps,
doubleHeader: 'Denominations', doubleHeader: 'Denominations of Cassettes & Recyclers',
isHidden: machine => isHidden: machine =>
it > it >
machines.find(({ deviceId }) => deviceId === machine.id) machines.find(({ deviceId }) => deviceId === machine.id)
@ -110,44 +145,24 @@ const getElements = (machines, locale = {}, classes) => {
R.until( R.until(
R.gt(R.__, maxNumberOfStackers), R.gt(R.__, maxNumberOfStackers),
it => { it => {
elements.push( elements.push({
{ names: [`stacker${it}f`, `stacker${it}r`],
name: `stacker${it}f`, header: `Stacker ${it}`,
header: `Stacker ${it}F`,
size: 'sm', size: 'sm',
stripe: true, stripe: true,
textAlign: 'right', textAlign: 'right',
width: widthsByNumberOfCassettes[maxNumberOfCashUnits]?.cassette, width: widthsByNumberOfCassettes[maxNumberOfCashUnits]?.cassette,
prefix: it => (R.last(it) === 'f' ? 'F' : 'R'),
suffix: fiatCurrency, suffix: fiatCurrency,
bold: bold, bold: bold,
view: it => it,
input: options?.length > 0 ? Autocomplete : NumberInput, input: options?.length > 0 ? Autocomplete : NumberInput,
inputProps: cassetteProps, inputProps: cassetteProps,
doubleHeader: 'Denominations', doubleHeader: 'Denominations of Cassettes & Recyclers',
isHidden: machine => isHidden: machine =>
it > it >
machines.find(({ deviceId }) => deviceId === machine.id) machines.find(({ deviceId }) => deviceId === machine.id)
.numberOfStackers .numberOfStackers
}, })
{
name: `stacker${it}r`,
header: `Stacker ${it}R`,
size: 'sm',
stripe: true,
textAlign: 'right',
width: widthsByNumberOfCassettes[maxNumberOfCashUnits]?.cassette,
suffix: fiatCurrency,
bold: bold,
view: it => it,
input: options?.length > 0 ? Autocomplete : NumberInput,
inputProps: cassetteProps,
doubleHeader: 'Denominations',
isHidden: machine =>
it >
machines.find(({ deviceId }) => deviceId === machine.id)
.numberOfStackers
}
)
return R.add(1, it) return R.add(1, it)
}, },
1 1