/
edit.tsx
96 lines (85 loc) · 2.84 KB
/
edit.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import React, { FC, useState, useEffect } from 'react'
import Select from 'react-select/async'
import { withTheme, DefaultTheme } from 'styled-components'
import { FormGroup, FormMessage, selectStyles } from '@admin-bro/design-system'
import ApiClient from '../../../utils/api-client'
import { EditPropertyProps, SelectRecord } from '../base-property-props'
import { RecordJSON } from '../../../interfaces'
import { PropertyLabel } from '../utils/property-label'
type CombinedProps = EditPropertyProps & {theme: DefaultTheme}
type SelectRecordEnhanced = SelectRecord & {
record: RecordJSON;
}
const Edit: FC<CombinedProps> = (props) => {
const { onChange, property, record, theme } = props
const { reference: resourceId } = property
if (!resourceId) {
throw new Error(`Cannot reference resource in property '${property.path}'`)
}
const handleChange = (selected: SelectRecordEnhanced): void => {
if (selected) {
onChange(property.path, selected.value, selected.record)
} else {
onChange(property.path, null)
}
}
const loadOptions = async (inputValue: string): Promise<SelectRecordEnhanced[]> => {
const api = new ApiClient()
const optionRecords = await api.searchRecords({
resourceId,
query: inputValue,
})
return optionRecords.map((optionRecord: RecordJSON) => ({
value: optionRecord.id,
label: optionRecord.title,
record: optionRecord,
}))
}
const error = record?.errors[property.path]
const selectedId = record?.params[property.path] as string | undefined
const [loadedRecord, setLoadedRecord] = useState<RecordJSON | undefined>()
const [loadingRecord, setLoadingRecord] = useState(0)
const selectedValue = record?.populated[property.path] ?? loadedRecord
const selectedOption = (selectedId && selectedValue) ? {
value: selectedValue.id,
label: selectedValue.title,
} : {
value: '',
label: '',
}
const styles = selectStyles(theme)
useEffect(() => {
if (!selectedValue && selectedId) {
setLoadingRecord(c => c + 1)
const api = new ApiClient()
api.recordAction({
actionName: 'show',
resourceId,
recordId: selectedId,
}).then(({ data }: any) => {
setLoadedRecord(data.record)
}).finally(() => {
setLoadingRecord(c => c - 1)
})
}
}, [selectedValue, selectedId, resourceId])
return (
<FormGroup error={Boolean(error)}>
<PropertyLabel property={property} />
<Select
cacheOptions
value={selectedOption}
styles={styles}
defaultOptions
loadOptions={loadOptions}
onChange={handleChange}
isClearable
isDisabled={property.isDisabled}
isLoading={loadingRecord}
{...property.props}
/>
<FormMessage>{error?.message}</FormMessage>
</FormGroup>
)
}
export default withTheme(Edit)