import {useState, useEffect} from 'react' import {Stack, Typography, Button, MenuItem, Select, FormControl, InputLabel, Grid, Box, Accordion, AccordionSummary, AccordionDetails, useTheme, TextField} from '@mui/material' import ExpandMoreIcon from '@mui/icons-material/ExpandMore' import axios from 'axios' import {BACKEND_URL} from '../lib/constants' type Field = { label: string data: keyof T } type ExtraFieldConfig = { type: 'number' label: string minValue: number maxValue: (linkedItems: any[]) => number } type LinkedItemsProps = { parentId: string | number parentResource: string childResource: string fields: Field[] title: string type: 'show' | 'edit' extraField?: ExtraFieldConfig } export const LinkedItems = ({parentId, parentResource, childResource, fields, title, type}: LinkedItemsProps) => { const [items, setItems] = useState([]) const [linkedItems, setLinkedItems] = useState([]) const [selectedItemId, setSelectedItemId] = useState(null) const [pageNum, setPageNum] = useState(1) const [isLoading, setIsLoading] = useState(true) const [mediaOrder, setMediaOrder] = useState(1) const theme = useTheme() useEffect(() => { if (parentId) { axios .get(`${BACKEND_URL}/${parentResource}/${parentId}/${childResource}`) .then((response) => { setLinkedItems(response?.data || []) }) .catch(() => { setLinkedItems([]) }) } }, [parentId, parentResource, childResource]) useEffect(() => { if (type === 'edit') { axios .get(`${BACKEND_URL}/${childResource}/`) .then((response) => { setItems(response?.data || []) setIsLoading(false) }) .catch(() => { setItems([]) setIsLoading(false) }) } else { setIsLoading(false) } }, [childResource, type]) useEffect(() => { if (childResource === 'article' && parentResource === 'sight') { setPageNum(linkedItems.length + 1) } }, [linkedItems, childResource, parentResource]) const availableItems = items.filter((item) => !linkedItems.some((linked) => linked.id === item.id)) const linkItem = () => { if (selectedItemId !== null) { const requestData = childResource === 'article' ? { [`${childResource}_id`]: selectedItemId, page_num: pageNum, } : childResource === 'media' ? { [`${childResource}_id`]: selectedItemId, media_order: mediaOrder, } : { [`${childResource}_id`]: selectedItemId, } axios .post(`${BACKEND_URL}/${parentResource}/${parentId}/${childResource}`, requestData) .then(() => { axios.get(`${BACKEND_URL}/${parentResource}/${parentId}/${childResource}`).then((response) => { setLinkedItems(response?.data || []) setSelectedItemId(null) if (childResource === 'article') { setPageNum(pageNum + 1) } }) }) .catch((error) => { console.error('Error linking item:', error) }) } } const deleteItem = (itemId: number) => { axios .delete(`${BACKEND_URL}/${parentResource}/${parentId}/${childResource}`, { data: {[`${childResource}_id`]: itemId}, }) .then(() => { setLinkedItems((prev) => prev.filter((item) => item.id !== itemId)) }) .catch((error) => { console.error('Error unlinking item:', error) }) } return ( } sx={{ background: theme.palette.background.paper, borderBottom: `1px solid ${theme.palette.divider}`, }} > Привязанные {title} {isLoading ? ( Загрузка... ) : linkedItems.length > 0 ? ( linkedItems.map((item, index) => ( {fields.map(({label, data}) => ( {label}: {item[data]} ))} {type === 'edit' && ( )} )) ) : ( {title} не найдены )} {type === 'edit' && ( Добавить {title} Выберите {title} {childResource === 'article' && ( { const newValue = Number(e.target.value) const minValue = linkedItems.length + 1 // page number on articles lenght setPageNum(newValue < minValue ? minValue : newValue) }} fullWidth InputLabelProps={{shrink: true}} /> )} {childResource === 'media' && type === 'edit' && ( { const newValue = Number(e.target.value) const maxValue = linkedItems.length + 1 const value = Math.max(1, Math.min(newValue, maxValue)) setMediaOrder(value) }} fullWidth InputLabelProps={{shrink: true}} /> )} )} ) }