integrate article
data into /sight/show
page
This commit is contained in:
parent
3af49c5a23
commit
bf72f78020
@ -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: 'Виды',
|
||||
|
@ -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>
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user