Fix boolean handling and read-mode display value functionality in dropdown & radiobutton

This commit is contained in:
arttu
2024-06-07 14:27:24 +03:00
parent 5c7e7b8f80
commit 23f76b2e54
3 changed files with 48 additions and 39 deletions
@@ -24,6 +24,20 @@ const fieldWidth = '14em'
export type DropdownOptionValue = string | number
export type DropdownOption = { value: DropdownOptionValue; display: string }
const setDropdownOptionValue = (
setValue: (val: string | number | boolean) => void,
value: string | undefined,
asNumber: boolean
) => {
if (value && asNumber) {
setValue(parseInt(value))
} else if (value === 'true' || value === 'false') {
setValue(value === 'true')
} else {
setValue(value ?? '')
}
}
export const DropdownSelector = <T extends object>({
options,
name,
@@ -43,8 +57,12 @@ export const DropdownSelector = <T extends object>({
labelId={`${name}-multiselect-label`}
label={name}
id={`${name}-multiselect`}
value={(editData[field] || '') as string}
onChange={(event: SelectChangeEvent) => setEditData({ ...editData, [field]: event.target.value })}
value={editData[field] as string}
onChange={(event: SelectChangeEvent) => {
const setValue = (value: number | string | boolean) => setEditData({ ...editData, [field]: value })
const asNumber = typeof options[0] === 'number'
setDropdownOptionValue(setValue, event?.target?.value, asNumber)
}}
sx={{ width: fieldWidth, backgroundColor: disabled ? 'grey' : '' }}
size="small"
disabled={disabled}
@@ -95,6 +113,7 @@ const getDisplay = (item: DropdownOption | DropdownOptionValue) => (typeof item
This also means that the options cannot be 'true' or 'false' if you want
to actually write those as strings to database. If that is required, this
needs to be changed.
ALSO: All options have to be of same type! This isn't enforced with types.
*/
export const RadioSelector = <T extends object>({
options,
@@ -112,15 +131,9 @@ export const RadioSelector = <T extends object>({
aria-labelledby={`${name}-radio-selection`}
name={name}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
const value = event?.currentTarget?.value
const setValue = (val: string | number | boolean) => setEditData({ ...editData, [field]: val })
if (value && typeof getValue(options[0]) === 'number') {
setValue(parseInt(value))
} else if (value === 'true' || value === 'false') {
setValue(value === 'true')
} else {
setEditData({ ...editData, [field]: value })
}
const setValue = (value: number | string | boolean) => setEditData({ ...editData, [field]: value })
const asNumber = typeof options[0] === 'number'
setDropdownOptionValue(setValue, event?.currentTarget?.value, asNumber)
}}
value={editData[field]}
sx={{ display: 'flex', flexDirection: 'row' }}
@@ -150,7 +163,8 @@ const MultiSelector = <T extends object>({
editingComponent: ReactNode
}) => {
const { data } = useDetailContext<T>()
const option = options.find(option => getValue(option) == data[field as keyof T]) // TODO intentional use of == but is it necessary anymore
const valueInField = data[field as keyof T]
const option = options.find(option => getValue(option) === valueInField || getValue(option) === valueInField + '')
const displayValue = option ? getDisplay(option) : null
return <DataValue<T> field={field} EditElement={editingComponent} displayValue={displayValue} />
}
@@ -8,9 +8,12 @@ import { EditableTable } from '@/components/DetailView/common/EditableTable'
import { EditingModal } from '@/components/DetailView/common/EditingModal'
export const LocalityTab = () => {
const { data, textField, radioSelection, dropdown, mode, bigTextField } = useDetailContext<LocalityDetailsType>()
const { textField, radioSelection, dropdown, mode, bigTextField } = useDetailContext<LocalityDetailsType>()
const approximateCoordinatesOptions = ['', { display: 'No', value: '0' }, { display: 'Yes', value: '1' }]
const approximateCoordinatesOptions = [
{ display: 'No', value: 'false' },
{ display: 'Yes', value: 'true' },
]
const generalLocalityOptions = ['', { display: 'No', value: 'n' }, { display: 'Yes', value: 'y' }]
const siteAreaOptions = [
@@ -22,22 +25,18 @@ export const LocalityTab = () => {
{ display: '>1000 m2', value: '>1000m2' },
]
const getStatusText = () => (data.loc_status ? <>Draft</> : <>Public</>)
const info = [
['Name', textField('loc_name')],
[
'Visibility status',
!mode.read
? radioSelection(
'loc_status',
[
{ value: 'false', display: 'Public' },
{ value: 'true', display: 'Draft' },
],
'Status'
)
: getStatusText(),
radioSelection(
'loc_status',
[
{ value: 'false', display: 'Public' },
{ value: 'true', display: 'Draft' },
],
'Status'
),
],
]
const country = [
@@ -5,9 +5,7 @@ import { MRT_ColumnDef } from 'material-react-table'
import { EditableTable } from '@/components/DetailView/common/EditableTable'
export const CoordinatorTab = () => {
const { data, editData, mode, radioSelection, textField } = useDetailContext<ProjectDetailsType>()
const getStatusText = () => (data.proj_records ? <>Private</> : <>Public</>)
const { editData, radioSelection, textField } = useDetailContext<ProjectDetailsType>()
const projectInformation = [
['Project Id', textField('pid')],
@@ -28,16 +26,14 @@ export const CoordinatorTab = () => {
],
[
'Record Status',
!mode.read
? radioSelection(
'proj_records',
[
{ value: 'false', display: 'Public' },
{ value: 'true', display: 'Private' },
],
'Record Status'
)
: getStatusText(),
radioSelection(
'proj_records',
[
{ value: 'false', display: 'Public' },
{ value: 'true', display: 'Private' },
],
'Record Status'
),
],
]