._.
This commit is contained in:
parent
a33b0615fd
commit
a6f9918c43
@ -10,6 +10,6 @@
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="public/bundle.js"></script>
|
||||
</body>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -5,6 +5,7 @@ import Accessories from "./pages/Accessories.jsx";
|
||||
import PrivateRoute from "./components/PrivateRoute";
|
||||
import Cities from "./pages/Cities.jsx";
|
||||
import FederalDistricts from "./pages/FederalDistricts.jsx";
|
||||
import Roles from "./pages/Roles.jsx";
|
||||
|
||||
const RoutesComponent = () => (
|
||||
<Routes>
|
||||
@ -14,6 +15,7 @@ const RoutesComponent = () => (
|
||||
<Route path="/accessories" element={<Accessories />} />
|
||||
<Route path="/cities" element={<Cities />} />
|
||||
<Route path="/federal_districts" element={<FederalDistricts />} />
|
||||
<Route path="/roles" element={<Roles />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
);
|
||||
|
||||
59
src/api.jsx
59
src/api.jsx
@ -222,3 +222,62 @@ export const deleteFederalDistrict = async (id) => {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const getRoles = async () => {
|
||||
try {
|
||||
const response = await axios.get(`${API_URL}/roles`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${getAuthToken()}`,
|
||||
Accept: "application/json",
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.log("Ошибка при загрузке ролей:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const createRole = async (roleData) => {
|
||||
try {
|
||||
const response = await axios.post(`${API_URL}/roles`, roleData, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${getAuthToken()}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.log("Ошибка при создании роли:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const updateRole = async (id, roleData) => {
|
||||
try {
|
||||
const response = await axios.put(`${API_URL}/roles/${id}`, roleData, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${getAuthToken()}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.log("Ошибка при обновлении роли:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteRole = async (id) => {
|
||||
try {
|
||||
await axios.delete(`${API_URL}/roles/${id}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${getAuthToken()}`,
|
||||
Accept: "application/json",
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("Ошибка при удалении роли:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
@ -18,7 +18,7 @@ const Header = () => {
|
||||
<Link className="navbar-brand" to="/">
|
||||
Логистика
|
||||
</Link>
|
||||
<div className="collapse navbar-collapse">
|
||||
<div className="collapse navbar-collapse" id="navbarNav">
|
||||
<ul className="navbar-nav me-auto">
|
||||
<li className="nav-item">
|
||||
<Link className="nav-link" to="/">
|
||||
@ -40,6 +40,11 @@ const Header = () => {
|
||||
Федеральные округа
|
||||
</Link>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<Link className="nav-link" to="/roles">
|
||||
Роли
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="d-flex align-items-center ml-auto">
|
||||
{isAuthenticated ? (
|
||||
|
||||
154
src/pages/Roles.jsx
Normal file
154
src/pages/Roles.jsx
Normal file
@ -0,0 +1,154 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { getAuthToken } from "../api.jsx";
|
||||
import { getRoles, createRole, updateRole, deleteRole } from "../api.jsx";
|
||||
|
||||
const Roles = () => {
|
||||
const [roles, setRoles] = useState([]);
|
||||
const [newRole, setNewRole] = useState({
|
||||
name: "",
|
||||
});
|
||||
const [editingRoleId, setEditingRoleId] = useState(null);
|
||||
const [error, setError] = useState(null);
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
fetchRoles();
|
||||
}, []);
|
||||
|
||||
const fetchRoles = async () => {
|
||||
try {
|
||||
const data = await getRoles();
|
||||
setRoles(data);
|
||||
} catch (error) {
|
||||
console.error("Ошибка при загрузке ролей:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleInputChange = (e) => {
|
||||
const { name, value } = e.target;
|
||||
setNewRole({ ...newRole, [name]: value });
|
||||
};
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!newRole.name) {
|
||||
setError("Пожалуйста, заполните все поля.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (editingRoleId) {
|
||||
await updateRole(editingRoleId, newRole);
|
||||
} else {
|
||||
await createRole(newRole);
|
||||
}
|
||||
fetchRoles();
|
||||
resetForm();
|
||||
} catch (error) {
|
||||
console.error("Ошибка при добавлении или обновлении роли:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEdit = (role) => {
|
||||
setNewRole({
|
||||
name: role.name,
|
||||
});
|
||||
setEditingRoleId(role.id);
|
||||
};
|
||||
|
||||
const handleDelete = async (roleId) => {
|
||||
try {
|
||||
await deleteRole(roleId);
|
||||
fetchRoles();
|
||||
} catch (error) {
|
||||
console.error("Ошибка при удалении роли:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
setNewRole({
|
||||
name: "",
|
||||
});
|
||||
setEditingRoleId(null);
|
||||
};
|
||||
|
||||
if (getAuthToken() === null) {
|
||||
navigate("/login");
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container mt-4">
|
||||
<h3>Роли</h3>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="form-group">
|
||||
<label htmlFor="roleName">Название роли</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="roleName"
|
||||
name="name"
|
||||
placeholder="Введите название роли"
|
||||
value={newRole.name}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="btn-group">
|
||||
<button type="submit" className="btn btn-primary">
|
||||
{editingRoleId ? "Обновить" : "Создать"}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary"
|
||||
onClick={resetForm}
|
||||
>
|
||||
Отменить
|
||||
</button>
|
||||
</div>
|
||||
{error && (
|
||||
<div className="alert alert-danger mt-3" role="alert">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
<h3 className="mt-5">Список ролей</h3>
|
||||
<table className="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Название</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{roles.map((role) => (
|
||||
<tr key={role.id}>
|
||||
<td>{role.id}</td>
|
||||
<td>{role.name}</td>
|
||||
<td>
|
||||
<div className="btn-group">
|
||||
<button
|
||||
className="btn btn-warning"
|
||||
onClick={() => handleEdit(role)}
|
||||
>
|
||||
Изменить
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-danger"
|
||||
onClick={() => handleDelete(role.id)}
|
||||
>
|
||||
Удалить
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Roles;
|
||||
Loading…
x
Reference in New Issue
Block a user