add new props for /station route

This commit is contained in:
maxim 2025-04-06 23:16:24 +03:00
parent af5e8adc3c
commit b105bfe395
4 changed files with 219 additions and 5 deletions

View File

@ -12,7 +12,7 @@ interface CustomDataGridProps extends DataGridProps {
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) => {
// const isDev = import.meta.env.DEV

View File

@ -1,12 +1,26 @@
import {Box, TextField} from '@mui/material'
import {Create} from '@refinedev/mui'
import {Autocomplete, Box, TextField, Typography, Paper, Grid} from '@mui/material'
import {Create, useAutocomplete} from '@refinedev/mui'
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 = () => {
const {
saveButtonProps,
refineCore: {formLoading},
register,
control,
formState: {errors},
} = useForm({
refineCoreProps: {
@ -14,6 +28,17 @@ export const StationCreate = () => {
},
})
const {autocompleteProps: cityAutocompleteProps} = useAutocomplete({
resource: 'city',
onSearch: (value) => [
{
field: 'name',
operator: 'contains',
value,
},
],
})
return (
<Create isLoading={formLoading} saveButtonProps={saveButtonProps}>
<Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off">
@ -84,6 +109,74 @@ export const StationCreate = () => {
label={'Долгота *'}
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>
</Create>
)

View File

@ -1,19 +1,45 @@
import {Box, TextField} from '@mui/material'
import {Edit} from '@refinedev/mui'
import {Autocomplete, Box, TextField, Typography, Paper, Grid} from '@mui/material'
import {Edit, useAutocomplete} from '@refinedev/mui'
import {useForm} from '@refinedev/react-hook-form'
import {Controller} from 'react-hook-form'
import {useParams} from 'react-router'
import {LinkedItems} from '../../components/LinkedItems'
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 = () => {
const {
saveButtonProps,
register,
control,
formState: {errors},
} = useForm({})
const {id: stationId} = useParams<{id: string}>()
const {autocompleteProps: cityAutocompleteProps} = useAutocomplete({
resource: 'city',
onSearch: (value) => [
{
field: 'name',
operator: 'contains',
value,
},
],
})
return (
<Edit saveButtonProps={saveButtonProps}>
<Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off">
@ -84,6 +110,74 @@ export const StationEdit = () => {
label={'Долгота *'}
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>
{stationId && (

View File

@ -55,6 +55,33 @@ export const StationList = () => {
align: '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',
headerName: 'Описание',