Add ArrayDisplay and ArrayInput components for enhanced array handling. ArrayDisplay provides a visual representation of array items with optional prefix and suffix, while ArrayInput allows dynamic addition and removal of items, supporting both text and numeric inputs for improved user interaction.
This commit is contained in:
parent
8cb2bea2d3
commit
0c6fe5cbac
30
src/components/Dashboard/common/ArrayDisplay.jsx
Normal file
30
src/components/Dashboard/common/ArrayDisplay.jsx
Normal file
@ -0,0 +1,30 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import { Flex, Tag, Typography } from 'antd'
|
||||
|
||||
const { Text } = Typography
|
||||
|
||||
const ArrayDisplay = ({ value, prefix, suffix }) => {
|
||||
if (!Array.isArray(value) || value.length === 0) {
|
||||
return <Text type='secondary'>n/a</Text>
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex gap='small' wrap>
|
||||
{value.map((item, index) => (
|
||||
<Tag key={`${item}-${index}`}>
|
||||
{prefix}
|
||||
{item}
|
||||
{suffix}
|
||||
</Tag>
|
||||
))}
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
ArrayDisplay.propTypes = {
|
||||
value: PropTypes.array,
|
||||
prefix: PropTypes.node,
|
||||
suffix: PropTypes.node
|
||||
}
|
||||
|
||||
export default ArrayDisplay
|
||||
83
src/components/Dashboard/common/ArrayInput.jsx
Normal file
83
src/components/Dashboard/common/ArrayInput.jsx
Normal file
@ -0,0 +1,83 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import { Button, Flex, Input, InputNumber } from 'antd'
|
||||
|
||||
const ArrayInput = ({
|
||||
value = [],
|
||||
onChange,
|
||||
disabled = false,
|
||||
numeric = false,
|
||||
min,
|
||||
max,
|
||||
step,
|
||||
placeholder
|
||||
}) => {
|
||||
const values = Array.isArray(value) ? value : []
|
||||
|
||||
const updateValue = (index, nextValue) => {
|
||||
const nextValues = [...values]
|
||||
nextValues[index] = nextValue
|
||||
onChange?.(nextValues)
|
||||
}
|
||||
|
||||
const removeValue = (index) => {
|
||||
onChange?.(values.filter((_, valueIndex) => valueIndex !== index))
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex vertical gap='small' style={{ width: '100%' }}>
|
||||
{values.map((item, index) => (
|
||||
<Flex key={index} gap='small' style={{ width: '100%' }}>
|
||||
{numeric ? (
|
||||
<InputNumber
|
||||
value={item}
|
||||
onChange={(nextValue) => updateValue(index, nextValue)}
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
placeholder={placeholder}
|
||||
disabled={disabled}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
) : (
|
||||
<Input
|
||||
value={item}
|
||||
onChange={(event) => updateValue(index, event.target.value)}
|
||||
placeholder={placeholder}
|
||||
disabled={disabled}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => removeValue(index)}
|
||||
disabled={disabled}
|
||||
danger
|
||||
aria-label={`Remove ${placeholder || 'item'}`}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
</Flex>
|
||||
))}
|
||||
<Button
|
||||
onClick={() => onChange?.([...values, numeric ? null : ''])}
|
||||
disabled={disabled}
|
||||
type='dashed'
|
||||
block
|
||||
>
|
||||
Add {placeholder || 'item'}
|
||||
</Button>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
ArrayInput.propTypes = {
|
||||
value: PropTypes.array,
|
||||
onChange: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
numeric: PropTypes.bool,
|
||||
min: PropTypes.number,
|
||||
max: PropTypes.number,
|
||||
step: PropTypes.number,
|
||||
placeholder: PropTypes.string
|
||||
}
|
||||
|
||||
export default ArrayInput
|
||||
Loading…
x
Reference in New Issue
Block a user