diff --git a/src/App.tsx b/src/App.tsx index 5cd15ce..20eaf7d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -122,7 +122,6 @@ function App() { create: '/station/create', edit: '/station/edit/:id', show: '/station/show/:id', - // добавить SHOW для station->sight (https://wn.krbl.ru/station/2/sight) meta: { canDelete: true, label: 'Остановки', diff --git a/src/pages/sight/show.tsx b/src/pages/sight/show.tsx index 1beda1b..9300fef 100644 --- a/src/pages/sight/show.tsx +++ b/src/pages/sight/show.tsx @@ -39,7 +39,7 @@ export const SightShow = () => { useEffect(() => { axios - .get(`${BACKEND_URL}/article/`) + .get(`${BACKEND_URL}/article/`) // without "/" throws CORS error .then((response) => { setArticles(response?.data || []) setArticlesLoading(false) diff --git a/src/pages/station/show.tsx b/src/pages/station/show.tsx index 6734007..0fa2a55 100644 --- a/src/pages/station/show.tsx +++ b/src/pages/station/show.tsx @@ -1,13 +1,100 @@ -import {Stack, Typography} from '@mui/material' +import {Stack, Typography, Box, Grid2 as Grid, Button, MenuItem, Select, FormControl, InputLabel} 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} from '../../lib/constants' + +type SightItem = { + id: number + name: string + latitude: number + longitude: number + city_id: number +} + export const StationShow = () => { const {query} = useShow({}) const {data, isLoading} = query - const record = data?.data + const [sights, setSights] = useState([]) + const [linkedSights, setLinkedSights] = useState([]) + const [selectedSightId, setSelectedSightId] = useState('') + const [sightsLoading, setSightsLoading] = useState(true) + + useEffect(() => { + if (record?.id) { + axios + .get(`${BACKEND_URL}/station/${record.id}/sight`) + .then((response) => { + setLinkedSights(response?.data || []) + }) + .catch(() => { + setLinkedSights([]) + }) + } + }, [record?.id]) + + useEffect(() => { + axios + .get(`${BACKEND_URL}/sight/`) // without "/" throws CORS error + .then((response) => { + setSights(response?.data || []) + setSightsLoading(false) + }) + .catch(() => { + setSights([]) + setSightsLoading(false) + }) + }, []) + + const availableSights = sights.filter((sight) => !linkedSights.some((linked) => linked.id === sight.id)) + + const linkSight = () => { + if (selectedSightId) { + axios + .post( + `${BACKEND_URL}/station/${record?.id}/sight`, + {sight_id: selectedSightId}, + { + headers: { + accept: 'application/json', + 'Content-Type': 'application/json', + }, + }, + ) + .then(() => { + axios + .get(`${BACKEND_URL}/station/${record?.id}/sight`) + .then((response) => { + setLinkedSights(response?.data || []) + }) + .catch(() => { + setLinkedSights([]) + }) + }) + .catch((error) => { + console.error('Error linking sight:', error) + }) + } + } + + const deleteSight = (sightId: number) => { + axios + .delete(`${BACKEND_URL}/station/${record?.id}/sight`, { + data: {sight_id: sightId}, + }) + .then(() => { + setLinkedSights((prevSights) => prevSights.filter((item) => item.id !== sightId)) + }) + .catch((error) => { + console.error('Error deleting sight:', error) + }) + } + const fields = [ {label: 'ID', data: 'id'}, {label: 'Name', data: 'name'}, @@ -16,6 +103,14 @@ export const StationShow = () => { {label: 'Description', data: 'description'}, ] + const sightFields = [ + {label: 'ID', data: 'id' as keyof SightItem}, + {label: 'Name', data: 'name' as keyof SightItem}, + {label: 'Latitude', data: 'latitude' as keyof SightItem}, + {label: 'Longitude', data: 'longitude' as keyof SightItem}, + {label: 'City ID', data: 'city_id' as keyof SightItem}, + ] + return ( @@ -24,9 +119,60 @@ export const StationShow = () => { {label} - + ))} + + + + Linked Sights + + + + {sightsLoading ? ( + Loading sights... + ) : linkedSights.length > 0 ? ( + linkedSights.map((sight, index) => ( + + + {sightFields.map(({label, data}) => ( + + {label}: {sight?.[data]} + + ))} + + + + + )) + ) : ( + No sights found + )} + + + + + Link Sight + + + + Sight + + + + + + )