diff --git a/frontend/api.js b/frontend/api.js
index 279d3e0..4a241b8 100644
--- a/frontend/api.js
+++ b/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 = `
+
+
+
+
+
+
+
+ `;
+ 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)
+ );
+}
diff --git a/frontend/script.js b/frontend/script.js
index 4cca204..64a37cc 100644
--- a/frontend/script.js
+++ b/frontend/script.js
@@ -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 = `
-
- ${store.name}
- `;
+ ${store.name}
+ `;
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("Пользователь и связанные отчеты удалены!");
+// }
+// }
// === УПРАВЛЕНИЕ МАГАЗИНАМИ ===