diff --git a/src/pages/carrier/create.tsx b/src/pages/carrier/create.tsx
index 0fcf422..3144784 100644
--- a/src/pages/carrier/create.tsx
+++ b/src/pages/carrier/create.tsx
@@ -3,19 +3,63 @@ import { Create, useAutocomplete } from "@refinedev/mui";
import { useForm } from "@refinedev/react-hook-form";
import { Controller } from "react-hook-form";
import { observer } from "mobx-react-lite";
-import { languageStore, META_LANGUAGE } from "../../store/LanguageStore";
+import { META_LANGUAGE } from "../../store/LanguageStore";
+import { LanguageSwitch } from "@/components/LanguageSwitch";
+
+import { useEffect, useState } from "react";
+import { EVERY_LANGUAGE, Languages, languageStore } from "@stores";
+
export const CarrierCreate = observer(() => {
- const { language } = languageStore;
+ const { language, setLanguageAction } = languageStore;
const {
saveButtonProps,
refineCore: { formLoading },
register,
control,
+ setValue,
+ watch,
formState: { errors },
} = useForm({
- refineCoreProps: META_LANGUAGE(language)
+ refineCoreProps: META_LANGUAGE(language),
});
+ const [carrierData, setCarrierData] = useState({
+ full_name: EVERY_LANGUAGE(""),
+ short_name: EVERY_LANGUAGE(""),
+ slogan: EVERY_LANGUAGE(""),
+ });
+
+ useEffect(() => {
+ setValue("full_name", carrierData.full_name[language]);
+ setValue("short_name", carrierData.short_name[language]);
+ setValue("slogan", carrierData.slogan[language]);
+ }, [carrierData, language, setValue]);
+
+ function updateTranslations(update: boolean = true) {
+ const newCarrierData = {
+ ...carrierData,
+ full_name: {
+ ...carrierData.full_name,
+ [language]: watch("full_name") ?? "",
+ },
+ short_name: {
+ ...carrierData.short_name,
+ [language]: watch("short_name") ?? "",
+ },
+ slogan: {
+ ...carrierData.slogan,
+ [language]: watch("slogan") ?? "",
+ },
+ };
+ if (update) setCarrierData(newCarrierData);
+ return newCarrierData;
+ }
+
+ const handleLanguageChange = (lang: Languages) => {
+ updateTranslations();
+ setLanguageAction(lang);
+ };
+
const { autocompleteProps: cityAutocompleteProps } = useAutocomplete({
resource: "city",
onSearch: (value) => [
@@ -45,6 +89,7 @@ export const CarrierCreate = observer(() => {
sx={{ display: "flex", flexDirection: "column" }}
autoComplete="off"
>
+
{
helperText={(errors as any)?.full_name?.message}
margin="normal"
fullWidth
- slotProps={{inputLabel: {shrink: true}}}
+ slotProps={{ inputLabel: { shrink: true } }}
type="text"
label={"Полное имя *"}
name="full_name"
@@ -109,16 +154,13 @@ export const CarrierCreate = observer(() => {
helperText={(errors as any)?.short_name?.message}
margin="normal"
fullWidth
- slotProps={{inputLabel: {shrink: true}}}
+ slotProps={{ inputLabel: { shrink: true } }}
type="text"
label={"Короткое имя"}
name="short_name"
/>
-
+
{
helperText={(errors as any)?.main_color?.message}
margin="normal"
fullWidth
- slotProps={{inputLabel: {shrink: true}}}
+ slotProps={{ inputLabel: { shrink: true } }}
type="color"
label={"Основной цвет"}
name="main_color"
@@ -149,7 +191,7 @@ export const CarrierCreate = observer(() => {
helperText={(errors as any)?.left_color?.message}
margin="normal"
fullWidth
- slotProps={{inputLabel: {shrink: true}}}
+ slotProps={{ inputLabel: { shrink: true } }}
type="color"
label={"Цвет левого виджета"}
name="left_color"
@@ -172,7 +214,7 @@ export const CarrierCreate = observer(() => {
helperText={(errors as any)?.right_color?.message}
margin="normal"
fullWidth
- slotProps={{inputLabel: {shrink: true}}}
+ slotProps={{ inputLabel: { shrink: true } }}
type="color"
label={"Цвет правого виджета"}
name="right_color"
@@ -195,7 +237,7 @@ export const CarrierCreate = observer(() => {
helperText={(errors as any)?.slogan?.message}
margin="normal"
fullWidth
- slotProps={{inputLabel: {shrink: true}}}
+ slotProps={{ inputLabel: { shrink: true } }}
type="text"
label={"Слоган"}
name="slogan"
diff --git a/src/pages/city/create.tsx b/src/pages/city/create.tsx
index bb1a93c..647c1ea 100644
--- a/src/pages/city/create.tsx
+++ b/src/pages/city/create.tsx
@@ -1,97 +1,303 @@
-import {Autocomplete, Box, TextField} from '@mui/material'
-import {Create, useAutocomplete} from '@refinedev/mui'
-import {useForm} from '@refinedev/react-hook-form'
-import {Controller} from 'react-hook-form'
+import { Autocomplete, Box, TextField } from "@mui/material";
+import { Create, useAutocomplete } from "@refinedev/mui";
+import { useForm } from "@refinedev/react-hook-form";
+import { Controller } from "react-hook-form";
+import { useEffect, useState } from "react";
+import { EVERY_LANGUAGE, Languages, languageStore } from "@stores"; // Assuming these imports are correct and available
+import { LanguageSwitch } from "@/components/LanguageSwitch"; // Assuming this import is correct and available
+import { axiosInstance, axiosInstanceForGet } from "@/providers"; // Assuming these imports are correct and available
+import { useNavigate } from "react-router";
+import { useNotification } from "@refinedev/core";
export const CityCreate = () => {
+ const { language, setLanguageAction } = languageStore;
+ const navigate = useNavigate();
+ const notification = useNotification();
+ // State to hold all language translations for the city name.
+ // Initialized with an object where each language key maps to an empty string.
+ const [allLanguageNames, setAllLanguageNames] = useState<
+ Record
+ >(EVERY_LANGUAGE(""));
+
const {
saveButtonProps,
- refineCore: {formLoading},
- register,
- control,
- formState: {errors},
- } = useForm({})
+ refineCore: { formLoading }, // Indicates if the form is currently loading data
+ register, // Function to register input fields with react-hook-form
+ control, // Object to pass to Controller for controlled components
+ setValue, // Function to programmatically set form values
+ watch, // Function to watch for changes in form values
+ handleSubmit, // Function to handle form submission, including validation
+ formState: { errors }, // Object containing form validation errors
+ } = useForm<{
+ name: string; // This field will hold the name for the *currently active* language
+ country_code: string; // The code for the selected country
+ arms: string; // The ID of the selected media for the city's arms (e.g., coat of arms)
+ }>({});
- const {autocompleteProps: countryAutocompleteProps} = useAutocomplete({
- resource: 'country',
- })
+ // useEffect hook to synchronize the 'name' TextField with the 'allLanguageNames' state.
+ // Whenever the active 'language' or the 'allLanguageNames' state changes,
+ // the 'name' field in the form is updated to display the correct translation.
+ useEffect(() => {
+ setValue("name", allLanguageNames[language]);
+ }, [language, allLanguageNames, setValue]);
- const {autocompleteProps: mediaAutocompleteProps} = useAutocomplete({
- resource: 'media',
+ // Function to update the 'allLanguageNames' state with the current value from the 'name' TextField.
+ // This is crucial to ensure that changes made by the user are saved before
+ // switching languages or submitting the form.
+ const updateCurrentLanguageName = () => {
+ const currentNameValue = watch("name"); // Get the current value typed into the 'name' TextField
+ setAllLanguageNames((prev) => ({
+ ...prev,
+ [language]: currentNameValue || "", // Update the specific language entry in the state
+ }));
+ };
+
+ // Handler for language switch.
+ // It first saves the current input for the active language, then changes the language.
+ const handleLanguageChange = (lang: Languages) => {
+ updateCurrentLanguageName(); // Save the current input before switching language
+ setLanguageAction(lang); // Update the global language state
+ };
+
+ // Autocomplete props for Country selection.
+ // 'resource' specifies the API endpoint, and it's assumed 'code' is the value
+ // to be stored and 'name' is the label to display.
+ const { autocompleteProps: countryAutocompleteProps } = useAutocomplete({
+ resource: "country",
+ });
+
+ // Autocomplete props for Media selection (specifically for city's arms).
+ // 'resource' specifies the API endpoint, and 'onSearch' provides a custom
+ // search filter based on 'media_name'.
+ const { autocompleteProps: mediaAutocompleteProps } = useAutocomplete({
+ resource: "media",
onSearch: (value) => [
{
- field: 'media_name',
- operator: 'contains',
+ field: "media_name",
+ operator: "contains",
value,
},
],
- })
+ });
+
+ // This function is called when the form is submitted and passes validation.
+ // It orchestrates the API calls for creating the city and updating its translations.
+ const onFinish = async (data: {
+ name: string;
+ country_code: string;
+ arms: string;
+ }) => {
+ // Ensure the very latest input for the current language is captured
+ // into 'allLanguageNames' before making API calls. This handles cases
+ // where the user might click 'Save' without blurring the 'name' field.
+ updateCurrentLanguageName();
+
+ // Create a final set of names including the latest value from the form
+ // for the current language.
+ const finalNames = {
+ ...allLanguageNames,
+ [language]: data.name, // Ensure the absolute latest value from the form is included
+ };
+
+ try {
+ // Validate that the Russian name is present, as it's used for the initial POST request.
+ if (!finalNames["ru"]) {
+ console.error("Russian name is required for initial city creation.");
+ // In a real application, you might want to display a user-friendly error message here.
+ return;
+ }
+
+ console.log("Submitting with names:", finalNames);
+
+ // 1. Create the city entry in Russian.
+ // This POST request typically returns the ID of the newly created resource.
+ const ruResponse = await axiosInstanceForGet("ru").post("/city", {
+ name: finalNames["ru"], // Russian name
+ country_code: data.country_code, // Country code from the form
+ arms: data.arms, // Arms ID from the form, included in initial creation
+ });
+
+ const id = ruResponse.data.id; // Extract the ID of the newly created city
+
+ // 2. Patch the city with the English name if available.
+ if (finalNames["en"]) {
+ await axiosInstanceForGet("en").patch(`/city/${id}`, {
+ name: finalNames["en"], // English name
+ country_code: data.country_code, // Country code from the form
+ arms: data.arms, // Arms ID from the form, included in initial creation
+ });
+ }
+
+ // 3. Patch the city with the Chinese name if available.
+ if (finalNames["zh"]) {
+ await axiosInstanceForGet("zh").patch(`/city/${id}`, {
+ name: finalNames["zh"], // Chinese name
+ country_code: data.country_code, // Country code from the form
+ arms: data.arms, // Arms ID from the form, included in initial creation
+ });
+ }
+
+ console.log("City created/updated successfully!");
+ if (notification && typeof notification.open === "function") {
+ notification.open({
+ message: "Город успешно создан",
+ type: "success",
+ });
+ }
+ window.onbeforeunload = null;
+ navigate("/city");
+
+ // After successful creation/update, you might want to:
+ // - Navigate to a different page (e.g., city list).
+ // - Display a success notification to the user.
+ } catch (error) {
+ console.error("Error creating/updating city:", error);
+ // Display an error message to the user if the API calls fail.
+ }
+ };
return (
-
-
+
+
+ {/* Language Switch component to change the active language */}
+
+
+ {/* Country Autocomplete field */}
(
+ control={control} // Pass control from useForm
+ name="country_code" // Field name in the form state
+ rules={{ required: "Это поле является обязательным" }} // Validation rule
+ defaultValue={null} // Initial value
+ render={({ field }) => (
option.code === field.value) || null}
- onChange={(_, value) => {
- field.onChange(value?.code || '')
+ {...countryAutocompleteProps} // Spread autocomplete props from useAutocomplete hook
+ value={
+ // Find the selected option based on the field's current value
+ countryAutocompleteProps.options.find(
+ (option: { code: string; name: string; id: string }) =>
+ option.code === field.value
+ ) || null
+ }
+ onChange={(
+ _,
+ value: { code: string; name: string; id: string } | null
+ ) => {
+ // Update the form field's value when an option is selected
+ field.onChange(value?.code || "");
}}
- getOptionLabel={(item) => {
- return item ? item.name : ''
+ getOptionLabel={(item: {
+ code: string;
+ name: string;
+ id: string;
+ }) => {
+ // Define how to display the label for each option
+ return item ? item.name : "";
}}
- isOptionEqualToValue={(option, value) => {
- return option.id === value?.id
+ isOptionEqualToValue={(
+ option: { code: string; name: string; id: string },
+ value: { code: string; name: string; id: string }
+ ) => {
+ // Define how to compare options for equality
+ return option.id === value?.id;
}}
- renderInput={(params) => }
+ renderInput={(params) => (
+
+ )}
/>
)}
/>
+ {/* City Name TextField for the current language */}
+ {/* Arms Autocomplete field */}
(
+ control={control} // Pass control from useForm
+ name="arms" // Field name in the form state
+ defaultValue={null} // Initial value
+ render={({ field }) => (
option.id === field.value) || null}
- onChange={(_, value) => {
- field.onChange(value?.id || '')
+ {...mediaAutocompleteProps} // Spread autocomplete props from useAutocomplete hook
+ value={
+ // Find the selected option based on the field's current value
+ mediaAutocompleteProps.options.find(
+ (option: { id: string; media_name: string }) =>
+ option.id === field.value
+ ) || null
+ }
+ onChange={(
+ _,
+ value: { id: string; media_name: string } | null
+ ) => {
+ // Update the form field's value when an option is selected
+ field.onChange(value?.id || "");
}}
- getOptionLabel={(item) => {
- return item ? item.media_name : ''
+ getOptionLabel={(item: { id: string; media_name: string }) => {
+ // Define how to display the label for each option
+ return item ? item.media_name : "";
}}
- isOptionEqualToValue={(option, value) => {
- return option.id === value?.id
+ isOptionEqualToValue={(
+ option: { id: string; media_name: string },
+ value: { id: string; media_name: string }
+ ) => {
+ // Define how to compare options for equality
+ return option.id === value?.id;
}}
- filterOptions={(options, {inputValue}) => {
- return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase()))
+ filterOptions={(
+ options: { id: string; media_name: string }[],
+ { inputValue }
+ ) => {
+ // Custom filter for options based on input value
+ return options.filter((option) =>
+ option.media_name
+ .toLowerCase()
+ .includes(inputValue.toLowerCase())
+ );
}}
- renderInput={(params) => }
+ renderInput={(params) => (
+
+ )}
/>
)}
/>
- )
-}
+ );
+};
diff --git a/src/pages/media/list.tsx b/src/pages/media/list.tsx
index d6e626e..b70320a 100644
--- a/src/pages/media/list.tsx
+++ b/src/pages/media/list.tsx
@@ -100,7 +100,6 @@ export const MediaList = observer(() => {
columns={columns}
localeText={localeText}
getRowId={(row: any) => row.id}
- languageEnabled
/>
);
diff --git a/src/pages/route-preview/Station.tsx b/src/pages/route-preview/Station.tsx
index 1128699..f262fe2 100644
--- a/src/pages/route-preview/Station.tsx
+++ b/src/pages/route-preview/Station.tsx
@@ -114,10 +114,10 @@ export const StationLabel = observer(
rotation={-rotation}
>
{
))}
diff --git a/src/pages/sight/create.tsx b/src/pages/sight/create.tsx
index f76f068..2be4644 100644
--- a/src/pages/sight/create.tsx
+++ b/src/pages/sight/create.tsx
@@ -22,6 +22,7 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
export const SightCreate = observer(() => {
const { language, setLanguageAction } = languageStore;
+ const [coordinates, setCoordinates] = useState("");
const [sightData, setSightData] = useState({
name: EVERY_LANGUAGE(""),
address: EVERY_LANGUAGE(""),
@@ -79,10 +80,7 @@ export const SightCreate = observer(() => {
});
const [namePreview, setNamePreview] = useState("");
- const [coordinatesPreview, setCoordinatesPreview] = useState({
- latitude: "",
- longitude: "",
- });
+ const [coordinatesPreview, setCoordinatesPreview] = useState("");
const [creatingArticleHeading, setCreatingArticleHeading] =
useState("");
@@ -102,13 +100,19 @@ export const SightCreate = observer(() => {
const [previewArticlePreview, setPreviewArticlePreview] = useState("");
const handleCoordinatesChange = (e: React.ChangeEvent) => {
- const [lat, lon] = e.target.value.split(",").map((s) => s.trim());
- setCoordinatesPreview({
- latitude: lat,
- longitude: lon,
- });
- setValue("latitude", lat);
- setValue("longitude", lon);
+ setCoordinates(e.target.value);
+ if (e.target.value) {
+ const [lat, lon] = e.target.value.split(" ").map((s) => s.trim());
+ setCoordinatesPreview(
+ `${lat ? Number(lat) : 0}, ${lon ? Number(lon) : 0}`
+ );
+ setValue("latitude", lat ? Number(lat) : 0);
+ setValue("longitude", lon ? Number(lon) : 0);
+ } else {
+ setCoordinatesPreview("");
+ setValue("latitude", "");
+ setValue("longitude", "");
+ }
};
// Автокомплиты
@@ -170,13 +174,6 @@ export const SightCreate = observer(() => {
setNamePreview(nameContent ?? "");
}, [nameContent]);
- useEffect(() => {
- setCoordinatesPreview({
- latitude: latitudeContent || "",
- longitude: longitudeContent || "",
- });
- }, [latitudeContent, longitudeContent]);
-
useEffect(() => {
const selectedCity = cityAutocompleteProps.options.find(
(option) => option.id === cityContent
@@ -276,7 +273,7 @@ export const SightCreate = observer(() => {
/>
{
type="text"
label={"Координаты *"}
/>
+
{
{
{/* Координаты */}
-
-
- Координаты:{" "}
-
-
- theme.palette.mode === "dark" ? "grey.300" : "grey.800",
- }}
- >
- {`${coordinatesPreview.latitude}, ${coordinatesPreview.longitude}`}
-
-
-
+ {coordinatesPreview && (
+
+
+ Координаты:{" "}
+
+
+ theme.palette.mode === "dark" ? "grey.300" : "grey.800",
+ }}
+ >
+ {coordinatesPreview}
+
+
+ )}
{/* Обложка */}
{thumbnailPreview && (
diff --git a/src/pages/sight/edit.tsx b/src/pages/sight/edit.tsx
index b995470..2a81981 100644
--- a/src/pages/sight/edit.tsx
+++ b/src/pages/sight/edit.tsx
@@ -70,6 +70,7 @@ export const SightEdit = observer(() => {
name: EVERY_LANGUAGE(""),
address: EVERY_LANGUAGE(""),
});
+ const [coordinates, setCoordinates] = useState("");
const {
saveButtonProps,
@@ -163,37 +164,13 @@ export const SightEdit = observer(() => {
setValue("address", sightData.address[language]);
}, [language, sightData, setValue]);
- useEffect(() => {
- const latitude = getValues("latitude");
- const longitude = getValues("longitude");
- if (latitude && longitude) {
- setCoordinatesPreview({
- latitude: latitude,
- longitude: longitude,
- });
- }
- }, [getValues]);
-
- const handleCoordinatesChange = (e: React.ChangeEvent) => {
- const [lat, lon] = e.target.value.split(",").map((s) => s.trim());
- setCoordinatesPreview({
- latitude: lat,
- longitude: lon,
- });
- setValue("latitude", lat);
- setValue("longitude", lon);
- };
-
// Состояния для предпросмотра
const [creatingArticleHeading, setCreatingArticleHeading] =
useState("");
const [creatingArticleBody, setCreatingArticleBody] = useState("");
- const [coordinatesPreview, setCoordinatesPreview] = useState({
- latitude: "",
- longitude: "",
- });
+ const [coordinatesPreview, setCoordinatesPreview] = useState("");
const [selectedArticleIndex, setSelectedArticleIndex] = useState(-1);
const [previewMediaFile, setPreviewMediaFile] = useState();
const [thumbnailPreview, setThumbnailPreview] = useState(null);
@@ -243,12 +220,25 @@ export const SightEdit = observer(() => {
const watermarkRDContent = watch("watermark_rd");
useEffect(() => {
- setCoordinatesPreview({
- latitude: latitudeContent ?? "",
- longitude: longitudeContent ?? "",
- });
+ if (latitudeContent && longitudeContent) {
+ setCoordinates(`${latitudeContent} ${longitudeContent}`);
+ }
}, [latitudeContent, longitudeContent]);
+ const handleCoordinatesChange = (e: React.ChangeEvent) => {
+ setCoordinates(e.target.value);
+ if (e.target.value) {
+ const [lat, lon] = e.target.value.split(" ").map((s) => s.trim());
+ setCoordinatesPreview(`${lat ?? "0"}, ${lon ?? "0"}`);
+ setValue("latitude", lat ?? "");
+ setValue("longitude", lon ?? "");
+ } else {
+ setCoordinatesPreview("");
+ setValue("latitude", "");
+ setValue("longitude", "");
+ }
+ };
+
useEffect(() => {
if (linkedArticles[selectedArticleIndex]?.id) {
getMedia(linkedArticles[selectedArticleIndex].id).then((media) => {
@@ -505,7 +495,6 @@ export const SightEdit = observer(() => {
{
{
/>
{
: "grey.800",
}}
>
- {`${coordinatesPreview.latitude}, ${coordinatesPreview.longitude}`}
+ {coordinatesPreview}
diff --git a/src/pages/sight/list.tsx b/src/pages/sight/list.tsx
index c309a41..a41b838 100644
--- a/src/pages/sight/list.tsx
+++ b/src/pages/sight/list.tsx
@@ -56,6 +56,7 @@ export const SightList = observer(() => {
display: "flex",
align: "left",
headerAlign: "left",
+ flex: 1,
},
{
field: "latitude",
diff --git a/src/pages/station/create.tsx b/src/pages/station/create.tsx
index aa6f266..42bbf67 100644
--- a/src/pages/station/create.tsx
+++ b/src/pages/station/create.tsx
@@ -41,40 +41,19 @@ export const StationCreate = () => {
},
});
- const [coordinatesPreview, setCoordinatesPreview] = useState({
- latitude: "",
- longitude: "",
- });
+ const [coordinates, setCoordinates] = useState("");
const handleCoordinatesChange = (e: React.ChangeEvent) => {
- const [lat, lon] = e.target.value.split(",").map((s) => s.trim());
- setCoordinatesPreview({
- latitude: lat,
- longitude: lon,
- });
+ setCoordinates(e.target.value);
+ const [lat, lon] = e.target.value
+ .replace(/,/g, "") // Remove all commas from the string
+ .split(" ")
+ .map((s) => s.trim());
+ console.log(lat, lon);
setValue("latitude", lat);
setValue("longitude", lon);
};
- const latitudeContent = watch("latitude");
- const longitudeContent = watch("longitude");
- useEffect(() => {
- setCoordinatesPreview({
- latitude: latitudeContent || "",
- longitude: longitudeContent || "",
- });
- }, [latitudeContent, longitudeContent]);
-
- useEffect(() => {
- const latitude = getValues("latitude");
- const longitude = getValues("longitude");
- if (latitude && longitude) {
- setCoordinatesPreview({
- latitude: latitude,
- longitude: longitude,
- });
- }
- }, [getValues]);
const directions = [
{
label: "Прямой",
@@ -188,7 +167,7 @@ export const StationCreate = () => {
)}
/>
{
type="text"
label={"Координаты *"}
/>
+
{
if (value === "") {
return 0;
@@ -213,7 +193,7 @@ export const StationCreate = () => {
{
if (value === "") {
return 0;
diff --git a/src/pages/station/edit.tsx b/src/pages/station/edit.tsx
index 24e09c7..395f01b 100644
--- a/src/pages/station/edit.tsx
+++ b/src/pages/station/edit.tsx
@@ -40,24 +40,24 @@ export const StationEdit = observer(() => {
system_name: "",
description: "",
address: "",
- latitude: "",
- longitude: "",
+ latitude: 0,
+ longitude: 0,
},
en: {
name: "",
system_name: "",
description: "",
address: "",
- latitude: "",
- longitude: "",
+ latitude: 0,
+ longitude: 0,
},
zh: {
name: "",
system_name: "",
description: "",
address: "",
- latitude: "",
- longitude: "",
+ latitude: 0,
+ longitude: 0,
},
});
@@ -69,8 +69,8 @@ export const StationEdit = observer(() => {
system_name: watch("system_name") ?? "",
description: watch("description") ?? "",
address: watch("address") ?? "",
- latitude: watch("latitude") ?? "",
- longitude: watch("longitude") ?? "",
+ latitude: Number(watch("latitude")) || 0,
+ longitude: Number(watch("longitude")) || 0,
},
}));
};
@@ -120,7 +120,7 @@ export const StationEdit = observer(() => {
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) {
+ if (stationData[language as keyof typeof stationData]?.system_name) {
setValue(
"system_name",
stationData[language as keyof typeof stationData]?.system_name || ""
@@ -132,16 +132,20 @@ export const StationEdit = observer(() => {
stationData[language as keyof typeof stationData]?.description || ""
);
}
- if (stationData[language as keyof typeof stationData]?.latitude) {
+ if (
+ stationData[language as keyof typeof stationData]?.latitude !== undefined
+ ) {
setValue(
"latitude",
- stationData[language as keyof typeof stationData]?.latitude || ""
+ stationData[language as keyof typeof stationData]?.latitude || 0
);
}
- if (stationData[language as keyof typeof stationData]?.longitude) {
+ if (
+ stationData[language as keyof typeof stationData]?.longitude !== undefined
+ ) {
setValue(
"longitude",
- stationData[language as keyof typeof stationData]?.longitude || ""
+ stationData[language as keyof typeof stationData]?.longitude || 0
);
}
}, [language, stationData, setValue]);
@@ -150,28 +154,36 @@ export const StationEdit = observer(() => {
setLanguageAction("ru");
}, []);
- const { id: stationId } = useParams<{ id: string }>();
+ const [coordinates, setCoordinates] = useState("");
- const handleCoordinatesChange = (e: React.ChangeEvent) => {
- const [lat, lon] = e.target.value.split(",").map((s) => s.trim());
- setCoordinatesPreview({
- latitude: lat,
- longitude: lon,
- });
- setValue("latitude", lat);
- setValue("longitude", lon);
- };
+ const { id: stationId } = useParams<{ id: string }>();
const latitudeContent = watch("latitude");
const longitudeContent = watch("longitude");
useEffect(() => {
- setCoordinatesPreview({
- latitude: latitudeContent || "",
- longitude: longitudeContent || "",
- });
+ if (latitudeContent && longitudeContent) {
+ setCoordinates(`${latitudeContent} ${longitudeContent}`);
+ }
}, [latitudeContent, longitudeContent]);
+ const handleCoordinatesChange = (e: React.ChangeEvent) => {
+ setCoordinates(e.target.value);
+ if (e.target.value) {
+ const [lat, lon] = e.target.value
+ .replace(/,/g, "") // Remove all commas from the string
+ .split(" ")
+ .map((s) => s.trim());
+ setCoordinates(`${lat ?? 0} ${lon ?? 0}`);
+ setValue("latitude", lat ?? 0);
+ setValue("longitude", lon ?? 0);
+ } else {
+ setCoordinates("");
+ setValue("latitude", "");
+ setValue("longitude", "");
+ }
+ };
+
const { autocompleteProps: cityAutocompleteProps } = useAutocomplete({
resource: "city",
onSearch: (value) => [
@@ -282,7 +294,7 @@ export const StationEdit = observer(() => {
/>
{
{
+ if (value === "") {
+ return 0;
+ }
+ return Number(value);
+ },
})}
/>
{
+ if (value === "") {
+ return 0;
+ }
+ return Number(value);
+ },
+ })}
/>
{
type: "string",
minWidth: 150,
display: "flex",
+ flex: 1,
align: "left",
headerAlign: "left",
renderCell: (params) => {
@@ -116,6 +117,7 @@ export const VehicleList = observer(() => {
headerName: "Город",
type: "string",
minWidth: 150,
+ flex: 1,
display: "flex",
align: "left",
headerAlign: "left",