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 ( +
    +

    Города

    +
    +
    + + +
    + +
    + setShowDistrictDialog(true)} + /> +
    + +
    +
    + +
    + + +
    + {error && ( +
    + {error} +
    + )} +
    +

    Список городов

    + + + + + + + + + + + {cities.map((city) => ( + + + + + + + ))} + +
    IDНазваниеФедеральный округДействия
    {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;