375 lines
14 KiB
TypeScript
375 lines
14 KiB
TypeScript
import {
|
||
Box,
|
||
Button,
|
||
Paper,
|
||
Typography,
|
||
Menu,
|
||
MenuItem,
|
||
TextField,
|
||
} from "@mui/material";
|
||
import { BackButton, createSightStore, languageStore, TabPanel } from "@shared";
|
||
import {
|
||
LanguageSwitcher,
|
||
ReactMarkdownComponent,
|
||
ReactMarkdownEditor,
|
||
} from "@widgets";
|
||
import { ImagePlus, Plus } from "lucide-react";
|
||
import { observer } from "mobx-react-lite";
|
||
import { useState } from "react";
|
||
|
||
// --- RightWidgetTab (Parent) Component ---
|
||
export const CreateRightTab = observer(
|
||
({ value, index }: { value: number; index: number }) => {
|
||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||
const { sight, createNewRightArticle, updateRightArticleInfo } =
|
||
createSightStore;
|
||
const { language } = languageStore;
|
||
|
||
const [activeArticleIndex, setActiveArticleIndex] = useState<number | null>(
|
||
null
|
||
);
|
||
const open = Boolean(anchorEl);
|
||
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||
setAnchorEl(event.currentTarget);
|
||
};
|
||
const handleClose = () => {
|
||
setAnchorEl(null);
|
||
};
|
||
const handleSave = () => {
|
||
console.log("Saving right widget...");
|
||
};
|
||
|
||
const handleSelectArticle = (index: number) => {
|
||
setActiveArticleIndex(index);
|
||
};
|
||
|
||
return (
|
||
<TabPanel value={value} index={index}>
|
||
<LanguageSwitcher />
|
||
<Box
|
||
sx={{
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
height: "100%",
|
||
minHeight: "calc(100vh - 200px)", // Adjust as needed
|
||
gap: 2,
|
||
paddingBottom: "70px", // Space for the save button
|
||
position: "relative",
|
||
}}
|
||
>
|
||
<BackButton />
|
||
|
||
<Box sx={{ display: "flex", flexGrow: 1, gap: 2.5 }}>
|
||
<Box className="flex flex-col w-[75%] gap-2">
|
||
<Box className="w-full flex gap-2 ">
|
||
<Box className="relative w-[20%] h-[70vh] flex flex-col rounded-2xl overflow-y-auto gap-3 border border-gray-300 p-3">
|
||
<Box className="flex flex-col gap-3 max-h-[60vh] overflow-y-auto">
|
||
<Box
|
||
onClick={() => {
|
||
// setMediaType("preview");
|
||
}}
|
||
className="w-full bg-gray-200 p-4 rounded-2xl cursor-pointer text-sm hover:bg-gray-300 transition-all duration-300"
|
||
>
|
||
<Typography>Предпросмотр медиа</Typography>
|
||
</Box>
|
||
|
||
{sight[language].right.map((article, index) => (
|
||
<Box
|
||
key={index}
|
||
className="w-full bg-gray-200 p-4 rounded-2xl text-sm cursor-pointer hover:bg-gray-300 transition-all duration-300"
|
||
onClick={() => {
|
||
handleSelectArticle(index);
|
||
}}
|
||
>
|
||
<Typography>{article.heading}</Typography>
|
||
</Box>
|
||
))}
|
||
</Box>
|
||
<button
|
||
className="w-10 h-10 bg-blue-500 rounded-full absolute bottom-5 left-5 flex items-center justify-center"
|
||
onClick={handleClick}
|
||
>
|
||
<Plus size={20} color="white" />
|
||
</button>
|
||
<Menu
|
||
id="basic-menu"
|
||
anchorEl={anchorEl}
|
||
open={open}
|
||
onClose={handleClose}
|
||
MenuListProps={{
|
||
"aria-labelledby": "basic-button",
|
||
}}
|
||
sx={{
|
||
mt: 1,
|
||
}}
|
||
>
|
||
<MenuItem
|
||
onClick={() => {
|
||
createNewRightArticle();
|
||
handleClose();
|
||
}}
|
||
>
|
||
<Typography>Создать новую</Typography>
|
||
</MenuItem>
|
||
<MenuItem
|
||
onClick={() => {
|
||
handleClose();
|
||
}}
|
||
>
|
||
<Typography>Выбрать существующую статью</Typography>
|
||
</MenuItem>
|
||
</Menu>
|
||
</Box>
|
||
<Box className="w-[80%] h-[70vh] border border-gray-300 rounded-2xl p-3">
|
||
{activeArticleIndex !== null && (
|
||
<>
|
||
<Box className="flex justify-end gap-2 mb-3">
|
||
<Button variant="contained" color="primary">
|
||
Открепить
|
||
</Button>
|
||
|
||
<Button variant="contained" color="success">
|
||
Удалить
|
||
</Button>
|
||
</Box>
|
||
<Box sx={{ display: "flex", gap: 3, flexGrow: 1 }}>
|
||
{/* Левая колонка: Редактирование */}
|
||
|
||
<Box
|
||
sx={{
|
||
flex: 2,
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
gap: 2,
|
||
}}
|
||
>
|
||
<TextField
|
||
label="Название информации"
|
||
value={
|
||
sight[language].right[activeArticleIndex].heading
|
||
}
|
||
onChange={(e) =>
|
||
updateRightArticleInfo(
|
||
activeArticleIndex,
|
||
language,
|
||
e.target.value,
|
||
sight[language].right[activeArticleIndex].body
|
||
)
|
||
}
|
||
variant="outlined"
|
||
fullWidth
|
||
/>
|
||
|
||
<ReactMarkdownEditor
|
||
value={
|
||
sight[language].right[activeArticleIndex].body
|
||
}
|
||
onChange={(value) =>
|
||
updateRightArticleInfo(
|
||
activeArticleIndex,
|
||
language,
|
||
sight[language].right[activeArticleIndex]
|
||
.heading,
|
||
value
|
||
)
|
||
}
|
||
/>
|
||
</Box>
|
||
{/* Блок МЕДИА для статьи */}
|
||
{/* <Paper elevation={1} sx={{ padding: 2, mt: 1 }}>
|
||
<Typography variant="h6" gutterBottom>
|
||
МЕДИА
|
||
</Typography>
|
||
{data.left.media ? (
|
||
<Box sx={{ mb: 1 }}>
|
||
<img
|
||
src={data.left.media.filename}
|
||
alt="Selected media"
|
||
style={{
|
||
maxWidth: "100%",
|
||
maxHeight: "150px",
|
||
objectFit: "contain",
|
||
}}
|
||
/>
|
||
</Box>
|
||
) : (
|
||
<Box
|
||
sx={{
|
||
width: "100%",
|
||
height: 100,
|
||
backgroundColor: "grey.100",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
borderRadius: 1,
|
||
mb: 1,
|
||
border: "2px dashed",
|
||
borderColor: "grey.300",
|
||
}}
|
||
>
|
||
<Typography color="text.secondary">Нет медиа</Typography>
|
||
</Box>
|
||
)}
|
||
<Button
|
||
variant="contained"
|
||
startIcon={<ImagePlus size={18} />}
|
||
onClick={handleOpenMediaDialog}
|
||
>
|
||
Выбрать/Загрузить медиа
|
||
</Button>
|
||
{data.left.media && (
|
||
<Button
|
||
variant="outlined"
|
||
color="error"
|
||
size="small"
|
||
sx={{ ml: 1 }}
|
||
onClick={() =>
|
||
updateSightInfo(
|
||
languageStore.language,
|
||
{
|
||
left: {
|
||
heading: data.left.heading,
|
||
body: data.left.body,
|
||
media: null,
|
||
},
|
||
},
|
||
false
|
||
)
|
||
}
|
||
>
|
||
Удалить медиа
|
||
</Button>
|
||
)}
|
||
</Paper> */}
|
||
</Box>
|
||
</>
|
||
)}
|
||
</Box>
|
||
</Box>
|
||
</Box>
|
||
<Box className="w-[25%] mr-10">
|
||
{activeArticleIndex !== null && (
|
||
<Paper
|
||
className="flex-1 flex flex-col rounded-2xl"
|
||
elevation={2}
|
||
>
|
||
<Box
|
||
className="rounded-2xl overflow-hidden"
|
||
sx={{
|
||
width: "100%",
|
||
height: "75vh",
|
||
background: "#877361",
|
||
borderColor: "grey.300",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
}}
|
||
>
|
||
{false ? (
|
||
<Box
|
||
sx={{
|
||
width: "100%",
|
||
height: "100%",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
}}
|
||
>
|
||
<Typography color="white">Загрузка...</Typography>
|
||
</Box>
|
||
) : (
|
||
<>
|
||
<Box
|
||
sx={{
|
||
width: "100%",
|
||
height: 200,
|
||
flexShrink: 0,
|
||
backgroundColor: "rgba(0,0,0,0.1)",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
}}
|
||
>
|
||
<ImagePlus size={48} color="white" />
|
||
</Box>
|
||
|
||
<Box
|
||
sx={{
|
||
width: "100%",
|
||
minHeight: "70px",
|
||
background: "#877361",
|
||
display: "flex",
|
||
flexShrink: 0,
|
||
alignItems: "center",
|
||
borderBottom: "1px solid rgba(255,255,255,0.1)",
|
||
px: 2,
|
||
}}
|
||
>
|
||
<Typography variant="h6" color="white">
|
||
{sight[language].right[activeArticleIndex]
|
||
.heading || "Выберите статью"}
|
||
</Typography>
|
||
</Box>
|
||
|
||
<Box
|
||
sx={{
|
||
px: 2,
|
||
flexGrow: 1,
|
||
|
||
overflowY: "auto",
|
||
backgroundColor: "#877361",
|
||
color: "white",
|
||
py: 1,
|
||
}}
|
||
>
|
||
{sight[language].right[activeArticleIndex].body ? (
|
||
<ReactMarkdownComponent
|
||
value={
|
||
sight[language].right[activeArticleIndex].body
|
||
}
|
||
/>
|
||
) : (
|
||
<Typography
|
||
color="rgba(255,255,255,0.7)"
|
||
sx={{ textAlign: "center", mt: 4 }}
|
||
>
|
||
Предпросмотр статьи появится здесь
|
||
</Typography>
|
||
)}
|
||
</Box>
|
||
</>
|
||
)}
|
||
</Box>
|
||
</Paper>
|
||
)}
|
||
</Box>
|
||
</Box>
|
||
|
||
<Box
|
||
sx={{
|
||
position: "absolute",
|
||
bottom: 0,
|
||
right: 0,
|
||
padding: 2,
|
||
backgroundColor: "background.paper", // Ensure button is visible
|
||
width: "100%", // Cover the full width to make it a sticky footer
|
||
display: "flex",
|
||
justifyContent: "flex-end",
|
||
}}
|
||
>
|
||
<Button variant="contained" color="success" onClick={handleSave}>
|
||
Сохранить изменения
|
||
</Button>
|
||
</Box>
|
||
</Box>
|
||
{/*
|
||
<SelectArticleModal
|
||
open={openedType === "article"}
|
||
onClose={handleCloseSelectModal}
|
||
onSelectArticle={handleSelectArticle}
|
||
linkedArticleIds={linkedArticleIds}
|
||
/> */}
|
||
</TabPanel>
|
||
);
|
||
}
|
||
);
|