218 lines
7.8 KiB
TypeScript
218 lines
7.8 KiB
TypeScript
import {Autocomplete, Box, TextField, FormControlLabel, Checkbox, Typography} from '@mui/material'
|
||
import {Create, useAutocomplete} from '@refinedev/mui'
|
||
import {useForm} from '@refinedev/react-hook-form'
|
||
import {Controller} from 'react-hook-form'
|
||
|
||
export const RouteCreate = () => {
|
||
const {
|
||
saveButtonProps,
|
||
refineCore: {formLoading},
|
||
register,
|
||
control,
|
||
formState: {errors},
|
||
} = useForm({
|
||
refineCoreProps: {
|
||
resource: 'route/',
|
||
},
|
||
})
|
||
|
||
const {autocompleteProps: carrierAutocompleteProps} = useAutocomplete({
|
||
resource: 'carrier',
|
||
onSearch: (value) => [
|
||
{
|
||
field: 'short_name',
|
||
operator: 'contains',
|
||
value,
|
||
},
|
||
],
|
||
})
|
||
|
||
return (
|
||
<Create isLoading={formLoading} saveButtonProps={saveButtonProps}>
|
||
<Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off">
|
||
<Controller
|
||
control={control}
|
||
name="carrier_id"
|
||
rules={{required: 'Это поле является обязательным'}}
|
||
defaultValue={null}
|
||
render={({field}) => (
|
||
<Autocomplete
|
||
{...carrierAutocompleteProps}
|
||
value={carrierAutocompleteProps.options.find((option) => option.id === field.value) || null}
|
||
onChange={(_, value) => {
|
||
field.onChange(value?.id || '')
|
||
}}
|
||
getOptionLabel={(item) => {
|
||
return item ? item.short_name : ''
|
||
}}
|
||
isOptionEqualToValue={(option, value) => {
|
||
return option.id === value?.id
|
||
}}
|
||
filterOptions={(options, {inputValue}) => {
|
||
return options.filter((option) => option.short_name.toLowerCase().includes(inputValue.toLowerCase()))
|
||
}}
|
||
renderInput={(params) => <TextField {...params} label="Выберите перевозчика" margin="normal" variant="outlined" error={!!errors.carrier_id} helperText={(errors as any)?.carrier_id?.message} required />}
|
||
/>
|
||
)}
|
||
/>
|
||
|
||
<TextField
|
||
{...register('route_number', {
|
||
required: 'Это поле является обязательным',
|
||
setValueAs: (value) => String(value),
|
||
})}
|
||
error={!!(errors as any)?.route_number}
|
||
helperText={(errors as any)?.route_number?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{shrink: true}}
|
||
type="text"
|
||
label={'Номер маршрута *'}
|
||
name="route_number"
|
||
/>
|
||
|
||
<Controller
|
||
name="route_direction" // boolean
|
||
control={control}
|
||
defaultValue={false}
|
||
render={({field}: {field: any}) => <FormControlLabel label="Прямой маршрут? *" control={<Checkbox {...field} checked={field.value} onChange={(e) => field.onChange(e.target.checked)} />} />}
|
||
/>
|
||
<Typography variant="caption" color="textSecondary" sx={{mt: 0, mb: 1}}>
|
||
(Прямой / Обратный)
|
||
</Typography>
|
||
|
||
<TextField
|
||
{...register('path', {
|
||
required: 'Это поле является обязательным',
|
||
setValueAs: (value: string) => {
|
||
try {
|
||
// Парсим строку в массив массивов
|
||
return JSON.parse(value)
|
||
} catch {
|
||
return []
|
||
}
|
||
},
|
||
validate: (value: unknown) => {
|
||
if (!Array.isArray(value)) return 'Неверный формат'
|
||
if (!value.every((point: unknown) => Array.isArray(point) && point.length === 2)) {
|
||
return 'Каждая точка должна быть массивом из двух координат'
|
||
}
|
||
if (!value.every((point: unknown[]) => point.every((coord: unknown) => !isNaN(Number(coord)) && typeof coord === 'number'))) {
|
||
return 'Координаты должны быть числами'
|
||
}
|
||
return true
|
||
},
|
||
})}
|
||
error={!!(errors as any)?.path}
|
||
helperText={(errors as any)?.path?.message} // 'Формат: [[lat1,lon1], [lat2,lon2], ...]'
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{shrink: true}}
|
||
type="text"
|
||
label={'Координаты маршрута *'}
|
||
name="path"
|
||
placeholder="[[1.1, 2.2], [2.1, 4.5]]"
|
||
/>
|
||
|
||
<TextField
|
||
{...register('route_sys_number', {
|
||
required: 'Это поле является обязательным',
|
||
})}
|
||
error={!!(errors as any)?.route_sys_number}
|
||
helperText={(errors as any)?.route_sys_number?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{shrink: true}}
|
||
type="number"
|
||
label={'Системный номер маршрута *'}
|
||
name="route_sys_number"
|
||
/>
|
||
|
||
<TextField
|
||
{...register('governor_appeal', {
|
||
// required: 'Это поле является обязательным',
|
||
})}
|
||
error={!!(errors as any)?.governor_appeal}
|
||
helperText={(errors as any)?.governor_appeal?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{shrink: true}}
|
||
type="number"
|
||
label={'Обращение губернатора'}
|
||
name="governor_appeal"
|
||
/>
|
||
|
||
<TextField
|
||
{...register('scale_min', {
|
||
// required: 'Это поле является обязательным',
|
||
})}
|
||
error={!!(errors as any)?.scale_min}
|
||
helperText={(errors as any)?.scale_min?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{shrink: true}}
|
||
type="number"
|
||
label={'Масштаб (мин)'}
|
||
name="scale_min"
|
||
/>
|
||
|
||
<TextField
|
||
{...register('scale_max', {
|
||
// required: 'Это поле является обязательным',
|
||
})}
|
||
error={!!(errors as any)?.scale_max}
|
||
helperText={(errors as any)?.scale_max?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{shrink: true}}
|
||
type="number"
|
||
label={'Масштаб (макс)'}
|
||
name="scale_max"
|
||
/>
|
||
|
||
<TextField
|
||
{...register('rotate', {
|
||
// required: 'Это поле является обязательным',
|
||
})}
|
||
error={!!(errors as any)?.rotate}
|
||
helperText={(errors as any)?.rotate?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{shrink: true}}
|
||
type="number"
|
||
label={'Поворот'}
|
||
name="rotate"
|
||
/>
|
||
|
||
<TextField
|
||
{...register('center_latitude', {
|
||
// required: 'Это поле является обязательным',
|
||
})}
|
||
error={!!(errors as any)?.center_latitude}
|
||
helperText={(errors as any)?.center_latitude?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{shrink: true}}
|
||
type="number"
|
||
label={'Центр. широта'}
|
||
name="center_latitude"
|
||
/>
|
||
|
||
<TextField
|
||
{...register('center_longitude', {
|
||
// required: 'Это поле является обязательным',
|
||
})}
|
||
error={!!(errors as any)?.center_longitude}
|
||
helperText={(errors as any)?.center_longitude?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{shrink: true}}
|
||
type="number"
|
||
label={'Центр. долгота'}
|
||
name="center_longitude"
|
||
/>
|
||
</Box>
|
||
</Create>
|
||
)
|
||
}
|