From 311bf2189bf95bddce208ed92e7ec9363044bed3 Mon Sep 17 00:00:00 2001 From: maxim Date: Thu, 13 Feb 2025 20:09:35 +0300 Subject: [PATCH] add `post` option for `media` to `/article/show` page --- src/pages/article/show.tsx | 130 +++++++++++++++++++++++++++---------- 1 file changed, 97 insertions(+), 33 deletions(-) diff --git a/src/pages/article/show.tsx b/src/pages/article/show.tsx index f1f5224..73f5dd3 100644 --- a/src/pages/article/show.tsx +++ b/src/pages/article/show.tsx @@ -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 {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 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([]) - const [mediaLoading, setMediaLoading] = useState(true) + const [media, setMedia] = useState([]) + const [linkedMedia, setLinkedMedia] = useState([]) + const [selectedMediaId, setSelectedMediaId] = useState('') + const [mediaOrder, setMediaOrder] = useState(1) + const [mediaLoading, setMediaLoading] = useState(true) useEffect(() => { if (record?.id) { axios .get(`${BACKEND_URL}/article/${record.id}/media`) .then((response) => { - setMedia(response?.data || []) - setMediaLoading(false) + setLinkedMedia(response?.data || []) }) .catch(() => { - setMedia([]) - setMediaLoading(false) + 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) + }) + .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(() => { - setMedia((prevMedia) => prevMedia.filter((item) => item.id !== mediaId)) + setLinkedMedia((prevMedia) => prevMedia.filter((item) => item.id !== mediaId)) }) .catch((error) => { console.error('Error deleting media:', error) @@ -50,9 +103,9 @@ export const ArticleShow = () => { ] const mediaFields = [ - {label: 'ID', data: 'id'}, - {label: 'Filename', data: 'filename'}, - {label: 'Media Type', data: 'media_type'}, + {label: 'ID', data: 'id' as keyof MediaItem}, + {label: 'Filename', data: 'filename' as keyof MediaItem}, + {label: 'Media Type', data: 'media_type' as keyof MediaItem}, ] return ( @@ -63,7 +116,7 @@ export const ArticleShow = () => { {label} - + ))} @@ -75,28 +128,12 @@ export const ArticleShow = () => { {mediaLoading ? ( Loading media... - ) : media.length > 0 ? ( - media.map((mediaItem, index) => ( + ) : linkedMedia.length > 0 ? ( + linkedMedia.map((mediaItem, index) => ( {record && ( - - {mediaItem?.filename} + + {mediaItem?.filename} )} @@ -117,6 +154,33 @@ export const ArticleShow = () => { No media found )} + + + + Link Media + + + + + Media + + + + + setMediaOrder(Number(e.target.value))} fullWidth InputLabelProps={{shrink: true}} /> + + + + +