136 lines
3.7 KiB
JavaScript
136 lines
3.7 KiB
JavaScript
import { useState, useEffect } from 'react'
|
|
import { Flex, InputNumber, Typography, Switch } from 'antd'
|
|
import PropTypes from 'prop-types'
|
|
|
|
const { Text } = Typography
|
|
|
|
const NetGrossInput = ({
|
|
value = {},
|
|
onChange,
|
|
prefix = '',
|
|
suffix = '',
|
|
min,
|
|
max,
|
|
step,
|
|
disabled = false,
|
|
difference = 0
|
|
}) => {
|
|
const net = value?.net
|
|
const gross = value?.gross
|
|
|
|
// State to track which input is enabled: true = Gross enabled, false = Net enabled
|
|
const [isGrossEnabled, setIsGrossEnabled] = useState(true)
|
|
|
|
// Helper to update both values based on which field is enabled
|
|
const handleChange = (field, val) => {
|
|
if (!onChange) return
|
|
if (field === 'net') {
|
|
const newNet = val
|
|
let newGross
|
|
if (typeof difference === 'number' && newNet != null) {
|
|
newGross = newNet + difference
|
|
} else {
|
|
newGross = undefined
|
|
}
|
|
onChange({ net: newNet, gross: newGross })
|
|
} else if (field === 'gross') {
|
|
const newGross = val
|
|
let newNet
|
|
if (typeof difference === 'number' && newGross != null) {
|
|
newNet = newGross - difference
|
|
} else {
|
|
newNet = undefined
|
|
}
|
|
onChange({ net: newNet, gross: newGross })
|
|
}
|
|
}
|
|
|
|
// When toggling between Net and Gross, recalculate the other value
|
|
const handleSwitch = (checked) => {
|
|
setIsGrossEnabled(checked)
|
|
if (!onChange) return
|
|
if (checked) {
|
|
// Switched to Gross: recalc net
|
|
if (typeof value?.gross === 'number' && typeof difference === 'number') {
|
|
onChange({ net: value.gross - difference, gross: value.gross })
|
|
}
|
|
} else {
|
|
// Switched to Net: recalc gross
|
|
if (typeof value?.net === 'number' && typeof difference === 'number') {
|
|
onChange({ net: value.net, gross: value.net + difference })
|
|
}
|
|
}
|
|
}
|
|
|
|
// When difference changes, recalculate the dependent value
|
|
useEffect(() => {
|
|
if (!onChange) return
|
|
if (isGrossEnabled) {
|
|
if (typeof value?.gross === 'number' && typeof difference === 'number') {
|
|
onChange({ net: value.gross - difference, gross: value.gross })
|
|
}
|
|
} else {
|
|
if (typeof value?.net === 'number' && typeof difference === 'number') {
|
|
onChange({ net: value.net, gross: value.net + difference })
|
|
}
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [difference])
|
|
|
|
return (
|
|
<Flex gap={'middle'} align='center'>
|
|
<InputNumber
|
|
addonBefore={<Text type='secondary'>Net:</Text>}
|
|
value={net}
|
|
onChange={(val) => handleChange('net', val)}
|
|
prefix={prefix}
|
|
suffix={suffix}
|
|
min={min}
|
|
max={max}
|
|
step={step}
|
|
disabled={disabled || isGrossEnabled}
|
|
style={
|
|
isGrossEnabled ? { minWidth: 120 } : { minWidth: 120, width: '100%' }
|
|
}
|
|
/>
|
|
|
|
<Switch
|
|
checked={isGrossEnabled}
|
|
onChange={handleSwitch}
|
|
disabled={disabled}
|
|
/>
|
|
<InputNumber
|
|
value={gross}
|
|
addonBefore={<Text type='secondary'>Gross:</Text>}
|
|
onChange={(val) => handleChange('gross', val)}
|
|
prefix={prefix}
|
|
suffix={suffix}
|
|
min={min}
|
|
max={max}
|
|
step={step}
|
|
disabled={disabled || !isGrossEnabled}
|
|
style={
|
|
isGrossEnabled ? { minWidth: 120, width: '100%' } : { minWidth: 120 }
|
|
}
|
|
/>
|
|
</Flex>
|
|
)
|
|
}
|
|
|
|
NetGrossInput.propTypes = {
|
|
value: PropTypes.shape({
|
|
net: PropTypes.number,
|
|
gross: PropTypes.number
|
|
}),
|
|
onChange: PropTypes.func,
|
|
prefix: PropTypes.string,
|
|
suffix: PropTypes.string,
|
|
min: PropTypes.number,
|
|
max: PropTypes.number,
|
|
step: PropTypes.number,
|
|
disabled: PropTypes.bool,
|
|
difference: PropTypes.number
|
|
}
|
|
|
|
export default NetGrossInput
|