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("Пользователь и связанные отчеты удалены!"); +// } +// } // === УПРАВЛЕНИЕ МАГАЗИНАМИ ===