add post option for media to /article/show page

This commit is contained in:
maxim 2025-02-13 20:09:35 +03:00
parent 96585fe618
commit 311bf2189b

View File

@ -1,42 +1,95 @@
import {Stack, Typography, Box, Grid2 as Grid, Button} 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 {useShow} from '@refinedev/core'
import {Show, TextFieldComponent as TextField} from '@refinedev/mui' import {Show, TextFieldComponent} from '@refinedev/mui'
import {useEffect, useState} from 'react' import {useEffect, useState} from 'react'
import axios from 'axios' import axios from 'axios'
import {BACKEND_URL} from '../../lib/constants' import {BACKEND_URL} from '../../lib/constants'
type MediaItem = {
id: string
filename: string
media_type: string
}
export const ArticleShow = () => { export const ArticleShow = () => {
const {query} = useShow({}) const {query} = useShow({})
const {data, isLoading} = query const {data, isLoading} = query
const record = data?.data const record = data?.data
const [media, setMedia] = useState<any[]>([]) const [media, setMedia] = useState<MediaItem[]>([])
const [mediaLoading, setMediaLoading] = useState(true) const [linkedMedia, setLinkedMedia] = useState<MediaItem[]>([])
const [selectedMediaId, setSelectedMediaId] = useState<string>('')
const [mediaOrder, setMediaOrder] = useState<number>(1)
const [mediaLoading, setMediaLoading] = useState<boolean>(true)
useEffect(() => { useEffect(() => {
if (record?.id) { if (record?.id) {
axios axios
.get(`${BACKEND_URL}/article/${record.id}/media`) .get(`${BACKEND_URL}/article/${record.id}/media`)
.then((response) => { .then((response) => {
setMedia(response?.data || []) setLinkedMedia(response?.data || [])
setMediaLoading(false)
}) })
.catch(() => { .catch(() => {
setMedia([]) setLinkedMedia([])
setMediaLoading(false)
}) })
} }
}, [record?.id]) }, [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)
})
.catch(() => {
setLinkedMedia([])
})
})
.catch((error) => {
console.error('Error linking media:', error)
})
}
}
const deleteMedia = (mediaId: string) => { const deleteMedia = (mediaId: string) => {
axios axios
.delete(`${BACKEND_URL}/article/${record?.id}/media`, { .delete(`${BACKEND_URL}/article/${record?.id}/media`, {
data: {media_id: mediaId}, data: {media_id: mediaId},
}) })
.then(() => { .then(() => {
setMedia((prevMedia) => prevMedia.filter((item) => item.id !== mediaId)) setLinkedMedia((prevMedia) => prevMedia.filter((item) => item.id !== mediaId))
}) })
.catch((error) => { .catch((error) => {
console.error('Error deleting media:', error) console.error('Error deleting media:', error)
@ -50,9 +103,9 @@ export const ArticleShow = () => {
] ]
const mediaFields = [ const mediaFields = [
{label: 'ID', data: 'id'}, {label: 'ID', data: 'id' as keyof MediaItem},
{label: 'Filename', data: 'filename'}, {label: 'Filename', data: 'filename' as keyof MediaItem},
{label: 'Media Type', data: 'media_type'}, {label: 'Media Type', data: 'media_type' as keyof MediaItem},
] ]
return ( return (
@ -63,7 +116,7 @@ export const ArticleShow = () => {
<Typography variant="body1" fontWeight="bold"> <Typography variant="body1" fontWeight="bold">
{label} {label}
</Typography> </Typography>
<TextField value={record?.[data]} /> <TextFieldComponent value={record?.[data] || ''} />
</Stack> </Stack>
))} ))}
@ -75,28 +128,12 @@ export const ArticleShow = () => {
<Grid container gap={2}> <Grid container gap={2}>
{mediaLoading ? ( {mediaLoading ? (
<Typography>Loading media...</Typography> <Typography>Loading media...</Typography>
) : media.length > 0 ? ( ) : linkedMedia.length > 0 ? (
media.map((mediaItem, index) => ( linkedMedia.map((mediaItem, index) => (
<Box key={index} sx={{border: '2px solid #dddddd25', padding: '20px', marginBottom: '8px'}}> <Box key={index} sx={{border: '2px solid #dddddd25', padding: '20px', marginBottom: '8px'}}>
{record && ( {record && (
<Box <Box sx={{display: 'flex', justifyContent: 'center', alignItems: 'center', marginBottom: '20px'}}>
sx={{ <img src={`${BACKEND_URL}/media/${mediaItem?.id}/download`} alt={mediaItem?.filename} style={{maxWidth: '100%', height: '20vh', objectFit: 'contain', borderRadius: 8}} />
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
marginBottom: '20px',
}}
>
<img
src={`${BACKEND_URL}/media/${mediaItem?.id}/download`}
alt={mediaItem?.filename}
style={{
maxWidth: '100%',
height: '20vh',
objectFit: 'contain',
borderRadius: 8,
}}
/>
</Box> </Box>
)} )}
@ -117,6 +154,33 @@ export const ArticleShow = () => {
<Typography>No media found</Typography> <Typography>No media found</Typography>
)} )}
</Grid> </Grid>
<Stack gap={2}>
<Typography variant="body1" fontWeight="bold">
Link Media
</Typography>
<Stack gap={2.5}>
<FormControl fullWidth>
<InputLabel>Media</InputLabel>
<Select value={selectedMediaId} onChange={(e) => setSelectedMediaId(e.target.value)} label="Media" fullWidth>
{availableMedia.map((mediaItem) => (
<MenuItem key={mediaItem.id} value={mediaItem.id}>
{mediaItem.filename}
</MenuItem>
))}
</Select>
</FormControl>
<FormControl fullWidth>
<TextField type="number" label="Media Order" name="heading" value={mediaOrder} onChange={(e) => setMediaOrder(Number(e.target.value))} fullWidth InputLabelProps={{shrink: true}} />
</FormControl>
<Button variant="contained" onClick={linkMedia} disabled={!selectedMediaId}>
Link Media
</Button>
</Stack>
</Stack>
</Stack> </Stack>
</Stack> </Stack>
</Show> </Show>