2025-08-22 20:28:50 +01:00

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