WhiteNightsAdminPanel/src/pages/sight/show.tsx

178 lines
5.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {Stack, Typography, Box, Grid2 as Grid, Button, MenuItem, Select, FormControl, InputLabel, TextField} from '@mui/material'
import {useShow} from '@refinedev/core'
import {Show, TextFieldComponent} from '@refinedev/mui'
import {useEffect, useState} from 'react'
import axios from 'axios'
import {BACKEND_URL} from '../../lib/constants'
type ArticleItem = {
id: number
heading: string
body: string
}
export const SightShow = () => {
const {query} = useShow({})
const {data, isLoading} = query
const record = data?.data
const [articles, setArticles] = useState<ArticleItem[]>([])
const [linkedArticles, setLinkedArticles] = useState<ArticleItem[]>([])
const [selectedArticleId, setSelectedArticleId] = useState<number | ''>('')
const [pageNum, setPageNum] = useState<number>(1)
const [articlesLoading, setArticlesLoading] = useState<boolean>(true)
useEffect(() => {
if (record?.id) {
axios
.get(`${BACKEND_URL}/sight/${record.id}/article`)
.then((response) => {
setLinkedArticles(response?.data || [])
})
.catch(() => {
setLinkedArticles([])
})
}
}, [record?.id])
useEffect(() => {
axios
.get(`${BACKEND_URL}/article/`) // without "/" throws CORS error
.then((response) => {
setArticles(response?.data || [])
setArticlesLoading(false)
})
.catch(() => {
setArticles([])
setArticlesLoading(false)
})
}, [])
const availableArticles = articles.filter((article) => !linkedArticles.some((linked) => linked.id === article.id))
const linkArticle = () => {
if (selectedArticleId) {
const requestData = {
article_id: selectedArticleId,
page_num: pageNum,
}
axios
.post(`${BACKEND_URL}/sight/${record?.id}/article`, requestData, {
headers: {
accept: 'application/json',
'Content-Type': 'application/json',
},
})
.then(() => {
axios
.get(`${BACKEND_URL}/sight/${record?.id}/article`)
.then((response) => {
setLinkedArticles(response?.data || [])
setPageNum(pageNum + 1)
})
.catch(() => {
setLinkedArticles([])
})
})
.catch((error) => {
console.error('Error linking article:', error)
})
}
}
const deleteArticle = (articleId: number) => {
axios
.delete(`${BACKEND_URL}/sight/${record?.id}/article`, {
data: {article_id: articleId},
})
.then(() => {
setLinkedArticles((prev) => prev.filter((item) => item.id !== articleId))
})
.catch((error) => {
console.error('Error unlinking article:', error)
})
}
const fields = [
// {label: 'ID', data: 'id'},
{label: 'Название', data: 'name'},
{label: 'Широта', data: 'latitude'},
{label: 'Долгота', data: 'longitude'},
{label: 'ID города', data: 'city_id'},
]
return (
<Show isLoading={isLoading}>
<Stack gap={4}>
{fields.map(({label, data}) => (
<Stack key={data} gap={1}>
<Typography variant="body1" fontWeight="bold">
{label}
</Typography>
<TextFieldComponent value={record?.[data]} />
</Stack>
))}
<Stack gap={2}>
<Typography variant="body1" fontWeight="bold">
Привязанные статьи
</Typography>
<Grid container gap={2}>
{articlesLoading ? (
<Typography>Загрузка статей...</Typography>
) : linkedArticles.length > 0 ? (
linkedArticles.map((article) => (
<Box key={article.id} sx={{border: '2px solid #dddddd25', padding: '20px', marginBottom: '8px'}}>
<Stack gap={1}>
<Typography variant="h5">
<strong>{article.heading}</strong>
</Typography>
<Typography>{article.body}</Typography>
<Button variant="outlined" color="error" onClick={() => deleteArticle(article.id)} sx={{mt: 2}}>
Отвязать статью
</Button>
</Stack>
</Box>
))
) : (
<Typography>Статьи не найдены</Typography>
)}
</Grid>
<Stack gap={2}>
<Typography variant="body1" fontWeight="bold">
Привязать статью
</Typography>
<Stack gap={2.5}>
<FormControl fullWidth>
<InputLabel>Статья</InputLabel>
<Select value={selectedArticleId} onChange={(e) => setSelectedArticleId(Number(e.target.value))} label="Статья" fullWidth>
{availableArticles.map((article) => (
<MenuItem key={article.id} value={article.id}>
{article.heading}
</MenuItem>
))}
</Select>
</FormControl>
<FormControl fullWidth>
<TextField type="number" label="Номер страницы" name="page_num" value={pageNum} onChange={(e) => setPageNum(Number(e.target.value))} fullWidth InputLabelProps={{shrink: true}} />
</FormControl>
<Button variant="contained" onClick={linkArticle} disabled={!selectedArticleId}>
Привязать
</Button>
</Stack>
</Stack>
</Stack>
</Stack>
</Show>
)
}