361 lines
10 KiB
TypeScript
361 lines
10 KiB
TypeScript
import {
|
|
Autocomplete,
|
|
Box,
|
|
TextField,
|
|
Typography,
|
|
FormControlLabel,
|
|
Paper,
|
|
Grid,
|
|
Checkbox,
|
|
} from "@mui/material";
|
|
import { Edit, useAutocomplete } from "@refinedev/mui";
|
|
import { useForm } from "@refinedev/react-hook-form";
|
|
import { Controller } from "react-hook-form";
|
|
|
|
import { useParams } from "react-router";
|
|
import { LinkedItems } from "../../components/LinkedItems";
|
|
import { type SightItem, sightFields } from "./types";
|
|
import { observer } from "mobx-react-lite";
|
|
import { languageStore } from "../../store/LanguageStore";
|
|
import { useEffect, useState } from "react";
|
|
import { LanguageSwitch } from "../../components/LanguageSwitch/index";
|
|
|
|
const TRANSFER_FIELDS = [
|
|
{ name: "bus", label: "Автобус" },
|
|
{ name: "metro_blue", label: "Метро (синяя)" },
|
|
{ name: "metro_green", label: "Метро (зеленая)" },
|
|
{ name: "metro_orange", label: "Метро (оранжевая)" },
|
|
{ name: "metro_purple", label: "Метро (фиолетовая)" },
|
|
{ name: "metro_red", label: "Метро (красная)" },
|
|
{ name: "train", label: "Электричка" },
|
|
{ name: "tram", label: "Трамвай" },
|
|
{ name: "trolleybus", label: "Троллейбус" },
|
|
];
|
|
|
|
export const StationEdit = observer(() => {
|
|
const { language, setLanguageAction } = languageStore;
|
|
const [stationData, setStationData] = useState({
|
|
ru: {
|
|
name: "",
|
|
system_name: "",
|
|
description: "",
|
|
address: "",
|
|
latitude: "",
|
|
longitude: "",
|
|
},
|
|
en: {
|
|
name: "",
|
|
system_name: "",
|
|
description: "",
|
|
address: "",
|
|
latitude: "",
|
|
longitude: "",
|
|
},
|
|
zh: {
|
|
name: "",
|
|
system_name: "",
|
|
description: "",
|
|
address: "",
|
|
latitude: "",
|
|
longitude: "",
|
|
},
|
|
});
|
|
|
|
const handleLanguageChange = () => {
|
|
setStationData((prevData) => ({
|
|
...prevData,
|
|
[language]: {
|
|
name: watch("name") ?? "",
|
|
system_name: watch("system_name") ?? "",
|
|
description: watch("description") ?? "",
|
|
address: watch("address") ?? "",
|
|
latitude: watch("latitude") ?? "",
|
|
longitude: watch("longitude") ?? "",
|
|
},
|
|
}));
|
|
};
|
|
|
|
const [coordinatesPreview, setCoordinatesPreview] = useState({
|
|
latitude: "",
|
|
longitude: "",
|
|
});
|
|
|
|
const {
|
|
saveButtonProps,
|
|
register,
|
|
control,
|
|
getValues,
|
|
setValue,
|
|
watch,
|
|
formState: { errors },
|
|
} = useForm({
|
|
refineCoreProps: {
|
|
meta: {
|
|
headers: { "Accept-Language": language },
|
|
},
|
|
},
|
|
});
|
|
|
|
const directions = [
|
|
{
|
|
label: "Прямой",
|
|
value: true,
|
|
},
|
|
{
|
|
label: "Обратный",
|
|
value: false,
|
|
},
|
|
];
|
|
|
|
const directionContent = watch("direction");
|
|
const [routeDirection, setRouteDirection] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (directionContent) {
|
|
setRouteDirection(directionContent);
|
|
}
|
|
}, [directionContent]);
|
|
|
|
useEffect(() => {
|
|
if (stationData[language as keyof typeof stationData]?.name) {
|
|
setValue("name", stationData[language as keyof typeof stationData]?.name);
|
|
}
|
|
if (stationData[language as keyof typeof stationData]?.address) {
|
|
setValue(
|
|
"system_name",
|
|
stationData[language as keyof typeof stationData]?.system_name || ""
|
|
);
|
|
}
|
|
if (stationData[language as keyof typeof stationData]?.description) {
|
|
setValue(
|
|
"description",
|
|
stationData[language as keyof typeof stationData]?.description || ""
|
|
);
|
|
}
|
|
if (stationData[language as keyof typeof stationData]?.latitude) {
|
|
setValue(
|
|
"latitude",
|
|
stationData[language as keyof typeof stationData]?.latitude || ""
|
|
);
|
|
}
|
|
if (stationData[language as keyof typeof stationData]?.longitude) {
|
|
setValue(
|
|
"longitude",
|
|
stationData[language as keyof typeof stationData]?.longitude || ""
|
|
);
|
|
}
|
|
}, [language, stationData, setValue]);
|
|
|
|
useEffect(() => {
|
|
setLanguageAction("ru");
|
|
}, []);
|
|
|
|
const { id: stationId } = useParams<{ id: string }>();
|
|
|
|
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 latitudeContent = watch("latitude");
|
|
const longitudeContent = watch("longitude");
|
|
|
|
useEffect(() => {
|
|
setCoordinatesPreview({
|
|
latitude: latitudeContent || "",
|
|
longitude: longitudeContent || "",
|
|
});
|
|
}, [latitudeContent, longitudeContent]);
|
|
|
|
const { autocompleteProps: cityAutocompleteProps } = useAutocomplete({
|
|
resource: "city",
|
|
onSearch: (value) => [
|
|
{
|
|
field: "name",
|
|
operator: "contains",
|
|
value,
|
|
},
|
|
],
|
|
|
|
meta: {
|
|
headers: {
|
|
"Accept-Language": "ru",
|
|
},
|
|
},
|
|
queryOptions: {
|
|
queryKey: ["city"],
|
|
},
|
|
});
|
|
|
|
return (
|
|
<Edit saveButtonProps={saveButtonProps}>
|
|
<Box
|
|
component="form"
|
|
sx={{ display: "flex", flexDirection: "column" }}
|
|
autoComplete="off"
|
|
>
|
|
<LanguageSwitch action={handleLanguageChange} />
|
|
<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
|
|
{...register("system_name", {
|
|
required: "Это поле является обязательным",
|
|
})}
|
|
error={!!(errors as any)?.system_name}
|
|
helperText={(errors as any)?.system_name?.message}
|
|
margin="normal"
|
|
fullWidth
|
|
InputLabelProps={{ shrink: true }}
|
|
type="text"
|
|
label={"Системное название *"}
|
|
name="system_name"
|
|
/>
|
|
|
|
<input
|
|
type="hidden"
|
|
{...register("direction", { value: routeDirection })}
|
|
/>
|
|
<Autocomplete
|
|
options={directions}
|
|
value={directions.find((el) => el.value == routeDirection)}
|
|
onChange={(_, element) => {
|
|
if (element) {
|
|
setValue("direction", element.value);
|
|
setRouteDirection(element.value);
|
|
}
|
|
}}
|
|
renderInput={(params) => (
|
|
<TextField
|
|
{...params}
|
|
label="Прямой/обратный маршрут"
|
|
margin="normal"
|
|
variant="outlined"
|
|
error={!!errors.direction}
|
|
helperText={(errors as any)?.direction?.message}
|
|
required
|
|
/>
|
|
)}
|
|
/>
|
|
<TextField
|
|
{...register("description", {
|
|
// required: 'Это поле является обязательным',
|
|
})}
|
|
error={!!(errors as any)?.description}
|
|
helperText={(errors as any)?.description?.message}
|
|
margin="normal"
|
|
fullWidth
|
|
InputLabelProps={{ shrink: true }}
|
|
type="text"
|
|
label={"Описание"}
|
|
name="description"
|
|
/>
|
|
<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"
|
|
/>
|
|
|
|
<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("latitude", {
|
|
value: coordinatesPreview.latitude,
|
|
})}
|
|
/>
|
|
<input
|
|
type="hidden"
|
|
{...register("longitude", { value: coordinatesPreview.longitude })}
|
|
/>
|
|
|
|
<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
|
|
/>
|
|
)}
|
|
/>
|
|
)}
|
|
/>
|
|
</Box>
|
|
|
|
{stationId && (
|
|
<LinkedItems<SightItem>
|
|
type="edit" // display and manage
|
|
parentId={stationId}
|
|
parentResource="station"
|
|
childResource="sight"
|
|
fields={sightFields}
|
|
title="достопримечательности"
|
|
dragAllowed={false}
|
|
/>
|
|
)}
|
|
</Edit>
|
|
);
|
|
});
|