diff --git a/src/components/LinkedItems.tsx b/src/components/LinkedItems.tsx index af380db..8d0b5c3 100644 --- a/src/components/LinkedItems.tsx +++ b/src/components/LinkedItems.tsx @@ -104,7 +104,7 @@ export const LinkedItems = ({parentI - + {isLoading ? ( Загрузка... ) : linkedItems.length > 0 ? ( @@ -112,20 +112,20 @@ export const LinkedItems = ({parentI - + {fields.map(({label, data}) => ( - + {label}: {item[data]} ))} {type === 'edit' && ( - )} diff --git a/src/pages/route/edit.tsx b/src/pages/route/edit.tsx index 5a66217..a87193e 100644 --- a/src/pages/route/edit.tsx +++ b/src/pages/route/edit.tsx @@ -2,6 +2,9 @@ import {Autocomplete, Box, TextField, FormControlLabel, Checkbox, Typography} fr 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 {StationItem, VehicleItem, stationFields, vehicleFields} from './types' export const RouteEdit = () => { const { @@ -11,6 +14,8 @@ export const RouteEdit = () => { formState: {errors}, } = useForm({}) + const {id: routeId} = useParams<{id: string}>() + const {autocompleteProps: carrierAutocompleteProps} = useAutocomplete({ resource: 'carrier', }) @@ -107,6 +112,14 @@ export const RouteEdit = () => { )} /> + + {routeId && ( + <> + type="edit" parentId={routeId} parentResource="route" childResource="station" fields={stationFields} title="станции" /> + + type="edit" parentId={routeId} parentResource="route" childResource="vehicle" fields={vehicleFields} title="транспортные средства" /> + + )} ) } diff --git a/src/pages/route/show.tsx b/src/pages/route/show.tsx index 775cfd0..7f63db2 100644 --- a/src/pages/route/show.tsx +++ b/src/pages/route/show.tsx @@ -1,182 +1,14 @@ -import {Stack, Typography, Box, Grid2 as Grid, Button, MenuItem, Select, FormControl, InputLabel} from '@mui/material' +import {Stack, Typography, Box} from '@mui/material' import {useShow} from '@refinedev/core' import {Show, TextFieldComponent as TextField} from '@refinedev/mui' -import {useEffect, useState} from 'react' -import axios from 'axios' -import {BACKEND_URL, VEHICLE_TYPES} from '../../lib/constants' - -type StationItem = { - id: number - name: string - description: string - [key: string]: string | number -} - -type VehicleItem = { - id: number - tail_number: number - type: number - [key: string]: string | number -} +import {LinkedItems} from '../../components/LinkedItems' +import {StationItem, VehicleItem, stationFields, vehicleFields} from './types' export const RouteShow = () => { const {query} = useShow({}) const {data, isLoading} = query const record = data?.data - // Station states - const [stations, setStations] = useState([]) - const [linkedStations, setLinkedStations] = useState([]) - const [selectedStationId, setSelectedStationId] = useState('') - const [stationsLoading, setStationsLoading] = useState(true) - - // Vehicle states - const [vehicles, setVehicles] = useState([]) - const [linkedVehicles, setLinkedVehicles] = useState([]) - const [selectedVehicleId, setSelectedVehicleId] = useState('') - const [vehiclesLoading, setVehiclesLoading] = useState(true) - - useEffect(() => { - if (record?.id) { - axios - .get(`${BACKEND_URL}/route/${record.id}/station`) - .then((response) => { - setLinkedStations(response?.data || []) - }) - .catch(() => { - setLinkedStations([]) - }) - } - }, [record?.id]) - - useEffect(() => { - axios - .get(`${BACKEND_URL}/station/`) - .then((response) => { - setStations(response?.data || []) - setStationsLoading(false) - }) - .catch(() => { - setStations([]) - setStationsLoading(false) - }) - }, []) - - const availableStations = stations.filter((station) => !linkedStations.some((linked) => linked.id === station.id)) - - const linkStation = () => { - if (selectedStationId) { - axios - .post( - `${BACKEND_URL}/route/${record?.id}/station`, - {station_id: selectedStationId}, - { - headers: { - accept: 'application/json', - 'Content-Type': 'application/json', - }, - }, - ) - .then(() => { - axios - .get(`${BACKEND_URL}/route/${record?.id}/station`) - .then((response) => { - setLinkedStations(response?.data || []) - }) - .catch(() => { - setLinkedStations([]) - }) - }) - .catch((error) => { - console.error('Error linking station:', error) - }) - } - } - - const deleteStation = (stationId: number) => { - axios - .delete(`${BACKEND_URL}/route/${record?.id}/station`, { - data: {station_id: stationId}, - }) - .then(() => { - setLinkedStations((prevStations) => prevStations.filter((item) => item.id !== stationId)) - }) - .catch((error) => { - console.error('Error deleting station:', error) - }) - } - - // Vehicle effects - useEffect(() => { - if (record?.id) { - axios - .get(`${BACKEND_URL}/route/${record.id}/vehicle`) - .then((response) => { - setLinkedVehicles(response?.data || []) - }) - .catch(() => { - setLinkedVehicles([]) - }) - } - }, [record?.id]) - - useEffect(() => { - axios - .get(`${BACKEND_URL}/vehicle/`) - .then((response) => { - setVehicles(response?.data || []) - setVehiclesLoading(false) - }) - .catch(() => { - setVehicles([]) - setVehiclesLoading(false) - }) - }, []) - - const availableVehicles = vehicles.filter((vehicle) => !linkedVehicles.some((linked) => linked.id === vehicle.id)) - - const linkVehicle = () => { - if (selectedVehicleId) { - axios - .post( - `${BACKEND_URL}/route/${record?.id}/vehicle`, - {vehicle_id: selectedVehicleId}, - { - headers: { - accept: 'application/json', - 'Content-Type': 'application/json', - }, - }, - ) - .then(() => { - axios - .get(`${BACKEND_URL}/route/${record?.id}/vehicle`) - .then((response) => { - setLinkedVehicles(response?.data || []) - }) - .catch(() => { - setLinkedVehicles([]) - }) - }) - .catch((error) => { - console.error('Error linking vehicle:', error) - }) - } - } - - const deleteVehicle = (vehicleId: number) => { - axios - .delete(`${BACKEND_URL}/route/${record?.id}/vehicle`, { - data: {vehicle_id: vehicleId}, - }) - .then(() => { - setLinkedVehicles((prevVehicles) => prevVehicles.filter((item) => item.id !== vehicleId)) - }) - .catch((error) => { - console.error('Error deleting vehicle:', error) - }) - } - const fields = [ {label: 'Перевозчик', data: 'carrier'}, {label: 'Номер маршрута', data: 'route_number'}, @@ -204,16 +36,6 @@ export const RouteShow = () => { }, ] - const stationFields: Array<{label: string; data: keyof StationItem}> = [ - {label: 'Название', data: 'name'}, - {label: 'Описание', data: 'description'}, - ] - - const vehicleFields: Array<{label: string; data: keyof VehicleItem}> = [ - {label: 'Бортовой номер', data: 'tail_number'}, - {label: 'Тип', data: 'type'}, - ] - return ( @@ -226,123 +48,13 @@ export const RouteShow = () => { ))} - - - Привязанные станции - + {record?.id && ( + <> + type="show" parentId={record.id} parentResource="route" childResource="station" fields={stationFields} title="станции" /> - - {stationsLoading ? ( - Загрузка станций... - ) : linkedStations.length > 0 ? ( - linkedStations.map((station, index) => ( - `2px solid ${theme.palette.divider}`, - }} - > - - {stationFields.map(({label, data}) => ( - - {label}: {station[data]} - - ))} - - - - - )) - ) : ( - Станции не найдены - )} - - - - - Привязать станцию - - - - Станция - - - - - - - - - - Привязанные транспортные средства - - - - {vehiclesLoading ? ( - Загрузка транспорта... - ) : linkedVehicles.length > 0 ? ( - linkedVehicles.map((vehicle, index) => ( - `2px solid ${theme.palette.divider}`, - }} - > - - {vehicleFields.map(({label, data}) => ( - - {label}: {vehicle[data]} - - ))} - - - - - )) - ) : ( - Транспортные средства не найдены - )} - - - - - Привязать транспортное средство - - - - Транспортное средство - - - - - - + type="show" parentId={record.id} parentResource="route" childResource="vehicle" fields={vehicleFields} title="транспортные средства" /> + + )} ) diff --git a/src/pages/route/types.ts b/src/pages/route/types.ts new file mode 100644 index 0000000..f296105 --- /dev/null +++ b/src/pages/route/types.ts @@ -0,0 +1,35 @@ +import {VEHICLE_TYPES} from '../../lib/constants' + +export type StationItem = { + id: number + name: string + description: string + [key: string]: string | number +} + +export type VehicleItem = { + id: number + tail_number: number + type: number + [key: string]: string | number +} + +export type FieldType = { + label: string + data: keyof T + render?: (value: any) => React.ReactNode +} + +export const stationFields: Array> = [ + {label: 'Название', data: 'name'}, + {label: 'Описание', data: 'description'}, +] + +export const vehicleFields: Array> = [ + {label: 'Бортовой номер', data: 'tail_number'}, + { + label: 'Тип', + data: 'type', + render: (value: number) => VEHICLE_TYPES.find((type) => type.value === value)?.label || value, + }, +]