207 lines
6.1 KiB
TypeScript
207 lines
6.1 KiB
TypeScript
import {
|
||
Button,
|
||
Paper,
|
||
TextField,
|
||
Select,
|
||
MenuItem,
|
||
FormControl,
|
||
InputLabel,
|
||
} from "@mui/material";
|
||
import { observer } from "mobx-react-lite";
|
||
import { ArrowLeft, Save } from "lucide-react";
|
||
import { Loader2 } from "lucide-react";
|
||
import { useNavigate } from "react-router-dom";
|
||
import { toast } from "react-toastify";
|
||
import { stationsStore, languageStore, cityStore } from "@shared";
|
||
import { useEffect, useState } from "react";
|
||
import { LanguageSwitcher } from "@widgets";
|
||
|
||
export const StationCreatePage = observer(() => {
|
||
const navigate = useNavigate();
|
||
const [isLoading, setIsLoading] = useState(false);
|
||
const { language } = languageStore;
|
||
const {
|
||
createStationData,
|
||
setCreateCommonData,
|
||
createStation,
|
||
setLanguageCreateStationData,
|
||
} = stationsStore;
|
||
const { cities, getCities } = cityStore;
|
||
const [coordinates, setCoordinates] = useState<string>("");
|
||
|
||
useEffect(() => {
|
||
if (
|
||
createStationData.common.latitude !== 0 ||
|
||
createStationData.common.longitude !== 0
|
||
) {
|
||
setCoordinates(
|
||
`${createStationData.common.latitude}, ${createStationData.common.longitude}`
|
||
);
|
||
}
|
||
}, [createStationData.common.latitude, createStationData.common.longitude]);
|
||
|
||
const handleCreate = async () => {
|
||
try {
|
||
setIsLoading(true);
|
||
await createStation();
|
||
toast.success("Остановка успешно создана");
|
||
navigate("/station");
|
||
} catch (error) {
|
||
console.error("Error creating station:", error);
|
||
toast.error("Ошибка при создании станции");
|
||
} finally {
|
||
setIsLoading(false);
|
||
}
|
||
};
|
||
|
||
useEffect(() => {
|
||
const fetchCities = async () => {
|
||
await getCities("ru");
|
||
await getCities("en");
|
||
await getCities("zh");
|
||
};
|
||
|
||
fetchCities();
|
||
}, []);
|
||
|
||
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"
|
||
onClick={() => navigate(-1)}
|
||
>
|
||
<ArrowLeft size={20} />
|
||
Назад
|
||
</button>
|
||
</div>
|
||
|
||
<div className="flex flex-col gap-10 w-full items-end">
|
||
<div className="flex gap-10 items-center mb-5 max-w-[80%] self-start">
|
||
<h1 className="text-3xl break-words">Создание остановки</h1>
|
||
</div>
|
||
<TextField
|
||
fullWidth
|
||
label="Название"
|
||
value={createStationData[language].name || ""}
|
||
required
|
||
onChange={(e) =>
|
||
setLanguageCreateStationData(language, {
|
||
name: e.target.value,
|
||
})
|
||
}
|
||
/>
|
||
|
||
<FormControl fullWidth>
|
||
<InputLabel id="direction-label">Прямой/обратный маршрут</InputLabel>
|
||
<Select
|
||
labelId="direction-label"
|
||
value={createStationData.common.direction ? "Прямой" : "Обратный"}
|
||
label="Прямой/обратный маршрут"
|
||
onChange={(e) =>
|
||
setCreateCommonData({
|
||
direction: e.target.value === "Прямой",
|
||
})
|
||
}
|
||
>
|
||
<MenuItem value="Прямой">Прямой</MenuItem>
|
||
<MenuItem value="Обратный">Обратный</MenuItem>
|
||
</Select>
|
||
</FormControl>
|
||
|
||
<TextField
|
||
fullWidth
|
||
label="Описание"
|
||
value={createStationData.common.description || ""}
|
||
onChange={(e) =>
|
||
setCreateCommonData({
|
||
description: e.target.value,
|
||
})
|
||
}
|
||
/>
|
||
|
||
{/* <TextField
|
||
fullWidth
|
||
label="Адрес"
|
||
value={createStationData[language].address || ""}
|
||
onChange={(e) =>
|
||
setLanguageCreateStationData(language, {
|
||
address: e.target.value,
|
||
})
|
||
}
|
||
/> */}
|
||
|
||
<TextField
|
||
fullWidth
|
||
label="Координаты"
|
||
value={coordinates}
|
||
onChange={(e) => {
|
||
const newValue = e.target.value;
|
||
setCoordinates(newValue);
|
||
|
||
const input = newValue.replace(/,/g, " ").trim();
|
||
const [latStr, lonStr] = input.split(/\s+/);
|
||
|
||
const lat = parseFloat(latStr);
|
||
const lon = parseFloat(lonStr);
|
||
|
||
const isValidLat = !isNaN(lat);
|
||
const isValidLon = !isNaN(lon);
|
||
|
||
if (isValidLat && isValidLon) {
|
||
setCreateCommonData({
|
||
latitude: lat,
|
||
longitude: lon,
|
||
});
|
||
} else {
|
||
setCreateCommonData({
|
||
latitude: 0,
|
||
longitude: 0,
|
||
});
|
||
}
|
||
}}
|
||
placeholder="Введите координаты в формате: широта долгота (можно использовать запятые или пробелы)"
|
||
/>
|
||
|
||
<FormControl fullWidth>
|
||
<InputLabel>Город</InputLabel>
|
||
<Select
|
||
value={createStationData.common.city_id || ""}
|
||
label="Город"
|
||
onChange={(e) => {
|
||
const selectedCity = cities["ru"].data.find(
|
||
(city) => city.id === e.target.value
|
||
);
|
||
setCreateCommonData({
|
||
city_id: e.target.value as number,
|
||
city: selectedCity?.name || "",
|
||
});
|
||
}}
|
||
>
|
||
{cities["ru"].data.map((city) => (
|
||
<MenuItem key={city.id} value={city.id}>
|
||
{city.name}
|
||
</MenuItem>
|
||
))}
|
||
</Select>
|
||
</FormControl>
|
||
|
||
<Button
|
||
variant="contained"
|
||
className="w-min flex gap-2 items-center"
|
||
startIcon={<Save size={20} />}
|
||
onClick={handleCreate}
|
||
disabled={isLoading || !createStationData[language]?.name}
|
||
>
|
||
{isLoading ? (
|
||
<Loader2 size={20} className="animate-spin" />
|
||
) : (
|
||
"Создать"
|
||
)}
|
||
</Button>
|
||
</div>
|
||
</Paper>
|
||
);
|
||
});
|