WhiteNightsAdminPanel/src/pages/article/show.tsx
2025-02-21 22:15:16 +03:00

182 lines
5.9 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, Grid2 as Grid, Button, MenuItem, Select, FormControl, InputLabel, TextField, Card, CardMedia, CardContent, CardActions} 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 MediaItem = {
id: string
filename: string
media_type: string
}
export const ArticleShow = () => {
const {query} = useShow({})
const {data, isLoading} = query
const record = data?.data
const [media, setMedia] = useState<MediaItem[]>([])
const [linkedMedia, setLinkedMedia] = useState<MediaItem[]>([])
const [selectedMediaId, setSelectedMediaId] = useState<string>('')
const [mediaOrder, setMediaOrder] = useState<number>(1)
const [mediaLoading, setMediaLoading] = useState<boolean>(true)
useEffect(() => {
if (record?.id) {
axios
.get(`${BACKEND_URL}/article/${record.id}/media`)
.then((response) => {
setLinkedMedia(response?.data || [])
})
.catch(() => {
setLinkedMedia([])
})
}
}, [record?.id])
useEffect(() => {
axios
.get(`${BACKEND_URL}/media`)
.then((response) => {
setMedia(response?.data || [])
setMediaLoading(false)
})
.catch(() => {
setMedia([])
setMediaLoading(false)
})
}, [])
const availableMedia = media.filter((mediaItem) => !linkedMedia.some((linkedItem) => linkedItem.id === mediaItem.id))
const linkMedia = () => {
if (selectedMediaId) {
const requestData = {
media_id: selectedMediaId,
media_order: mediaOrder,
}
axios
.post(`${BACKEND_URL}/article/${record?.id}/media`, requestData, {
headers: {
accept: 'application/json',
'Content-Type': 'application/json',
},
})
.then(() => {
axios
.get(`${BACKEND_URL}/article/${record?.id}/media`)
.then((response) => {
setLinkedMedia(response?.data || [])
setMediaOrder(mediaOrder + 1)
setSelectedMediaId('')
})
.catch(() => {
setLinkedMedia([])
})
})
.catch((error) => {
console.error('Error linking media:', error)
})
}
}
const deleteMedia = (mediaId: string) => {
axios
.delete(`${BACKEND_URL}/article/${record?.id}/media`, {
data: {media_id: mediaId},
})
.then(() => {
setLinkedMedia((prevMedia) => prevMedia.filter((item) => item.id !== mediaId))
})
.catch((error) => {
console.error('Error deleting media:', error)
})
}
const fields = [
// {label: 'ID', data: 'id'},
{label: 'Заголовок', data: 'heading'},
{label: 'Контент', data: 'body'},
]
const mediaFields = [
// {label: 'ID', data: 'id' as keyof MediaItem},
{label: 'Имя', data: 'filename' as keyof MediaItem},
{label: 'Тип', data: 'media_type' as keyof MediaItem},
]
return (
<Show isLoading={isLoading}>
<Stack gap={4}>
{fields.map(({label, data}) => (
<Stack key={data} gap={1}>
<Typography variant="h6" fontWeight="bold">
{label}
</Typography>
<TextFieldComponent value={record?.[data] || ''} />
</Stack>
))}
<Stack gap={2}>
<Typography variant="h6" fontWeight="bold">
Медиа
</Typography>
<Grid container spacing={2}>
{mediaLoading ? (
<Typography>Загрузка медиа...</Typography>
) : linkedMedia.length > 0 ? (
linkedMedia.map((mediaItem) => (
<Grid key={mediaItem.id}>
<Card sx={{backgroundColor: '#1e1e1e', borderRadius: 2}}>
<CardMedia component="img" height="200" image={`${BACKEND_URL}/media/${mediaItem?.id}/download`} alt={mediaItem?.filename} sx={{objectFit: 'contain', backgroundColor: '#2e2e2e'}} />
<CardContent>
{mediaFields.map(({label, data}) => (
<Typography key={data} variant="body2" color="textSecondary">
<strong>{label}:</strong> {mediaItem?.[data]}
</Typography>
))}
</CardContent>
<CardActions>
<Button variant="outlined" color="error" onClick={() => deleteMedia(mediaItem?.id)} fullWidth>
Отвязать
</Button>
</CardActions>
</Card>
</Grid>
))
) : (
<Typography>Нет привязанных медиа</Typography>
)}
</Grid>
{/* sx={{width: '650px'}} */}
<Stack gap={2} mt={4}>
{' '}
<Typography variant="h6" fontWeight="bold">
Привязать медиа
</Typography>
<FormControl fullWidth>
<InputLabel>Медиа</InputLabel>
<Select value={selectedMediaId} onChange={(e) => setSelectedMediaId(e.target.value)} fullWidth>
{availableMedia.map((mediaItem) => (
<MenuItem key={mediaItem.id} value={mediaItem.id}>
{mediaItem.filename}
</MenuItem>
))}
</Select>
</FormControl>
<TextField type="number" label="Порядок отображения медиа" value={mediaOrder} onChange={(e) => setMediaOrder(Number(e.target.value))} fullWidth InputLabelProps={{shrink: true}} />
<Button variant="contained" onClick={linkMedia} disabled={!selectedMediaId}>
Привязать
</Button>
</Stack>
</Stack>
</Stack>
</Show>
)
}