915 lines
32 KiB
TypeScript
915 lines
32 KiB
TypeScript
import {
|
||
Autocomplete,
|
||
Box,
|
||
TextField,
|
||
Paper,
|
||
Typography,
|
||
Tab,
|
||
Tabs,
|
||
} from "@mui/material";
|
||
import { Edit, useAutocomplete } from "@refinedev/mui";
|
||
import { useForm } from "@refinedev/react-hook-form";
|
||
import { Controller } from "react-hook-form";
|
||
import { useParams, Link } from "react-router";
|
||
import React, { useState, useEffect } from "react";
|
||
import { LinkedItems } from "../../components/LinkedItems";
|
||
import { CreateSightArticle } from "../../components/CreateSightArticle";
|
||
import { ArticleItem, articleFields } from "./types";
|
||
import { TOKEN_KEY } from "../../authProvider";
|
||
import { observer } from "mobx-react-lite";
|
||
|
||
import { languageStore } from "../../store/LanguageStore";
|
||
|
||
function a11yProps(index: number) {
|
||
return {
|
||
id: `simple-tab-${index}`,
|
||
"aria-controls": `simple-tabpanel-${index}`,
|
||
};
|
||
}
|
||
|
||
interface TabPanelProps {
|
||
children?: React.ReactNode;
|
||
index: number;
|
||
value: number;
|
||
}
|
||
|
||
function CustomTabPanel(props: TabPanelProps) {
|
||
const { children, value, index, ...other } = props;
|
||
|
||
return (
|
||
<div
|
||
role="tabpanel"
|
||
hidden={value !== index}
|
||
id={`simple-tabpanel-${index}`}
|
||
aria-labelledby={`simple-tab-${index}`}
|
||
{...other}
|
||
>
|
||
{value === index && <Box sx={{ p: 3 }}>{children}</Box>}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export const SightEdit = observer(() => {
|
||
const { id: sightId } = useParams<{ id: string }>();
|
||
const { language, setLanguageAction } = languageStore;
|
||
|
||
const {
|
||
saveButtonProps,
|
||
register,
|
||
control,
|
||
watch,
|
||
getValues,
|
||
setValue,
|
||
formState: { errors },
|
||
} = useForm({
|
||
refineCoreProps: {
|
||
meta: {
|
||
headers: {
|
||
"Accept-Language": language,
|
||
},
|
||
},
|
||
},
|
||
});
|
||
|
||
const { autocompleteProps: cityAutocompleteProps } = useAutocomplete({
|
||
resource: "city",
|
||
onSearch: (value) => [
|
||
{
|
||
field: "name",
|
||
operator: "contains",
|
||
value,
|
||
},
|
||
],
|
||
});
|
||
const [tabValue, setTabValue] = useState(0);
|
||
const { autocompleteProps: mediaAutocompleteProps } = useAutocomplete({
|
||
resource: "media",
|
||
onSearch: (value) => [
|
||
{
|
||
field: "media_name",
|
||
operator: "contains",
|
||
value,
|
||
},
|
||
],
|
||
});
|
||
|
||
const { autocompleteProps: articleAutocompleteProps } = useAutocomplete({
|
||
resource: "article",
|
||
queryOptions: {
|
||
queryKey: ["article", language],
|
||
},
|
||
onSearch: (value) => [
|
||
{
|
||
field: "heading",
|
||
operator: "contains",
|
||
value,
|
||
},
|
||
],
|
||
});
|
||
|
||
useEffect(() => {
|
||
const latitude = getValues("latitude");
|
||
const longitude = getValues("longitude");
|
||
if (latitude && longitude) {
|
||
setCoordinatesPreview({
|
||
latitude: latitude,
|
||
longitude: longitude,
|
||
});
|
||
}
|
||
}, [getValues]);
|
||
|
||
const handleCoordinatesChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||
const [lat, lon] = e.target.value.split(",").map((s) => s.trim());
|
||
setCoordinatesPreview({
|
||
latitude: lat,
|
||
longitude: lon,
|
||
});
|
||
setValue("latitude", lat);
|
||
setValue("longitude", lon);
|
||
};
|
||
|
||
// Состояния для предпросмотра
|
||
const [namePreview, setNamePreview] = useState("");
|
||
const [coordinatesPreview, setCoordinatesPreview] = useState({
|
||
latitude: "",
|
||
longitude: "",
|
||
});
|
||
const [cityPreview, setCityPreview] = useState("");
|
||
const [thumbnailPreview, setThumbnailPreview] = useState<string | null>(null);
|
||
const [watermarkLUPreview, setWatermarkLUPreview] = useState<string | null>(
|
||
null
|
||
);
|
||
const [watermarkRDPreview, setWatermarkRDPreview] = useState<string | null>(
|
||
null
|
||
);
|
||
const [leftArticlePreview, setLeftArticlePreview] = useState("");
|
||
const [previewArticlePreview, setPreviewArticlePreview] = useState("");
|
||
|
||
// Следим за изменениями во всех полях
|
||
const coordinatesContent = watch("coordinates");
|
||
const addressContent = watch("address");
|
||
const nameContent = watch("name");
|
||
const latitudeContent = watch("latitude");
|
||
const longitudeContent = watch("longitude");
|
||
const cityContent = watch("city_id");
|
||
const thumbnailContent = watch("thumbnail");
|
||
const watermarkLUContent = watch("watermark_lu");
|
||
const watermarkRDContent = watch("watermark_rd");
|
||
const leftArticleContent = watch("left_article");
|
||
const previewArticleContent = watch("preview_article");
|
||
|
||
// Обновляем состояния при изменении полей
|
||
useEffect(() => {
|
||
setNamePreview(nameContent || "");
|
||
}, [nameContent]);
|
||
|
||
useEffect(() => {
|
||
setCoordinatesPreview({
|
||
latitude: latitudeContent || "",
|
||
longitude: longitudeContent || "",
|
||
});
|
||
}, [latitudeContent, longitudeContent]);
|
||
|
||
useEffect(() => {
|
||
const selectedCity = cityAutocompleteProps.options.find(
|
||
(option) => option.id === cityContent
|
||
);
|
||
setCityPreview(selectedCity?.name || "");
|
||
}, [cityContent, cityAutocompleteProps.options]);
|
||
|
||
useEffect(() => {
|
||
const selectedThumbnail = mediaAutocompleteProps.options.find(
|
||
(option) => option.id === thumbnailContent
|
||
);
|
||
setThumbnailPreview(
|
||
selectedThumbnail
|
||
? `${import.meta.env.VITE_KRBL_MEDIA}${
|
||
selectedThumbnail.id
|
||
}/download?token=${localStorage.getItem(TOKEN_KEY)}`
|
||
: null
|
||
);
|
||
}, [thumbnailContent, mediaAutocompleteProps.options]);
|
||
|
||
useEffect(() => {
|
||
const selectedWatermarkLU = mediaAutocompleteProps.options.find(
|
||
(option) => option.id === watermarkLUContent
|
||
);
|
||
setWatermarkLUPreview(
|
||
selectedWatermarkLU
|
||
? `${import.meta.env.VITE_KRBL_MEDIA}${
|
||
selectedWatermarkLU.id
|
||
}/download?token=${localStorage.getItem(TOKEN_KEY)}`
|
||
: null
|
||
);
|
||
}, [watermarkLUContent, mediaAutocompleteProps.options]);
|
||
|
||
useEffect(() => {
|
||
const selectedWatermarkRD = mediaAutocompleteProps.options.find(
|
||
(option) => option.id === watermarkRDContent
|
||
);
|
||
setWatermarkRDPreview(
|
||
selectedWatermarkRD
|
||
? `${import.meta.env.VITE_KRBL_MEDIA}${
|
||
selectedWatermarkRD.id
|
||
}/download?token=${localStorage.getItem(TOKEN_KEY)}`
|
||
: null
|
||
);
|
||
}, [watermarkRDContent, mediaAutocompleteProps.options]);
|
||
|
||
useEffect(() => {
|
||
const selectedLeftArticle = articleAutocompleteProps.options.find(
|
||
(option) => option.id === leftArticleContent
|
||
);
|
||
setLeftArticlePreview(selectedLeftArticle?.heading || "");
|
||
}, [leftArticleContent, articleAutocompleteProps.options]);
|
||
|
||
useEffect(() => {
|
||
const selectedPreviewArticle = articleAutocompleteProps.options.find(
|
||
(option) => option.id === previewArticleContent
|
||
);
|
||
setPreviewArticlePreview(selectedPreviewArticle?.heading || "");
|
||
}, [previewArticleContent, articleAutocompleteProps.options]);
|
||
|
||
return (
|
||
<Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
|
||
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
|
||
<Tabs
|
||
value={tabValue}
|
||
onChange={(_, newValue) => setTabValue(newValue)}
|
||
aria-label="basic tabs example"
|
||
>
|
||
<Tab label="Основная информация" {...a11yProps(1)} />
|
||
<Tab label="Левый виджет" {...a11yProps(2)} />
|
||
<Tab label="Правый информация" {...a11yProps(3)} />
|
||
</Tabs>
|
||
</Box>
|
||
|
||
<CustomTabPanel value={tabValue} index={0}>
|
||
<Edit saveButtonProps={saveButtonProps}>
|
||
<Box sx={{ display: "flex", gap: 2 }}>
|
||
<Box
|
||
sx={{
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
flex: 1,
|
||
gap: 10,
|
||
justifyContent: "space-between",
|
||
}}
|
||
>
|
||
{/* Language Selection */}
|
||
|
||
<Box
|
||
sx={{
|
||
display: "flex",
|
||
gap: 2,
|
||
}}
|
||
>
|
||
<Box
|
||
sx={{
|
||
cursor: "pointer",
|
||
flex: 1,
|
||
display: "flex",
|
||
justifyContent: "center",
|
||
bgcolor: language === "ru" ? "primary.main" : "transparent",
|
||
color: language === "ru" ? "white" : "inherit",
|
||
p: 1,
|
||
borderRadius: 1,
|
||
}}
|
||
onClick={() => setLanguageAction("ru")}
|
||
>
|
||
RU
|
||
</Box>
|
||
<Box
|
||
sx={{
|
||
cursor: "pointer",
|
||
flex: 1,
|
||
display: "flex",
|
||
justifyContent: "center",
|
||
bgcolor: language === "en" ? "primary.main" : "transparent",
|
||
color: language === "en" ? "white" : "inherit",
|
||
p: 1,
|
||
borderRadius: 1,
|
||
}}
|
||
onClick={() => setLanguageAction("en")}
|
||
>
|
||
EN
|
||
</Box>
|
||
<Box
|
||
sx={{
|
||
cursor: "pointer",
|
||
flex: 1,
|
||
display: "flex",
|
||
justifyContent: "center",
|
||
bgcolor: language === "zh" ? "primary.main" : "transparent",
|
||
color: language === "zh" ? "white" : "inherit",
|
||
p: 1,
|
||
borderRadius: 1,
|
||
}}
|
||
onClick={() => setLanguageAction("zh")}
|
||
>
|
||
ZH
|
||
</Box>
|
||
</Box>
|
||
|
||
{/* Форма редактирования */}
|
||
<Box
|
||
component="form"
|
||
sx={{ flex: 1, display: "flex", flexDirection: "column" }}
|
||
autoComplete="off"
|
||
>
|
||
<TextField
|
||
{...register("name", {
|
||
required: "Это поле является обязательным",
|
||
})}
|
||
error={!!(errors as any)?.name}
|
||
helperText={(errors as any)?.name?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{ shrink: true }}
|
||
type="text"
|
||
label={"Название *"}
|
||
name="name"
|
||
/>
|
||
<TextField
|
||
value={`${coordinatesPreview.latitude}, ${coordinatesPreview.longitude}`}
|
||
onChange={handleCoordinatesChange}
|
||
error={!!(errors as any)?.latitude}
|
||
helperText={(errors as any)?.latitude?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{ shrink: true }}
|
||
type="text"
|
||
label={"Координаты *"}
|
||
/>
|
||
<input
|
||
type="hidden"
|
||
{...register("longitude", {
|
||
value: coordinatesPreview.longitude,
|
||
required: "Это поле является обязательным",
|
||
valueAsNumber: true,
|
||
})}
|
||
/>
|
||
<input
|
||
type="hidden"
|
||
{...register("latitude", {
|
||
value: coordinatesPreview.latitude,
|
||
required: "Это поле является обязательным",
|
||
valueAsNumber: true,
|
||
})}
|
||
/>
|
||
|
||
{/*
|
||
<TextField
|
||
{...register("longitude", {
|
||
required: "Это поле является обязательным",
|
||
valueAsNumber: true,
|
||
})}
|
||
error={!!(errors as any)?.longitude}
|
||
helperText={(errors as any)?.longitude?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{ shrink: true }}
|
||
type="number"
|
||
label={"Долгота *"}
|
||
name="longitude"
|
||
/> */}
|
||
|
||
{/* <TextField
|
||
{...register("coordinates", {
|
||
required: "Это поле является обязательным",
|
||
valueAsNumber: true,
|
||
})}
|
||
error={!!(errors as any)?.coordinates}
|
||
helperText={(errors as any)?.coordinates?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{ shrink: true }}
|
||
type="number"
|
||
label={"Координаты *"}
|
||
name="coordinates"
|
||
/> */}
|
||
|
||
<TextField
|
||
{...register("address", {
|
||
required: "Это поле является обязательным",
|
||
})}
|
||
error={!!(errors as any)?.address}
|
||
helperText={(errors as any)?.address?.message}
|
||
margin="normal"
|
||
fullWidth
|
||
InputLabelProps={{ shrink: true }}
|
||
type="text"
|
||
label={"Адрес *"}
|
||
name="address"
|
||
/>
|
||
|
||
<Controller
|
||
control={control}
|
||
name="city_id"
|
||
rules={{ required: "Это поле является обязательным" }}
|
||
defaultValue={null}
|
||
render={({ field }) => (
|
||
<Autocomplete
|
||
{...cityAutocompleteProps}
|
||
value={
|
||
cityAutocompleteProps.options.find(
|
||
(option) => option.id === field.value
|
||
) || null
|
||
}
|
||
onChange={(_, value) => {
|
||
field.onChange(value?.id || "");
|
||
}}
|
||
getOptionLabel={(item) => {
|
||
return item ? item.name : "";
|
||
}}
|
||
isOptionEqualToValue={(option, value) => {
|
||
return option.id === value?.id;
|
||
}}
|
||
filterOptions={(options, { inputValue }) => {
|
||
return options.filter((option) =>
|
||
option.name
|
||
.toLowerCase()
|
||
.includes(inputValue.toLowerCase())
|
||
);
|
||
}}
|
||
renderInput={(params) => (
|
||
<TextField
|
||
{...params}
|
||
label="Выберите город"
|
||
margin="normal"
|
||
variant="outlined"
|
||
error={!!errors.city_id}
|
||
helperText={(errors as any)?.city_id?.message}
|
||
required
|
||
/>
|
||
)}
|
||
/>
|
||
)}
|
||
/>
|
||
|
||
<Controller
|
||
control={control}
|
||
name="thumbnail"
|
||
defaultValue={null}
|
||
render={({ field }) => (
|
||
<Autocomplete
|
||
{...mediaAutocompleteProps}
|
||
value={
|
||
mediaAutocompleteProps.options.find(
|
||
(option) => option.id === field.value
|
||
) || null
|
||
}
|
||
onChange={(_, value) => {
|
||
field.onChange(value?.id || "");
|
||
}}
|
||
getOptionLabel={(item) => {
|
||
return item ? item.media_name : "";
|
||
}}
|
||
isOptionEqualToValue={(option, value) => {
|
||
return option.id === value?.id;
|
||
}}
|
||
filterOptions={(options, { inputValue }) => {
|
||
return options.filter((option) =>
|
||
option.media_name
|
||
.toLowerCase()
|
||
.includes(inputValue.toLowerCase())
|
||
);
|
||
}}
|
||
renderInput={(params) => (
|
||
<TextField
|
||
{...params}
|
||
label="Выберите обложку"
|
||
margin="normal"
|
||
variant="outlined"
|
||
error={!!errors.arms}
|
||
helperText={(errors as any)?.arms?.message}
|
||
required
|
||
/>
|
||
)}
|
||
/>
|
||
)}
|
||
/>
|
||
|
||
<Controller
|
||
control={control}
|
||
name="watermark_lu"
|
||
defaultValue={null}
|
||
render={({ field }) => (
|
||
<Autocomplete
|
||
{...mediaAutocompleteProps}
|
||
value={
|
||
mediaAutocompleteProps.options.find(
|
||
(option) => option.id === field.value
|
||
) || null
|
||
}
|
||
onChange={(_, value) => {
|
||
field.onChange(value?.id || "");
|
||
}}
|
||
getOptionLabel={(item) => {
|
||
return item ? item.media_name : "";
|
||
}}
|
||
isOptionEqualToValue={(option, value) => {
|
||
return option.id === value?.id;
|
||
}}
|
||
filterOptions={(options, { inputValue }) => {
|
||
return options.filter((option) =>
|
||
option.media_name
|
||
.toLowerCase()
|
||
.includes(inputValue.toLowerCase())
|
||
);
|
||
}}
|
||
renderInput={(params) => (
|
||
<TextField
|
||
{...params}
|
||
label="Выберите водный знак (Левый верх)"
|
||
margin="normal"
|
||
variant="outlined"
|
||
error={!!errors.arms}
|
||
helperText={(errors as any)?.arms?.message}
|
||
required
|
||
/>
|
||
)}
|
||
/>
|
||
)}
|
||
/>
|
||
|
||
<Controller
|
||
control={control}
|
||
name="watermark_rd"
|
||
defaultValue={null}
|
||
render={({ field }) => (
|
||
<Autocomplete
|
||
{...mediaAutocompleteProps}
|
||
value={
|
||
mediaAutocompleteProps.options.find(
|
||
(option) => option.id === field.value
|
||
) || null
|
||
}
|
||
onChange={(_, value) => {
|
||
field.onChange(value?.id || "");
|
||
}}
|
||
getOptionLabel={(item) => {
|
||
return item ? item.media_name : "";
|
||
}}
|
||
isOptionEqualToValue={(option, value) => {
|
||
return option.id === value?.id;
|
||
}}
|
||
filterOptions={(options, { inputValue }) => {
|
||
return options.filter((option) =>
|
||
option.media_name
|
||
.toLowerCase()
|
||
.includes(inputValue.toLowerCase())
|
||
);
|
||
}}
|
||
renderInput={(params) => (
|
||
<TextField
|
||
{...params}
|
||
label="Выберите водный знак (Правый вверх)"
|
||
margin="normal"
|
||
variant="outlined"
|
||
error={!!errors.arms}
|
||
helperText={(errors as any)?.arms?.message}
|
||
required
|
||
/>
|
||
)}
|
||
/>
|
||
)}
|
||
/>
|
||
|
||
<Controller
|
||
control={control}
|
||
name="left_article"
|
||
defaultValue={null}
|
||
render={({ field }) => (
|
||
<Autocomplete
|
||
{...articleAutocompleteProps}
|
||
value={
|
||
articleAutocompleteProps.options.find(
|
||
(option) => option.id === field.value
|
||
) || null
|
||
}
|
||
onChange={(_, value) => {
|
||
field.onChange(value?.id || "");
|
||
}}
|
||
getOptionLabel={(item) => {
|
||
return item ? item.heading : "";
|
||
}}
|
||
isOptionEqualToValue={(option, value) => {
|
||
return option.id === value?.id;
|
||
}}
|
||
filterOptions={(options, { inputValue }) => {
|
||
return options.filter((option) =>
|
||
option.heading
|
||
.toLowerCase()
|
||
.includes(inputValue.toLowerCase())
|
||
);
|
||
}}
|
||
renderInput={(params) => (
|
||
<TextField
|
||
{...params}
|
||
label="Левая статья"
|
||
margin="normal"
|
||
variant="outlined"
|
||
error={!!errors.arms}
|
||
helperText={(errors as any)?.arms?.message}
|
||
required
|
||
/>
|
||
)}
|
||
/>
|
||
)}
|
||
/>
|
||
|
||
<Controller
|
||
control={control}
|
||
name="preview_article"
|
||
defaultValue={null}
|
||
render={({ field }) => (
|
||
<Autocomplete
|
||
{...articleAutocompleteProps}
|
||
value={
|
||
articleAutocompleteProps.options.find(
|
||
(option) => option.id === field.value
|
||
) || null
|
||
}
|
||
onChange={(_, value) => {
|
||
field.onChange(value?.id || "");
|
||
}}
|
||
getOptionLabel={(item) => {
|
||
return item ? item.heading : "";
|
||
}}
|
||
isOptionEqualToValue={(option, value) => {
|
||
return option.id === value?.id;
|
||
}}
|
||
filterOptions={(options, { inputValue }) => {
|
||
return options.filter((option) =>
|
||
option.heading
|
||
.toLowerCase()
|
||
.includes(inputValue.toLowerCase())
|
||
);
|
||
}}
|
||
renderInput={(params) => (
|
||
<TextField
|
||
{...params}
|
||
label="Cтатья-предпросмотр"
|
||
margin="normal"
|
||
variant="outlined"
|
||
error={!!errors.arms}
|
||
helperText={(errors as any)?.arms?.message}
|
||
required
|
||
/>
|
||
)}
|
||
/>
|
||
)}
|
||
/>
|
||
</Box>
|
||
</Box>
|
||
|
||
{/* Блок предпросмотра */}
|
||
<Paper
|
||
sx={{
|
||
flex: 1,
|
||
p: 2,
|
||
|
||
position: "sticky",
|
||
top: 16,
|
||
borderRadius: 2,
|
||
border: "1px solid",
|
||
borderColor: "primary.main",
|
||
bgcolor: (theme) =>
|
||
theme.palette.mode === "dark" ? "background.paper" : "#fff",
|
||
}}
|
||
>
|
||
<Typography variant="h6" gutterBottom color="primary">
|
||
Предпросмотр
|
||
</Typography>
|
||
|
||
{/* Название достопримечательности */}
|
||
<Typography
|
||
variant="h4"
|
||
gutterBottom
|
||
sx={{
|
||
color: (theme) =>
|
||
theme.palette.mode === "dark" ? "grey.300" : "grey.800",
|
||
mb: 3,
|
||
}}
|
||
>
|
||
{namePreview}
|
||
</Typography>
|
||
|
||
{/* Город */}
|
||
<Typography variant="body1" sx={{ mb: 2 }}>
|
||
<Box component="span" sx={{ color: "text.secondary" }}>
|
||
Город:{" "}
|
||
</Box>
|
||
<Box
|
||
component="span"
|
||
sx={{
|
||
color: (theme) =>
|
||
theme.palette.mode === "dark" ? "grey.300" : "grey.800",
|
||
}}
|
||
>
|
||
{cityPreview}
|
||
</Box>
|
||
</Typography>
|
||
|
||
{/* Адрес */}
|
||
<Typography variant="body1" sx={{ mb: 2 }}>
|
||
<Box component="span" sx={{ color: "text.secondary" }}>
|
||
Адрес:{" "}
|
||
</Box>
|
||
<Box
|
||
component="span"
|
||
sx={{
|
||
color: (theme) =>
|
||
theme.palette.mode === "dark" ? "grey.300" : "grey.800",
|
||
}}
|
||
>
|
||
{addressContent}
|
||
</Box>
|
||
</Typography>
|
||
|
||
{/* Координаты */}
|
||
<Typography variant="body1" sx={{ mb: 2 }}>
|
||
<Box component="span" sx={{ color: "text.secondary" }}>
|
||
Координаты:{" "}
|
||
</Box>
|
||
<Box
|
||
component="span"
|
||
sx={{
|
||
color: (theme) =>
|
||
theme.palette.mode === "dark" ? "grey.300" : "grey.800",
|
||
}}
|
||
>
|
||
{`${coordinatesPreview.latitude}, ${coordinatesPreview.longitude}`}
|
||
</Box>
|
||
</Typography>
|
||
|
||
{/* Обложка */}
|
||
{thumbnailPreview && (
|
||
<Box sx={{ mb: 2 }}>
|
||
<Typography
|
||
variant="body1"
|
||
gutterBottom
|
||
sx={{ color: "text.secondary" }}
|
||
>
|
||
Обложка:
|
||
</Typography>
|
||
<Box
|
||
component="img"
|
||
src={thumbnailPreview}
|
||
alt="Обложка"
|
||
sx={{
|
||
maxWidth: "100%",
|
||
height: "40vh",
|
||
borderRadius: 2,
|
||
border: "1px solid",
|
||
borderColor: "primary.main",
|
||
}}
|
||
/>
|
||
</Box>
|
||
)}
|
||
|
||
{/* Водяные знаки */}
|
||
<Box sx={{ mb: 2 }}>
|
||
<Typography
|
||
variant="body1"
|
||
gutterBottom
|
||
sx={{ color: "text.secondary" }}
|
||
>
|
||
Водяные знаки:
|
||
</Typography>
|
||
<Box sx={{ display: "flex", gap: 2 }}>
|
||
{watermarkLUPreview && (
|
||
<Box>
|
||
<Typography
|
||
variant="body2"
|
||
gutterBottom
|
||
sx={{ color: "text.secondary" }}
|
||
>
|
||
Левый верхний:
|
||
</Typography>
|
||
<Box
|
||
component="img"
|
||
src={watermarkLUPreview}
|
||
alt="Водяной знак (ЛВ)"
|
||
sx={{
|
||
width: 100,
|
||
height: 100,
|
||
objectFit: "cover",
|
||
borderRadius: 1,
|
||
border: "1px solid",
|
||
borderColor: "primary.main",
|
||
}}
|
||
/>
|
||
</Box>
|
||
)}
|
||
{watermarkRDPreview && (
|
||
<Box>
|
||
<Typography
|
||
variant="body2"
|
||
gutterBottom
|
||
sx={{ color: "text.secondary" }}
|
||
>
|
||
Правый верхний:
|
||
</Typography>
|
||
<Box
|
||
component="img"
|
||
src={watermarkRDPreview}
|
||
alt="Водяной знак (ПН)"
|
||
sx={{
|
||
width: 100,
|
||
height: 100,
|
||
objectFit: "cover",
|
||
borderRadius: 1,
|
||
border: "1px solid",
|
||
borderColor: "primary.main",
|
||
}}
|
||
/>
|
||
</Box>
|
||
)}
|
||
</Box>
|
||
</Box>
|
||
|
||
{/* Связанные статьи */}
|
||
<Box>
|
||
{/* <Typography variant="body1" gutterBottom sx={{color: 'text.secondary'}}>
|
||
Связанные статьи:
|
||
</Typography> */}
|
||
{leftArticlePreview && (
|
||
<Typography variant="body1" gutterBottom>
|
||
<Box component="span" sx={{ color: "text.secondary" }}>
|
||
Левая статья:{" "}
|
||
</Box>
|
||
<Box
|
||
component={Link}
|
||
to={`/article/show/${watch("left_article")}`}
|
||
sx={{
|
||
color: (theme) =>
|
||
theme.palette.mode === "dark"
|
||
? "grey.300"
|
||
: "grey.800",
|
||
textDecoration: "none",
|
||
"&:hover": {
|
||
textDecoration: "underline",
|
||
},
|
||
}}
|
||
>
|
||
{leftArticlePreview}
|
||
</Box>
|
||
</Typography>
|
||
)}
|
||
{previewArticlePreview && (
|
||
<Typography variant="body1" gutterBottom>
|
||
<Box component="span" sx={{ color: "text.secondary" }}>
|
||
Статья-предпросмотр:{" "}
|
||
</Box>
|
||
<Box
|
||
component={Link}
|
||
to={`/article/show/${watch("preview_article")}`}
|
||
sx={{
|
||
color: (theme) =>
|
||
theme.palette.mode === "dark"
|
||
? "grey.300"
|
||
: "grey.800",
|
||
textDecoration: "none",
|
||
"&:hover": {
|
||
textDecoration: "underline",
|
||
},
|
||
}}
|
||
>
|
||
{previewArticlePreview}
|
||
</Box>
|
||
</Typography>
|
||
)}
|
||
</Box>
|
||
</Paper>
|
||
</Box>
|
||
<Box sx={{ mt: 3 }}>
|
||
<LinkedItems<ArticleItem>
|
||
type="edit"
|
||
parentId={sightId!}
|
||
parentResource="sight"
|
||
childResource="article"
|
||
fields={articleFields}
|
||
title="статьи"
|
||
/>
|
||
|
||
<CreateSightArticle
|
||
parentId={sightId!}
|
||
parentResource="sight"
|
||
childResource="article"
|
||
title="статью"
|
||
/>
|
||
</Box>
|
||
</Edit>
|
||
</CustomTabPanel>
|
||
<CustomTabPanel value={tabValue} index={1}>
|
||
1
|
||
</CustomTabPanel>
|
||
<CustomTabPanel value={tabValue} index={2}>
|
||
2
|
||
</CustomTabPanel>
|
||
</Box>
|
||
);
|
||
});
|