diff --git a/src/AppRouter.jsx b/src/AppRouter.jsx
index 95834a1..c4eb65e 100755
--- a/src/AppRouter.jsx
+++ b/src/AppRouter.jsx
@@ -3,6 +3,7 @@ import Login from "./pages/Login";
import Home from "./pages/Home.jsx";
import Accessories from "./pages/Accessories.jsx";
import PrivateRoute from "./components/PrivateRoute";
+import Cities from "./pages/Cities.jsx";
const RoutesComponent = () => (
@@ -10,6 +11,7 @@ const RoutesComponent = () => (
}>
} />
} />
+ } />
);
diff --git a/src/api.jsx b/src/api.jsx
index 17a2ca5..a19295a 100755
--- a/src/api.jsx
+++ b/src/api.jsx
@@ -111,3 +111,62 @@ export const getCities = async () => {
throw error;
}
};
+
+export const createCity = async (cityData) => {
+ try {
+ const response = await axios.post(`${API_URL}/cities`, cityData, {
+ headers: {
+ Authorization: `Bearer ${getAuthToken()}`,
+ "Content-Type": "application/json",
+ },
+ });
+ return response.data;
+ } catch (error) {
+ console.log("Ошибка при создании города:", error);
+ throw error;
+ }
+};
+
+export const updateCity = async (id, cityData) => {
+ try {
+ const response = await axios.put(`${API_URL}/cities/${id}`, cityData, {
+ headers: {
+ Authorization: `Bearer ${getAuthToken()}`,
+ "Content-Type": "application/json",
+ },
+ });
+ return response.data;
+ } catch (error) {
+ console.log("Ошибка при обновлении города:", error);
+ throw error;
+ }
+};
+
+export const deleteCity = async (id) => {
+ try {
+ await axios.delete(`${API_URL}/cities/${id}`, {
+ headers: {
+ Authorization: `Bearer ${getAuthToken()}`,
+ Accept: "application/json",
+ },
+ });
+ } catch (error) {
+ console.log("Ошибка при удалении города:", error);
+ throw error;
+ }
+};
+
+export const getFederalDistricts = async () => {
+ try {
+ const response = await axios.get(`${API_URL}/federal-districts`, {
+ headers: {
+ Authorization: `Bearer ${getAuthToken()}`,
+ Accept: "application/json",
+ },
+ });
+ return response.data;
+ } catch (error) {
+ console.log("Ошибка при получении федеральных округов:", error);
+ throw error;
+ }
+};
diff --git a/src/components/Header.jsx b/src/components/Header.jsx
index 6285c4e..0f9b0e1 100644
--- a/src/components/Header.jsx
+++ b/src/components/Header.jsx
@@ -30,6 +30,11 @@ const Header = () => {
Компоненты
+
+
+ Города
+
+
{isAuthenticated ? (
diff --git a/src/pages/Cities.jsx b/src/pages/Cities.jsx
new file mode 100644
index 0000000..93b6f3f
--- /dev/null
+++ b/src/pages/Cities.jsx
@@ -0,0 +1,223 @@
+import React, { useState, useEffect } from "react";
+import SelectionDialog from "../components/SelectionDialog.jsx";
+import { useNavigate } from "react-router-dom";
+import { getAuthToken } from "../api.jsx";
+import {
+ getCities,
+ createCity,
+ updateCity,
+ deleteCity,
+ getFederalDistricts,
+} from "../api.jsx";
+
+const Cities = () => {
+ const [cities, setCities] = useState([]);
+ const [federalDistricts, setFederalDistricts] = useState([]);
+ const [newCity, setNewCity] = useState({
+ name: "",
+ federal_district_id: "",
+ });
+ const [editingCityId, setEditingCityId] = useState(null);
+ const [error, setError] = useState(null);
+ const [showDistrictDialog, setShowDistrictDialog] = useState(false);
+ const navigate = useNavigate();
+
+ useEffect(() => {
+ fetchCities();
+ fetchFederalDistricts();
+ }, []);
+
+ const fetchCities = async () => {
+ try {
+ const data = await getCities();
+ setCities(data);
+ } catch (error) {
+ console.error("Ошибка при загрузке городов:", error);
+ }
+ };
+
+ const fetchFederalDistricts = async () => {
+ try {
+ const data = await getFederalDistricts();
+ setFederalDistricts(data);
+ } catch (error) {
+ console.error("Ошибка при загрузке федеральных округов:", error);
+ }
+ };
+
+ const handleInputChange = (e) => {
+ const { name, value } = e.target;
+ setNewCity({ ...newCity, [name]: value });
+ };
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+
+ if (!newCity.name || !newCity.federal_district_id) {
+ setError("Пожалуйста, заполните все поля.");
+ return;
+ }
+
+ try {
+ if (editingCityId) {
+ await updateCity(editingCityId, newCity);
+ } else {
+ await createCity(newCity);
+ }
+ fetchCities();
+ resetForm();
+ } catch (error) {
+ console.error("Ошибка при добавлении или обновлении города:", error);
+ }
+ };
+
+ const handleEdit = (city) => {
+ setNewCity({
+ name: city.name,
+ federal_district_id: city.federal_district_id,
+ federal_district_name: city.federal_district_name,
+ });
+ setEditingCityId(city.id);
+ };
+
+ const handleDelete = async (cityId) => {
+ try {
+ await deleteCity(cityId);
+ fetchCities();
+ } catch (error) {
+ console.error("Ошибка при удалении города:", error);
+ }
+ };
+
+ const resetForm = () => {
+ setNewCity({
+ name: "",
+ federal_district_id: "",
+ });
+ setEditingCityId(null);
+ };
+
+ const handleDialogSelectDistrict = (selectedItem) => {
+ setNewCity({
+ ...newCity,
+ federal_district_id: selectedItem.id,
+ federal_district_name: selectedItem.name,
+ });
+ setShowDistrictDialog(false);
+ };
+
+ if (getAuthToken() === null) {
+ navigate("/login");
+ }
+
+ return (
+
+
Города
+
+
Список городов
+
+
+
+ | ID |
+ Название |
+ Федеральный округ |
+ Действия |
+
+
+
+ {cities.map((city) => (
+
+ | {city.id} |
+ {city.name} |
+ {city.federal_district_name} |
+
+
+
+
+
+ |
+
+ ))}
+
+
+
+
setShowDistrictDialog(false)}
+ items={federalDistricts}
+ columns={[
+ { key: "id", label: "ID" },
+ { key: "name", label: "Название" },
+ ]}
+ onSelect={handleDialogSelectDistrict}
+ />
+
+ );
+};
+
+export default Cities;