Implemented better address handling.
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good

This commit is contained in:
Tom Butcher 2026-03-07 14:05:23 +00:00
parent 112cbb5ce8
commit fd968bb2b5
3 changed files with 133 additions and 45 deletions

View File

@ -0,0 +1,110 @@
import PropTypes from 'prop-types'
import { Flex, Typography, Input } from 'antd'
import CountryDisplay from './CountryDisplay'
import CountrySelect from './CountrySelect'
const { Text } = Typography
const ADDRESS_FIELDS = [
{ key: 'building', label: 'Building' },
{ key: 'addressLine1', label: 'Line 1' },
{ key: 'addressLine2', label: 'Line 2' },
{ key: 'city', label: 'City' },
{ key: 'state', label: 'State' },
{ key: 'postcode', label: 'Postcode' },
{ key: 'country', label: 'Country', isCountry: true }
]
const AddressDisplay = ({
value,
isEditing = false,
onChange,
disabled = false
}) => {
const address = value && typeof value === 'object' ? value : {}
const hasAddress = ADDRESS_FIELDS.some(
(f) => address[f.key] != null && address[f.key] !== ''
)
const handleFieldChange = (field, fieldValue) => {
if (!onChange) return
onChange({
...address,
[field]: fieldValue
})
}
if (!isEditing) {
if (!hasAddress) {
return <Text type='secondary'>n/a</Text>
}
return (
<Flex vertical gap={4}>
{ADDRESS_FIELDS.map(({ key, label, isCountry }) => {
const fieldValue = address[key]
if (fieldValue == null || fieldValue === '') return null
return (
<Flex key={key} gap={8} align='baseline'>
{isCountry ? (
<CountryDisplay countryCode={fieldValue} />
) : (
<Text ellipsis alt={label}>
{fieldValue}
</Text>
)}
</Flex>
)
})}
</Flex>
)
}
return (
<Flex vertical gap={12}>
{ADDRESS_FIELDS.map(({ key, label, isCountry }) =>
isCountry ? (
<Flex key={key} gap={8} align='center'>
<CountrySelect
placeholder={`Select ${label.toLowerCase()}`}
value={address[key]}
onChange={(v) => handleFieldChange(key, v)}
disabled={disabled}
style={{ flex: 1 }}
alt={label}
/>
</Flex>
) : (
<Flex key={key} gap={8} align='center'>
<Input
placeholder={label}
value={address[key] ?? ''}
onChange={(e) => handleFieldChange(key, e.target.value)}
disabled={disabled}
style={{ flex: 1 }}
alt={label}
/>
</Flex>
)
)}
</Flex>
)
}
AddressDisplay.propTypes = {
value: PropTypes.shape({
building: PropTypes.string,
addressLine1: PropTypes.string,
addressLine2: PropTypes.string,
city: PropTypes.string,
state: PropTypes.string,
postcode: PropTypes.string,
country: PropTypes.string
}),
isEditing: PropTypes.bool,
onChange: PropTypes.func,
disabled: PropTypes.bool
}
export default AddressDisplay

View File

@ -46,6 +46,7 @@ import DataTree from './DataTree'
import FileList from './FileList'
import ObjectChildTable from './ObjectChildTable'
import MiscId from './MiscId'
import AddressDisplay from './AddressDisplay'
import { round } from '../utils/Utils'
const { Text } = Typography
@ -521,6 +522,15 @@ const ObjectProperty = ({
)
}
}
case 'address': {
return (
<AddressDisplay
value={value}
isEditing={false}
disabled={disabled}
/>
)
}
case 'operation': {
if (value != null) {
return <OperationDisplay operation={value} />
@ -777,6 +787,16 @@ const ObjectProperty = ({
return <ObjectSelect type={objectType} multiple {...inputProps} />
case 'tags':
return <TagsInput {...inputProps} />
case 'address':
return (
<AddressDisplay
value={value}
isEditing={true}
onChange={onChange}
disabled={disabled}
{...inputProps}
/>
)
case 'file':
return (
<FileUpload

View File

@ -170,51 +170,9 @@ export const Vendor = {
required: false
},
{
name: 'address.building',
label: 'Building',
type: 'text',
readOnly: false,
required: false
},
{
name: 'address.addressLine1',
label: 'Address Line 1',
type: 'text',
readOnly: false,
required: false
},
{
name: 'address.addressLine2',
label: 'Address Line 2',
type: 'text',
readOnly: false,
required: false
},
{
name: 'address.city',
label: 'City',
type: 'text',
readOnly: false,
required: false
},
{
name: 'address.state',
label: 'State',
type: 'text',
readOnly: false,
required: false
},
{
name: 'address.postcode',
label: 'Postcode',
type: 'text',
readOnly: false,
required: false
},
{
name: 'address.country',
label: 'Country',
type: 'country',
name: 'address',
label: 'Address',
type: 'address',
readOnly: false,
required: false
}