fix: Update map with tables fixes
This commit is contained in:
@@ -6,34 +6,55 @@ import {
|
||||
MenuItem,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
// Typography,
|
||||
Typography,
|
||||
Box,
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
} from "@mui/material";
|
||||
import { LanguageSwitcher } from "@widgets";
|
||||
import { MediaViewer } from "@widgets";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { ArrowLeft, Save } from "lucide-react";
|
||||
import { ArrowLeft, Copy, Save, Plus } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
|
||||
import { carrierStore } from "../../../shared/store/CarrierStore";
|
||||
import { articlesStore } from "../../../shared/store/ArticlesStore";
|
||||
import { routeStore } from "../../../shared/store/RouteStore";
|
||||
import {
|
||||
routeStore,
|
||||
languageStore,
|
||||
SelectArticleModal,
|
||||
SelectMediaDialog,
|
||||
} from "@shared";
|
||||
import { toast } from "react-toastify";
|
||||
import { languageStore, stationsStore } from "@shared";
|
||||
import { stationsStore } from "@shared";
|
||||
import { LinkedItems } from "../LinekedStations";
|
||||
|
||||
export const RouteEditPage = observer(() => {
|
||||
const navigate = useNavigate();
|
||||
const { id } = useParams();
|
||||
const { editRouteData } = routeStore;
|
||||
const { editRouteData, copyRouteAction } = routeStore;
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isSelectArticleDialogOpen, setIsSelectArticleDialogOpen] =
|
||||
useState(false);
|
||||
const [isSelectVideoDialogOpen, setIsSelectVideoDialogOpen] = useState(false);
|
||||
const [isVideoPreviewOpen, setIsVideoPreviewOpen] = useState(false);
|
||||
const { language } = languageStore;
|
||||
const [coordinates, setCoordinates] = useState<string>("");
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
// Устанавливаем русский язык при загрузке страницы
|
||||
const response = await routeStore.getRoute(Number(id));
|
||||
routeStore.setEditRouteData(response);
|
||||
languageStore.setLanguage("ru");
|
||||
};
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
carrierStore.getCarriers(language);
|
||||
stationsStore.getStations();
|
||||
articlesStore.getArticleList();
|
||||
@@ -94,9 +115,43 @@ export const RouteEditPage = observer(() => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleCopy = async () => {
|
||||
await copyRouteAction(Number(id));
|
||||
toast.success("Маршрут успешно скопирован");
|
||||
};
|
||||
|
||||
const handleArticleSelect = (articleId: number) => {
|
||||
routeStore.setEditRouteData({
|
||||
governor_appeal: articleId,
|
||||
});
|
||||
setIsSelectArticleDialogOpen(false);
|
||||
};
|
||||
|
||||
const handleVideoSelect = (media: {
|
||||
id: string;
|
||||
filename: string;
|
||||
media_name?: string;
|
||||
media_type: number;
|
||||
}) => {
|
||||
routeStore.setEditRouteData({
|
||||
video_preview: media.id,
|
||||
});
|
||||
setIsSelectVideoDialogOpen(false);
|
||||
};
|
||||
|
||||
const handleVideoPreviewClick = () => {
|
||||
if (editRouteData.video_preview && editRouteData.video_preview !== "") {
|
||||
setIsVideoPreviewOpen(true);
|
||||
}
|
||||
};
|
||||
|
||||
// Получаем название выбранной статьи для отображения
|
||||
const selectedArticle = articlesStore.articleList.ru.data.find(
|
||||
(article) => article.id === editRouteData.governor_appeal
|
||||
);
|
||||
|
||||
return (
|
||||
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
||||
<LanguageSwitcher />
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
className="flex items-center gap-2"
|
||||
@@ -152,9 +207,11 @@ export const RouteEditPage = observer(() => {
|
||||
}
|
||||
/>
|
||||
<TextField
|
||||
className="w-full max-h-[300px] overflow-y-scroll -mt-5 h-full"
|
||||
className="w-full"
|
||||
label="Координаты маршрута"
|
||||
multiline
|
||||
minRows={4}
|
||||
minRows={2}
|
||||
maxRows={10}
|
||||
value={coordinates}
|
||||
onChange={(e) => {
|
||||
const newValue = e.target.value;
|
||||
@@ -190,10 +247,25 @@ export const RouteEditPage = observer(() => {
|
||||
helperText={
|
||||
typeof validateCoordinates(coordinates) === "string"
|
||||
? validateCoordinates(coordinates)
|
||||
: "Введите координаты в формате: широта долгота (можно использовать запятые или пробелы)"
|
||||
: "Формат: широта долгота"
|
||||
}
|
||||
placeholder="55.7558 37.6173
|
||||
55.7539 37.6208"
|
||||
placeholder="55.7558 37.6173 55.7539 37.6208"
|
||||
sx={{
|
||||
"& .MuiInputBase-root": {
|
||||
maxHeight: "500px",
|
||||
overflow: "auto",
|
||||
},
|
||||
"& .MuiInputBase-input": {
|
||||
fontFamily: "monospace",
|
||||
fontSize: "0.8rem",
|
||||
lineHeight: "1.2",
|
||||
padding: "8px 12px",
|
||||
},
|
||||
"& .MuiFormHelperText-root": {
|
||||
fontSize: "0.75rem",
|
||||
marginTop: "2px",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
className="w-full"
|
||||
@@ -206,28 +278,75 @@ export const RouteEditPage = observer(() => {
|
||||
})
|
||||
}
|
||||
/>
|
||||
<FormControl fullWidth required>
|
||||
<InputLabel>Обращение губернатора</InputLabel>
|
||||
<Select
|
||||
value={editRouteData.governor_appeal || ""}
|
||||
label="Обращение губернатора"
|
||||
onChange={(e) =>
|
||||
routeStore.setEditRouteData({
|
||||
governor_appeal: Number(e.target.value),
|
||||
})
|
||||
}
|
||||
disabled={articlesStore.articleList.ru.data.length === 0}
|
||||
>
|
||||
<MenuItem value="">Не выбрано</MenuItem>
|
||||
{articlesStore.articleList.ru.data.map(
|
||||
(a: (typeof articlesStore.articleList.ru.data)[number]) => (
|
||||
<MenuItem key={a.id} value={a.id}>
|
||||
{a.heading}
|
||||
</MenuItem>
|
||||
)
|
||||
)}
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
{/* Заменяем Select на кнопку для выбора статьи */}
|
||||
<Box className="flex flex-col gap-2">
|
||||
<label className="text-sm font-medium text-gray-700">
|
||||
Обращение к пассажирам
|
||||
</label>
|
||||
<Box className="flex gap-2">
|
||||
<TextField
|
||||
className="flex-1"
|
||||
value={selectedArticle?.heading || "Статья не выбрана"}
|
||||
placeholder="Выберите статью"
|
||||
disabled
|
||||
sx={{
|
||||
"& .MuiInputBase-input": {
|
||||
color: selectedArticle ? "inherit" : "#999",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => setIsSelectArticleDialogOpen(true)}
|
||||
startIcon={<Plus size={16} />}
|
||||
sx={{ minWidth: "auto", px: 2 }}
|
||||
>
|
||||
Выбрать
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Селектор видео превью */}
|
||||
<Box className="flex flex-col gap-2">
|
||||
<label className="text-sm font-medium text-gray-700">
|
||||
Видео превью
|
||||
</label>
|
||||
<Box className="flex gap-2">
|
||||
<Typography
|
||||
variant="body1"
|
||||
onClick={handleVideoPreviewClick}
|
||||
component="span"
|
||||
className="flex-1"
|
||||
sx={{
|
||||
color:
|
||||
editRouteData.video_preview &&
|
||||
editRouteData.video_preview !== ""
|
||||
? "inherit"
|
||||
: "#999",
|
||||
cursor:
|
||||
editRouteData.video_preview &&
|
||||
editRouteData.video_preview !== ""
|
||||
? "pointer"
|
||||
: "default",
|
||||
}}
|
||||
>
|
||||
{editRouteData.video_preview &&
|
||||
editRouteData.video_preview !== ""
|
||||
? "Видео выбрано"
|
||||
: "Видео не выбрано"}
|
||||
</Typography>
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => setIsSelectVideoDialogOpen(true)}
|
||||
startIcon={<Plus size={16} />}
|
||||
sx={{ minWidth: "auto", px: 2 }}
|
||||
>
|
||||
Выбрать
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<FormControl fullWidth required>
|
||||
<InputLabel>Прямой/обратный маршрут</InputLabel>
|
||||
<Select
|
||||
@@ -311,9 +430,21 @@ export const RouteEditPage = observer(() => {
|
||||
onUpdate={() => {
|
||||
routeStore.getRoute(Number(id));
|
||||
}}
|
||||
routeDirection={editRouteData.route_direction}
|
||||
/>
|
||||
|
||||
<div className="flex w-full justify-end">
|
||||
<div className="flex w-full justify-between">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
className="w-min flex gap-2 items-center"
|
||||
startIcon={<Copy size={20} />}
|
||||
onClick={handleCopy}
|
||||
disabled={isLoading}
|
||||
>
|
||||
Скопировать
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
@@ -326,6 +457,45 @@ export const RouteEditPage = observer(() => {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Модальное окно выбора статьи */}
|
||||
<SelectArticleModal
|
||||
open={isSelectArticleDialogOpen}
|
||||
onClose={() => setIsSelectArticleDialogOpen(false)}
|
||||
onSelectArticle={handleArticleSelect}
|
||||
/>
|
||||
|
||||
{/* Модальное окно выбора видео */}
|
||||
<SelectMediaDialog
|
||||
open={isSelectVideoDialogOpen}
|
||||
onClose={() => setIsSelectVideoDialogOpen(false)}
|
||||
onSelectMedia={handleVideoSelect}
|
||||
mediaType={2}
|
||||
/>
|
||||
|
||||
{/* Модальное окно предпросмотра видео */}
|
||||
<Dialog
|
||||
open={isVideoPreviewOpen}
|
||||
onClose={() => setIsVideoPreviewOpen(false)}
|
||||
maxWidth="md"
|
||||
fullWidth
|
||||
>
|
||||
<DialogTitle>Предпросмотр видео</DialogTitle>
|
||||
<DialogContent>
|
||||
<Box className="flex justify-center items-center p-4">
|
||||
<MediaViewer
|
||||
media={{
|
||||
id: editRouteData.video_preview,
|
||||
media_type: 2,
|
||||
filename: "video_preview",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setIsVideoPreviewOpen(false)}>Закрыть</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</Paper>
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user