feat: CRUD user added
This commit is contained in:
143
frontend/api.js
143
frontend/api.js
@@ -135,6 +135,8 @@ async function getAllUsers() {
|
||||
}
|
||||
}
|
||||
|
||||
let usersList = [];
|
||||
|
||||
async function loadUsers() {
|
||||
const tbody = document.getElementById("usersTableBody");
|
||||
tbody.innerHTML = "";
|
||||
@@ -149,6 +151,7 @@ async function loadUsers() {
|
||||
}
|
||||
|
||||
const users = result.users;
|
||||
usersList = users;
|
||||
|
||||
users.forEach((user) => {
|
||||
const userStores =
|
||||
@@ -194,3 +197,143 @@ async function loadUsers() {
|
||||
showNotification("Нет пользователей для отображения", "info");
|
||||
}
|
||||
}
|
||||
|
||||
//add user
|
||||
async function createUser(userData) {
|
||||
const token = localStorage.getItem("token");
|
||||
try {
|
||||
const response = await fetch(`${API_BASE_URL}/users`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(userData),
|
||||
});
|
||||
const data = await response.json();
|
||||
if (response.ok) {
|
||||
return { success: true, ...data };
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
data.error ||
|
||||
(data.errors && data.errors[0]?.msg) ||
|
||||
"Ошибка создания пользователя",
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
return { success: false, error: "Нет соединения с сервером" };
|
||||
}
|
||||
}
|
||||
|
||||
//edit user
|
||||
async function updateUser(userId, userData) {
|
||||
const token = localStorage.getItem("token");
|
||||
try {
|
||||
const response = await fetch(`${API_BASE_URL}/users/${userId}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(userData),
|
||||
});
|
||||
const data = await response.json();
|
||||
if (response.ok) {
|
||||
return { success: true };
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
data.error ||
|
||||
(data.errors && data.errors[0]?.msg) ||
|
||||
"Ошибка обновления пользователя",
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
return { success: false, error: "Нет соединения с сервером" };
|
||||
}
|
||||
}
|
||||
|
||||
// 1. Create modal on-demand if missing
|
||||
function ensureConfirmModal() {
|
||||
if (document.getElementById("confirmModal")) return;
|
||||
|
||||
const modal = document.createElement("div");
|
||||
modal.id = "confirmModal";
|
||||
modal.className =
|
||||
"hidden fixed inset-0 z-50 bg-black bg-opacity-30 flex items-center justify-center";
|
||||
modal.innerHTML = `
|
||||
<div class="bg-white rounded-lg shadow-lg p-8 max-w-sm w-full relative">
|
||||
<div id="confirmModalText" class="text-lg text-gray-700 mb-6"></div>
|
||||
<div class="flex justify-end space-x-4">
|
||||
<button id="confirmModalOk" class="px-5 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700">Удалить</button>
|
||||
<button id="confirmModalCancel" class="px-5 py-2 bg-gray-300 text-gray-700 rounded-lg hover:bg-gray-400">Отмена</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
document.body.appendChild(modal);
|
||||
}
|
||||
|
||||
// 2. Show confirm modal
|
||||
function showConfirmModal(message, onConfirm) {
|
||||
ensureConfirmModal();
|
||||
|
||||
const modal = document.getElementById("confirmModal");
|
||||
const text = document.getElementById("confirmModalText");
|
||||
const okBtn = document.getElementById("confirmModalOk");
|
||||
const cancelBtn = document.getElementById("confirmModalCancel");
|
||||
|
||||
text.textContent = message;
|
||||
modal.classList.remove("hidden");
|
||||
|
||||
function cleanup() {
|
||||
modal.classList.add("hidden");
|
||||
okBtn.removeEventListener("click", okHandler);
|
||||
cancelBtn.removeEventListener("click", cancelHandler);
|
||||
}
|
||||
|
||||
function okHandler() {
|
||||
cleanup();
|
||||
onConfirm();
|
||||
}
|
||||
|
||||
function cancelHandler() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
okBtn.addEventListener("click", okHandler);
|
||||
cancelBtn.addEventListener("click", cancelHandler);
|
||||
}
|
||||
|
||||
// 3. API call to delete user
|
||||
async function apiDeleteUser(userId) {
|
||||
const token = localStorage.getItem("token");
|
||||
try {
|
||||
const response = await fetch(`${API_BASE_URL}/users/${userId}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const data = await response.json();
|
||||
if (response.ok) {
|
||||
showNotification("Пользователь удален!");
|
||||
loadUsers();
|
||||
updateDashboard();
|
||||
} else {
|
||||
showNotification(data.error || "Ошибка удаления пользователя", "error");
|
||||
}
|
||||
} catch {
|
||||
showNotification("Нет соединения с сервером", "error");
|
||||
}
|
||||
}
|
||||
|
||||
// 4. UI trigger: delete user with modal
|
||||
function deleteUser(userId) {
|
||||
showConfirmModal("Вы уверены, что хотите удалить этого пользователя?", () =>
|
||||
apiDeleteUser(userId)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -135,6 +135,7 @@ generateTestData();
|
||||
function showNotification(message, type = "success") {
|
||||
const notification = document.getElementById("notification");
|
||||
const notificationText = document.getElementById("notificationText");
|
||||
if (!notification || !notificationText) return;
|
||||
|
||||
notificationText.textContent = message;
|
||||
notification.className = `fixed top-4 right-4 z-50 animate-fade-in`;
|
||||
@@ -1445,45 +1446,39 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
// Редактирование пользователя
|
||||
function editUser(userId) {
|
||||
editingUserId = userId;
|
||||
showUserEditModal();
|
||||
const user = usersList.find((u) => u.id === userId);
|
||||
showUserEditModal(user);
|
||||
}
|
||||
|
||||
// Показ модального окна редактирования пользователя
|
||||
function showUserEditModal() {
|
||||
function showUserEditModal(user) {
|
||||
const modal = document.getElementById("userEditModal");
|
||||
const title = document.getElementById("userModalTitle");
|
||||
const form = document.getElementById("userEditForm");
|
||||
|
||||
if (editingUserId) {
|
||||
const user = database.users.find((u) => u.id === editingUserId);
|
||||
title.textContent = "Редактирование пользователя";
|
||||
document.getElementById("userLogin").value = user.username;
|
||||
document.getElementById("userPassword").value = "";
|
||||
document.getElementById("userRole").value = user.role;
|
||||
} else {
|
||||
title.textContent = "Добавление пользователя";
|
||||
form.reset();
|
||||
}
|
||||
// If editingUserId, it's an edit; else, it's add
|
||||
title.textContent = editingUserId
|
||||
? "Редактирование пользователя"
|
||||
: "Добавление пользователя";
|
||||
|
||||
document.getElementById("userLogin").value = (user && user.username) || "";
|
||||
document.getElementById("userPassword").value = "";
|
||||
document.getElementById("userRole").value = (user && user.role) || "employee";
|
||||
|
||||
// Загрузка чекбоксов магазинов
|
||||
const storesContainer = document.getElementById("userStoresAccess");
|
||||
storesContainer.innerHTML = "";
|
||||
|
||||
database.stores.forEach((store) => {
|
||||
const isChecked = editingUserId
|
||||
? database.users
|
||||
.find((u) => u.id === editingUserId)
|
||||
.stores.includes(store.id)
|
||||
: false;
|
||||
|
||||
const isChecked = user && user.stores && user.stores.includes(store.id);
|
||||
const checkbox = document.createElement("label");
|
||||
checkbox.className = "flex items-center";
|
||||
checkbox.innerHTML = `
|
||||
<input type="checkbox" value="${store.id}" ${
|
||||
<input type="checkbox" value="${store.id}" ${
|
||||
isChecked ? "checked" : ""
|
||||
} class="mr-2">
|
||||
<span>${store.name}</span>
|
||||
`;
|
||||
<span>${store.name}</span>
|
||||
`;
|
||||
storesContainer.appendChild(checkbox);
|
||||
});
|
||||
|
||||
@@ -1506,78 +1501,80 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
}
|
||||
});
|
||||
|
||||
function saveUser() {
|
||||
const login = document.getElementById("userLogin").value;
|
||||
//save user for create and update
|
||||
async function saveUser() {
|
||||
const login = document.getElementById("userLogin").value.trim();
|
||||
const password = document.getElementById("userPassword").value;
|
||||
const role = document.getElementById("userRole").value;
|
||||
const selectedStores = Array.from(
|
||||
document.querySelectorAll(
|
||||
'#userStoresAccess input[type="checkbox"]:checked'
|
||||
)
|
||||
).map((cb) => parseInt(cb.value));
|
||||
|
||||
if (!login) {
|
||||
showNotification("Заполните логин!", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
// Получение выбранных магазинов
|
||||
const selectedStores = [];
|
||||
document
|
||||
.querySelectorAll('#userStoresAccess input[type="checkbox"]:checked')
|
||||
.forEach((cb) => {
|
||||
selectedStores.push(parseInt(cb.value));
|
||||
});
|
||||
// Always build userData
|
||||
const userData = {
|
||||
username: login,
|
||||
role: role,
|
||||
storeIds: selectedStores,
|
||||
};
|
||||
if (password) userData.password = password;
|
||||
|
||||
if (editingUserId) {
|
||||
// Редактирование
|
||||
const userIndex = database.users.findIndex((u) => u.id === editingUserId);
|
||||
database.users[userIndex].username = login;
|
||||
if (password) {
|
||||
database.users[userIndex].password = password;
|
||||
}
|
||||
database.users[userIndex].role = role;
|
||||
database.users[userIndex].stores = selectedStores;
|
||||
|
||||
showNotification("Пользователь обновлен!");
|
||||
} else {
|
||||
// Добавление
|
||||
// Determine CREATE or EDIT
|
||||
let result;
|
||||
if (!editingUserId) {
|
||||
if (!password) {
|
||||
showNotification("Укажите пароль для нового пользователя!", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const newId = Math.max(...database.users.map((u) => u.id)) + 1;
|
||||
database.users.push({
|
||||
id: newId,
|
||||
username: login,
|
||||
password: password,
|
||||
role: role,
|
||||
stores: selectedStores,
|
||||
});
|
||||
|
||||
showNotification("Пользователь добавлен!");
|
||||
// CREATE
|
||||
result = await createUser(userData);
|
||||
if (result.success) {
|
||||
showNotification("Пользователь добавлен!");
|
||||
}
|
||||
} else {
|
||||
// EDIT
|
||||
result = await updateUser(editingUserId, userData);
|
||||
if (result.success) {
|
||||
showNotification("Пользователь обновлен!");
|
||||
}
|
||||
editingUserId = null;
|
||||
}
|
||||
|
||||
hideModal("userEditModal");
|
||||
loadUsers();
|
||||
updateDashboard();
|
||||
// After save: UI update or error
|
||||
if (result && result.success) {
|
||||
hideModal("userEditModal");
|
||||
loadUsers();
|
||||
updateDashboard();
|
||||
} else if (result) {
|
||||
showNotification(result.error || "Ошибка операции", "error");
|
||||
}
|
||||
}
|
||||
|
||||
// Удаление пользователя
|
||||
function deleteUser(userId) {
|
||||
const user = database.users.find((u) => u.id === userId);
|
||||
const userReports = database.reports.filter((r) => r.userId === userId);
|
||||
// function deleteUser(userId) {
|
||||
// const user = database.users.find((u) => u.id === userId);
|
||||
// const userReports = database.reports.filter((r) => r.userId === userId);
|
||||
|
||||
let message = `Вы уверены, что хотите удалить пользователя "${user.username}"?`;
|
||||
if (userReports.length > 0) {
|
||||
message += `\n\nВнимание! У этого пользователя есть ${userReports.length} связанных отчетов. Они также будут удалены.`;
|
||||
}
|
||||
// let message = `Вы уверены, что хотите удалить пользователя "${user.username}"?`;
|
||||
// if (userReports.length > 0) {
|
||||
// message += `\n\nВнимание! У этого пользователя есть ${userReports.length} связанных отчетов. Они также будут удалены.`;
|
||||
// }
|
||||
|
||||
if (confirm(message)) {
|
||||
database.users = database.users.filter((u) => u.id !== userId);
|
||||
database.reports = database.reports.filter((r) => r.userId !== userId);
|
||||
loadUsers();
|
||||
loadReports();
|
||||
updateDashboard();
|
||||
showNotification("Пользователь и связанные отчеты удалены!");
|
||||
}
|
||||
}
|
||||
// if (confirm(message)) {
|
||||
// database.users = database.users.filter((u) => u.id !== userId);
|
||||
// database.reports = database.reports.filter((r) => r.userId !== userId);
|
||||
// loadUsers();
|
||||
// loadReports();
|
||||
// updateDashboard();
|
||||
// showNotification("Пользователь и связанные отчеты удалены!");
|
||||
// }
|
||||
// }
|
||||
|
||||
// === УПРАВЛЕНИЕ МАГАЗИНАМИ ===
|
||||
|
||||
|
||||
Reference in New Issue
Block a user