integrate article data into /sight/show page

This commit is contained in:
maxim 2025-02-14 00:27:36 +03:00
parent 3af49c5a23
commit bf72f78020
2 changed files with 153 additions and 5 deletions

View File

@ -110,7 +110,6 @@ function App() {
create: '/sight/create',
edit: '/sight/edit/:id',
show: '/sight/show/:id',
// добавить SHOW для sight->article (https://wn.krbl.ru/sight/2/article)
meta: {
canDelete: true,
label: 'Виды',

View File

@ -1,13 +1,101 @@
import {Stack, Typography} from '@mui/material'
import {Stack, Typography, Box, Grid2 as Grid, Button, MenuItem, Select, FormControl, InputLabel, TextField} from '@mui/material'
import {useShow} from '@refinedev/core'
import {Show, TextFieldComponent as TextField} from '@refinedev/mui'
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/`)
.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: 'Name', data: 'name'},
@ -24,9 +112,70 @@ export const SightShow = () => {
<Typography variant="body1" fontWeight="bold">
{label}
</Typography>
<TextField value={record?.[data]} />
<TextFieldComponent value={record?.[data]} />
</Stack>
))}
<Stack gap={2}>
<Typography variant="body1" fontWeight="bold">
Linked Articles
</Typography>
<Grid container gap={2}>
{articlesLoading ? (
<Typography>Loading articles...</Typography>
) : linkedArticles.length > 0 ? (
linkedArticles.map((article) => (
<Box key={article.id} sx={{border: '2px solid #dddddd25', padding: '20px', marginBottom: '8px'}}>
<Stack gap={0.5}>
<Typography>
<strong>ID:</strong> {article.id}
</Typography>
<Typography>
<strong>Heading:</strong> {article.heading}
</Typography>
<Typography>
<strong>Body:</strong> {article.body}
</Typography>
<Button variant="outlined" color="error" onClick={() => deleteArticle(article.id)} sx={{mt: 2}}>
Unlink Article
</Button>
</Stack>
</Box>
))
) : (
<Typography>No articles linked</Typography>
)}
</Grid>
<Stack gap={2}>
<Typography variant="body1" fontWeight="bold">
Link Article
</Typography>
<Stack gap={2.5}>
<FormControl fullWidth>
<InputLabel>Article</InputLabel>
<Select value={selectedArticleId} onChange={(e) => setSelectedArticleId(Number(e.target.value))} label="Article" fullWidth>
{availableArticles.map((article) => (
<MenuItem key={article.id} value={article.id}>
{article.heading}
</MenuItem>
))}
</Select>
</FormControl>
<FormControl fullWidth>
<TextField type="number" label="Page Number" name="page_num" value={pageNum} onChange={(e) => setPageNum(Number(e.target.value))} fullWidth InputLabelProps={{shrink: true}} />
</FormControl>
<Button variant="contained" onClick={linkArticle} disabled={!selectedArticleId}>
Link Article
</Button>
</Stack>
</Stack>
</Stack>
</Stack>
</Show>
)