import { Box, Button, Paper, Typography, Menu, MenuItem, TextField, } from "@mui/material"; import { authInstance, BackButton, editSightStore, languageStore, SelectArticleModal, SelectMediaDialog, TabPanel, UploadMediaDialog, } from "@shared"; import { DeleteModal, LanguageSwitcher, MediaArea, MediaAreaForSight, ReactMarkdownComponent, ReactMarkdownEditor, } from "@widgets"; import { ImagePlus, Plus, Save, Trash2, Unlink, X } from "lucide-react"; import { observer } from "mobx-react-lite"; import { useEffect, useState } from "react"; import { toast } from "react-toastify"; import { MediaViewer } from "../../MediaViewer/index"; import { DragDropContext, Droppable, Draggable, DropResult, } from "@hello-pangea/dnd"; export const RightWidgetTab = observer( ({ value, index }: { value: number; index: number }) => { const [anchorEl, setAnchorEl] = useState(null); const { sight, updateRightArticleInfo, getRightArticles, updateSight, unlinkPreviewMedia, linkPreviewMedia, unlinkRightArticle, deleteRightArticle, linkArticle, deleteRightArticleMedia, createLinkWithRightArticle, setFileToUpload, createNewRightArticle, updateRightArticles, } = editSightStore; const [previewMedia, setPreviewMedia] = useState(null); useEffect(() => { const fetchPreviewMedia = async () => { if (sight.common.preview_media) { const response = await authInstance.get( `/media/${sight.common.preview_media}` ); setPreviewMedia(response.data); } }; fetchPreviewMedia(); }, [sight.common.preview_media]); const handleUnlinkPreviewMedia = () => { unlinkPreviewMedia(); setPreviewMedia(null); }; const [uploadMediaOpen, setUploadMediaOpen] = useState(false); const { language } = languageStore; const [type, setType] = useState<"article" | "media">("media"); useEffect(() => { const fetchData = async () => { if (sight.common.id) { await getRightArticles(sight.common.id); } }; fetchData(); console.log(sight[language].right); }, [sight.common.id]); const [activeArticleIndex, setActiveArticleIndex] = useState( null ); const [isSelectModalOpen, setIsSelectModalOpen] = useState(false); const [isSelectMediaModalOpen, setIsSelectMediaModalOpen] = useState(false); const [isDeleteArticleModalOpen, setIsDeleteArticleModalOpen] = useState(false); const open = Boolean(anchorEl); const handleDeleteArticle = () => { deleteRightArticle(sight[language].right[activeArticleIndex || 0].id); setActiveArticleIndex(null); }; const handleClick = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; const handleSelectArticle = (index: number) => { setActiveArticleIndex(index); }; const handleCreateNew = () => { createNewRightArticle(); handleClose(); }; const handleSelectExisting = () => { setIsSelectModalOpen(true); handleClose(); }; const handleCloseSelectModal = () => { setIsSelectModalOpen(false); }; const handleArticleSelect = (id: number) => { linkArticle(id); handleCloseSelectModal(); }; const handleMediaSelected = async (media: { id: string; filename: string; media_name?: string; media_type: number; }) => { await createLinkWithRightArticle( media, sight[language].right[activeArticleIndex || 0].id ); }; const handleSave = async () => { await updateSight(); toast.success("Достопримечательность сохранена"); }; useEffect(() => { console.log(sight[language].right); }, [sight[language].right]); const handleDragEnd = (result: DropResult) => { const { source, destination } = result; // 1. Guard clause: If dropped outside any droppable area, do nothing. if (!destination) return; // Extract source and destination indices const sourceIndex = source.index; const destinationIndex = destination.index; // 2. Guard clause: If dropped in the same position, do nothing. if (sourceIndex === destinationIndex) return; // 3. Create a new array with reordered articles: // - Create a shallow copy of the current articles array. // This is important for immutability and triggering re-renders. const newRightArticles = [...sight[language].right]; // - Remove the dragged article from its original position. // `splice` returns an array of removed items, so we destructure the first (and only) one. const [movedArticle] = newRightArticles.splice(sourceIndex, 1); // - Insert the moved article into its new position. newRightArticles.splice(destinationIndex, 0, movedArticle); // 4. Update the store with the new order: // This will typically trigger a re-render of the component with the updated list. updateRightArticles(newRightArticles); }; return (

{sight[language].name}

setType("media")} className="w-full bg-green-200 p-4 rounded-2xl cursor-pointer text-sm hover:bg-gray-300 transition-all duration-300" > Предпросмотр медиа {(provided) => ( {sight[language].right.length > 0 ? sight[language].right.map( (article, index) => ( {(provided, snapshot) => ( { handleSelectArticle(index); setType("article"); }} > {article.heading} )} ) ) : null} {provided.placeholder} )} Создать новую Выбрать существующую статью {type === "article" && ( {activeArticleIndex !== null && ( <> updateRightArticleInfo( activeArticleIndex, language, e.target.value, sight[language].right[activeArticleIndex].body ) } variant="outlined" fullWidth /> updateRightArticleInfo( activeArticleIndex, language, sight[language].right[activeArticleIndex] .heading, value ) } /> { setFileToUpload(files[0]); setUploadMediaOpen(true); }} deleteMedia={deleteRightArticleMedia} setSelectMediaDialogOpen={() => { setIsSelectMediaModalOpen(true); }} /> )} )} {type === "media" && ( {sight.common.preview_media && ( <> {type === "media" && ( {previewMedia && ( <> )} {!previewMedia && ( { linkPreviewMedia(mediaId); }} onFilesDrop={() => {}} /> )} )} )} {!sight.common.preview_media && ( { linkPreviewMedia(mediaId); }} onFilesDrop={() => {}} /> )} )} {type === "article" && ( {activeArticleIndex !== null && ( {sight[language].right[activeArticleIndex].media.length > 0 ? ( ) : ( )} {sight[language].right[activeArticleIndex].heading || "Выберите статью"} {sight[language].right[activeArticleIndex].body ? ( ) : ( Предпросмотр статьи появится здесь )} {sight[language].right.length > 0 && sight[language].right.map((article, index) => ( ))} )} )}
setUploadMediaOpen(false)} afterUpload={async (media) => { setUploadMediaOpen(false); setFileToUpload(null); await createLinkWithRightArticle( media, sight[language].right[activeArticleIndex || 0].id ); }} /> setIsDeleteArticleModalOpen(false)} onDelete={() => { handleDeleteArticle(); setIsDeleteArticleModalOpen(false); }} /> article.id)} /> setIsSelectMediaModalOpen(false)} onSelectMedia={handleMediaSelected} />
); } );