add new props for /station
route
This commit is contained in:
parent
af5e8adc3c
commit
b105bfe395
@ -12,7 +12,7 @@ interface CustomDataGridProps extends DataGridProps {
|
|||||||
resource?: string // Add this prop
|
resource?: string // Add this prop
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEV_FIELDS = ['id', 'code', 'country_code', 'city_id', 'carrier_id', 'main_color', 'left_color', 'right_color', 'logo', 'slogan', 'filename', 'arms', 'thumbnail', 'route_sys_number', 'governor_appeal', 'scale_min', 'scale_max', 'rotate', 'center_latitude', 'center_longitude', 'watermark_lu', 'watermark_rd', 'left_article', 'preview_article'] as const
|
const DEV_FIELDS = ['id', 'code', 'country_code', 'city_id', 'carrier_id', 'main_color', 'left_color', 'right_color', 'logo', 'slogan', 'filename', 'arms', 'thumbnail', 'route_sys_number', 'governor_appeal', 'scale_min', 'scale_max', 'rotate', 'center_latitude', 'center_longitude', 'watermark_lu', 'watermark_rd', 'left_article', 'preview_article', 'offset_x', 'offset_y'] as const
|
||||||
|
|
||||||
export const CustomDataGrid = ({hasCoordinates = false, columns = [], resource, ...props}: CustomDataGridProps) => {
|
export const CustomDataGrid = ({hasCoordinates = false, columns = [], resource, ...props}: CustomDataGridProps) => {
|
||||||
// const isDev = import.meta.env.DEV
|
// const isDev = import.meta.env.DEV
|
||||||
|
@ -1,12 +1,26 @@
|
|||||||
import {Box, TextField} from '@mui/material'
|
import {Autocomplete, Box, TextField, Typography, Paper, Grid} from '@mui/material'
|
||||||
import {Create} from '@refinedev/mui'
|
import {Create, useAutocomplete} from '@refinedev/mui'
|
||||||
import {useForm} from '@refinedev/react-hook-form'
|
import {useForm} from '@refinedev/react-hook-form'
|
||||||
|
import {Controller} from 'react-hook-form'
|
||||||
|
|
||||||
|
const TRANSFER_FIELDS = [
|
||||||
|
{name: 'bus', label: 'Автобус'},
|
||||||
|
{name: 'metro_blue', label: 'Метро (синяя)'},
|
||||||
|
{name: 'metro_green', label: 'Метро (зеленая)'},
|
||||||
|
{name: 'metro_orange', label: 'Метро (оранжевая)'},
|
||||||
|
{name: 'metro_purple', label: 'Метро (фиолетовая)'},
|
||||||
|
{name: 'metro_red', label: 'Метро (красная)'},
|
||||||
|
{name: 'train', label: 'Электричка'},
|
||||||
|
{name: 'tram', label: 'Трамвай'},
|
||||||
|
{name: 'trolleybus', label: 'Троллейбус'},
|
||||||
|
]
|
||||||
|
|
||||||
export const StationCreate = () => {
|
export const StationCreate = () => {
|
||||||
const {
|
const {
|
||||||
saveButtonProps,
|
saveButtonProps,
|
||||||
refineCore: {formLoading},
|
refineCore: {formLoading},
|
||||||
register,
|
register,
|
||||||
|
control,
|
||||||
formState: {errors},
|
formState: {errors},
|
||||||
} = useForm({
|
} = useForm({
|
||||||
refineCoreProps: {
|
refineCoreProps: {
|
||||||
@ -14,6 +28,17 @@ export const StationCreate = () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const {autocompleteProps: cityAutocompleteProps} = useAutocomplete({
|
||||||
|
resource: 'city',
|
||||||
|
onSearch: (value) => [
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
operator: 'contains',
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Create isLoading={formLoading} saveButtonProps={saveButtonProps}>
|
<Create isLoading={formLoading} saveButtonProps={saveButtonProps}>
|
||||||
<Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off">
|
<Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off">
|
||||||
@ -84,6 +109,74 @@ export const StationCreate = () => {
|
|||||||
label={'Долгота *'}
|
label={'Долгота *'}
|
||||||
name="longitude"
|
name="longitude"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="city_id"
|
||||||
|
rules={{required: 'Это поле является обязательным'}}
|
||||||
|
defaultValue={null}
|
||||||
|
render={({field}) => (
|
||||||
|
<Autocomplete
|
||||||
|
{...cityAutocompleteProps}
|
||||||
|
value={cityAutocompleteProps.options.find((option) => option.id === field.value) || null}
|
||||||
|
onChange={(_, value) => {
|
||||||
|
field.onChange(value?.id || '')
|
||||||
|
}}
|
||||||
|
getOptionLabel={(item) => {
|
||||||
|
return item ? item.name : ''
|
||||||
|
}}
|
||||||
|
isOptionEqualToValue={(option, value) => {
|
||||||
|
return option.id === value?.id
|
||||||
|
}}
|
||||||
|
filterOptions={(options, {inputValue}) => {
|
||||||
|
return options.filter((option) => option.name.toLowerCase().includes(inputValue.toLowerCase()))
|
||||||
|
}}
|
||||||
|
renderInput={(params) => <TextField {...params} label="Выберите город" margin="normal" variant="outlined" error={!!errors.city_id} helperText={(errors as any)?.city_id?.message} required />}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
{...register('offset_x', {
|
||||||
|
// required: 'Это поле является обязательным',
|
||||||
|
})}
|
||||||
|
error={!!(errors as any)?.offset_x}
|
||||||
|
helperText={(errors as any)?.offset_x?.message}
|
||||||
|
margin="normal"
|
||||||
|
fullWidth
|
||||||
|
InputLabelProps={{shrink: true}}
|
||||||
|
type="number"
|
||||||
|
label={'Смещение (X)'}
|
||||||
|
name="offset_x"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
{...register('offset_y', {
|
||||||
|
// required: 'Это поле является обязательным',
|
||||||
|
})}
|
||||||
|
error={!!(errors as any)?.offset_y}
|
||||||
|
helperText={(errors as any)?.offset_y?.message}
|
||||||
|
margin="normal"
|
||||||
|
fullWidth
|
||||||
|
InputLabelProps={{shrink: true}}
|
||||||
|
type="number"
|
||||||
|
label={'Смещение (Y)'}
|
||||||
|
name="offset_y"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Группа полей пересадок */}
|
||||||
|
<Paper sx={{p: 2, mt: 2}}>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
Пересадки
|
||||||
|
</Typography>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
{TRANSFER_FIELDS.map((field) => (
|
||||||
|
<Grid item xs={12} sm={6} md={4} key={field.name}>
|
||||||
|
<TextField {...register(`transfers.${field.name}`)} error={!!(errors as any)?.transfers?.[field.name]} helperText={(errors as any)?.transfers?.[field.name]?.message} margin="normal" fullWidth InputLabelProps={{shrink: true}} type="text" label={field.label} name={`transfers.${field.name}`} />
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
</Create>
|
</Create>
|
||||||
)
|
)
|
||||||
|
@ -1,19 +1,45 @@
|
|||||||
import {Box, TextField} from '@mui/material'
|
import {Autocomplete, Box, TextField, Typography, Paper, Grid} from '@mui/material'
|
||||||
import {Edit} from '@refinedev/mui'
|
import {Edit, useAutocomplete} from '@refinedev/mui'
|
||||||
import {useForm} from '@refinedev/react-hook-form'
|
import {useForm} from '@refinedev/react-hook-form'
|
||||||
|
import {Controller} from 'react-hook-form'
|
||||||
|
|
||||||
import {useParams} from 'react-router'
|
import {useParams} from 'react-router'
|
||||||
import {LinkedItems} from '../../components/LinkedItems'
|
import {LinkedItems} from '../../components/LinkedItems'
|
||||||
import {type SightItem, sightFields} from './types'
|
import {type SightItem, sightFields} from './types'
|
||||||
|
|
||||||
|
const TRANSFER_FIELDS = [
|
||||||
|
{name: 'bus', label: 'Автобус'},
|
||||||
|
{name: 'metro_blue', label: 'Метро (синяя)'},
|
||||||
|
{name: 'metro_green', label: 'Метро (зеленая)'},
|
||||||
|
{name: 'metro_orange', label: 'Метро (оранжевая)'},
|
||||||
|
{name: 'metro_purple', label: 'Метро (фиолетовая)'},
|
||||||
|
{name: 'metro_red', label: 'Метро (красная)'},
|
||||||
|
{name: 'train', label: 'Электричка'},
|
||||||
|
{name: 'tram', label: 'Трамвай'},
|
||||||
|
{name: 'trolleybus', label: 'Троллейбус'},
|
||||||
|
]
|
||||||
|
|
||||||
export const StationEdit = () => {
|
export const StationEdit = () => {
|
||||||
const {
|
const {
|
||||||
saveButtonProps,
|
saveButtonProps,
|
||||||
register,
|
register,
|
||||||
|
control,
|
||||||
formState: {errors},
|
formState: {errors},
|
||||||
} = useForm({})
|
} = useForm({})
|
||||||
|
|
||||||
const {id: stationId} = useParams<{id: string}>()
|
const {id: stationId} = useParams<{id: string}>()
|
||||||
|
|
||||||
|
const {autocompleteProps: cityAutocompleteProps} = useAutocomplete({
|
||||||
|
resource: 'city',
|
||||||
|
onSearch: (value) => [
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
operator: 'contains',
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Edit saveButtonProps={saveButtonProps}>
|
<Edit saveButtonProps={saveButtonProps}>
|
||||||
<Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off">
|
<Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off">
|
||||||
@ -84,6 +110,74 @@ export const StationEdit = () => {
|
|||||||
label={'Долгота *'}
|
label={'Долгота *'}
|
||||||
name="longitude"
|
name="longitude"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="city_id"
|
||||||
|
rules={{required: 'Это поле является обязательным'}}
|
||||||
|
defaultValue={null}
|
||||||
|
render={({field}) => (
|
||||||
|
<Autocomplete
|
||||||
|
{...cityAutocompleteProps}
|
||||||
|
value={cityAutocompleteProps.options.find((option) => option.id === field.value) || null}
|
||||||
|
onChange={(_, value) => {
|
||||||
|
field.onChange(value?.id || '')
|
||||||
|
}}
|
||||||
|
getOptionLabel={(item) => {
|
||||||
|
return item ? item.name : ''
|
||||||
|
}}
|
||||||
|
isOptionEqualToValue={(option, value) => {
|
||||||
|
return option.id === value?.id
|
||||||
|
}}
|
||||||
|
filterOptions={(options, {inputValue}) => {
|
||||||
|
return options.filter((option) => option.name.toLowerCase().includes(inputValue.toLowerCase()))
|
||||||
|
}}
|
||||||
|
renderInput={(params) => <TextField {...params} label="Выберите город" margin="normal" variant="outlined" error={!!errors.city_id} helperText={(errors as any)?.city_id?.message} required />}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
{...register('offset_x', {
|
||||||
|
// required: 'Это поле является обязательным',
|
||||||
|
})}
|
||||||
|
error={!!(errors as any)?.offset_x}
|
||||||
|
helperText={(errors as any)?.offset_x?.message}
|
||||||
|
margin="normal"
|
||||||
|
fullWidth
|
||||||
|
InputLabelProps={{shrink: true}}
|
||||||
|
type="number"
|
||||||
|
label={'Смещение (X)'}
|
||||||
|
name="offset_x"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
{...register('offset_y', {
|
||||||
|
// required: 'Это поле является обязательным',
|
||||||
|
})}
|
||||||
|
error={!!(errors as any)?.offset_y}
|
||||||
|
helperText={(errors as any)?.offset_y?.message}
|
||||||
|
margin="normal"
|
||||||
|
fullWidth
|
||||||
|
InputLabelProps={{shrink: true}}
|
||||||
|
type="number"
|
||||||
|
label={'Смещение (Y)'}
|
||||||
|
name="offset_y"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Группа полей пересадок */}
|
||||||
|
<Paper sx={{p: 2, mt: 2}}>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
Пересадки
|
||||||
|
</Typography>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
{TRANSFER_FIELDS.map((field) => (
|
||||||
|
<Grid item xs={12} sm={6} md={4} key={field.name}>
|
||||||
|
<TextField {...register(`transfers.${field.name}`)} error={!!(errors as any)?.transfers?.[field.name]} helperText={(errors as any)?.transfers?.[field.name]?.message} margin="normal" fullWidth InputLabelProps={{shrink: true}} type="text" label={field.label} name={`transfers.${field.name}`} />
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{stationId && (
|
{stationId && (
|
||||||
|
@ -55,6 +55,33 @@ export const StationList = () => {
|
|||||||
align: 'left',
|
align: 'left',
|
||||||
headerAlign: 'left',
|
headerAlign: 'left',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: 'city_id',
|
||||||
|
headerName: 'ID города',
|
||||||
|
type: 'number',
|
||||||
|
minWidth: 120,
|
||||||
|
display: 'flex',
|
||||||
|
align: 'left',
|
||||||
|
headerAlign: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'offset_x',
|
||||||
|
headerName: 'Смещение (X)',
|
||||||
|
type: 'number',
|
||||||
|
minWidth: 120,
|
||||||
|
display: 'flex',
|
||||||
|
align: 'left',
|
||||||
|
headerAlign: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'offset_y',
|
||||||
|
headerName: 'Смещение (Y)',
|
||||||
|
type: 'number',
|
||||||
|
minWidth: 120,
|
||||||
|
display: 'flex',
|
||||||
|
align: 'left',
|
||||||
|
headerAlign: 'left',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'description',
|
field: 'description',
|
||||||
headerName: 'Описание',
|
headerName: 'Описание',
|
||||||
|
Loading…
Reference in New Issue
Block a user